diff --git a/README.md b/README.md index b8f55c19bd..213580a5e2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev) [![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) -:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md) | [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es/project/README.md) +:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md) | [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es/project/README.md) | [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR/project/README.md) The Electron framework lets you write cross-platform desktop applications using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and @@ -75,7 +75,7 @@ forums - [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)* - [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)* - [`electron-jp`](https://electron-jp.slack.com) *(Japanese)* -- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)* +- [`electron-tr`](https://electron-tr.slack.com) *(Turkish)* - [`electron-id`](https://electron-id.slack.com) *(Indonesia)* Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) diff --git a/atom/browser/api/atom_api_auto_updater.cc b/atom/browser/api/atom_api_auto_updater.cc index 276d889006..ea3024191e 100644 --- a/atom/browser/api/atom_api_auto_updater.cc +++ b/atom/browser/api/atom_api_auto_updater.cc @@ -87,16 +87,14 @@ void AutoUpdater::SetFeedURL(const std::string& url, mate::Arguments* args) { void AutoUpdater::QuitAndInstall() { // If we don't have any window then quitAndInstall immediately. - WindowList* window_list = WindowList::GetInstance(); - if (window_list->empty()) { + if (WindowList::IsEmpty()) { auto_updater::AutoUpdater::QuitAndInstall(); return; } // Otherwise do the restart after all windows have been closed. - window_list->AddObserver(this); - for (NativeWindow* window : *window_list) - window->Close(); + WindowList::AddObserver(this); + WindowList::CloseAllWindows(); } // static diff --git a/atom/browser/api/atom_api_browser_view.cc b/atom/browser/api/atom_api_browser_view.cc new file mode 100644 index 0000000000..dc17fce9e9 --- /dev/null +++ b/atom/browser/api/atom_api_browser_view.cc @@ -0,0 +1,162 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/atom_api_browser_view.h" + +#include "atom/browser/api/atom_api_web_contents.h" +#include "atom/browser/browser.h" +#include "atom/browser/native_browser_view.h" +#include "atom/common/color_util.h" +#include "atom/common/native_mate_converters/gfx_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" +#include "atom/common/node_includes.h" +#include "atom/common/options_switches.h" +#include "native_mate/constructor.h" +#include "native_mate/dictionary.h" +#include "ui/gfx/geometry/rect.h" + +namespace mate { + +template <> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + atom::AutoResizeFlags* auto_resize_flags) { + mate::Dictionary params; + if (!ConvertFromV8(isolate, val, ¶ms)) { + return false; + } + + uint8_t flags = 0; + bool width = false; + if (params.Get("width", &width) && width) { + flags |= atom::kAutoResizeWidth; + } + bool height = false; + if (params.Get("height", &height) && height) { + flags |= atom::kAutoResizeHeight; + } + + *auto_resize_flags = static_cast(flags); + return true; + } +}; + +} // namespace mate + +namespace atom { + +namespace api { + +BrowserView::BrowserView(v8::Isolate* isolate, + v8::Local wrapper, + const mate::Dictionary& options) + : api_web_contents_(nullptr) { + Init(isolate, wrapper, options); +} + +void BrowserView::Init(v8::Isolate* isolate, + v8::Local wrapper, + const mate::Dictionary& options) { + mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate); + options.Get(options::kWebPreferences, &web_preferences); + web_preferences.Set("isBrowserView", true); + mate::Handle web_contents = + WebContents::Create(isolate, web_preferences); + + web_contents_.Reset(isolate, web_contents.ToV8()); + api_web_contents_ = web_contents.get(); + + view_.reset(NativeBrowserView::Create( + api_web_contents_->managed_web_contents()->GetView())); + + InitWith(isolate, wrapper); +} + +BrowserView::~BrowserView() { + api_web_contents_->DestroyWebContents(); +} + +// static +mate::WrappableBase* BrowserView::New(mate::Arguments* args) { + if (!Browser::Get()->is_ready()) { + args->ThrowError("Cannot create BrowserView before app is ready"); + return nullptr; + } + + if (args->Length() > 1) { + args->ThrowError("Too many arguments"); + return nullptr; + } + + mate::Dictionary options; + if (!(args->Length() == 1 && args->GetNext(&options))) { + options = mate::Dictionary::CreateEmpty(args->isolate()); + } + + return new BrowserView(args->isolate(), args->GetThis(), options); +} + +int32_t BrowserView::ID() const { + return weak_map_id(); +} + +void BrowserView::SetAutoResize(AutoResizeFlags flags) { + view_->SetAutoResizeFlags(flags); +} + +void BrowserView::SetBounds(const gfx::Rect& bounds) { + view_->SetBounds(bounds); +} + +void BrowserView::SetBackgroundColor(const std::string& color_name) { + view_->SetBackgroundColor(ParseHexColor(color_name)); +} + +v8::Local BrowserView::WebContents() { + if (web_contents_.IsEmpty()) { + return v8::Null(isolate()); + } + + return v8::Local::New(isolate(), web_contents_); +} + +// static +void BrowserView::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "BrowserView")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) + .MakeDestroyable() + .SetMethod("setAutoResize", &BrowserView::SetAutoResize) + .SetMethod("setBounds", &BrowserView::SetBounds) + .SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor) + .SetProperty("webContents", &BrowserView::WebContents) + .SetProperty("id", &BrowserView::ID); +} + +} // namespace api + +} // namespace atom + +namespace { + +using atom::api::BrowserView; + +void Initialize(v8::Local exports, + v8::Local unused, + v8::Local context, + void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + BrowserView::SetConstructor(isolate, base::Bind(&BrowserView::New)); + + mate::Dictionary browser_view( + isolate, BrowserView::GetConstructor(isolate)->GetFunction()); + + mate::Dictionary dict(isolate, exports); + dict.Set("BrowserView", browser_view); +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_browser_view, Initialize) diff --git a/atom/browser/api/atom_api_browser_view.h b/atom/browser/api/atom_api_browser_view.h new file mode 100644 index 0000000000..7531cfcc4a --- /dev/null +++ b/atom/browser/api/atom_api_browser_view.h @@ -0,0 +1,72 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_ +#define ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_ + +#include +#include + +#include "atom/browser/api/trackable_object.h" +#include "atom/browser/native_browser_view.h" +#include "native_mate/handle.h" + +namespace gfx { +class Rect; +} + +namespace mate { +class Arguments; +class Dictionary; +} // namespace mate + +namespace atom { + +class NativeBrowserView; + +namespace api { + +class WebContents; + +class BrowserView : public mate::TrackableObject { + public: + static mate::WrappableBase* New(mate::Arguments* args); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + + NativeBrowserView* view() const { return view_.get(); } + + int32_t ID() const; + + protected: + BrowserView(v8::Isolate* isolate, + v8::Local wrapper, + const mate::Dictionary& options); + ~BrowserView() override; + + private: + void Init(v8::Isolate* isolate, + v8::Local wrapper, + const mate::Dictionary& options); + + void SetAutoResize(AutoResizeFlags flags); + void SetBounds(const gfx::Rect& bounds); + void SetBackgroundColor(const std::string& color_name); + + v8::Local WebContents(); + + v8::Global web_contents_; + class WebContents* api_web_contents_; + + std::unique_ptr view_; + + DISALLOW_COPY_AND_ASSIGN(BrowserView); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_ diff --git a/atom/browser/api/atom_api_dialog.cc b/atom/browser/api/atom_api_dialog.cc index cc849e026e..cb9f17f704 100644 --- a/atom/browser/api/atom_api_dialog.cc +++ b/atom/browser/api/atom_api_dialog.cc @@ -8,11 +8,13 @@ #include "atom/browser/api/atom_api_window.h" #include "atom/browser/native_window.h" +#include "atom/browser/ui/certificate_trust.h" #include "atom/browser/ui/file_dialog.h" #include "atom/browser/ui/message_box.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/image_converter.h" +#include "atom/common/native_mate_converters/net_converter.h" #include "native_mate/dictionary.h" #include "atom/common/node_includes.h" @@ -127,6 +129,10 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("showErrorBox", &atom::ShowErrorBox); dict.SetMethod("showOpenDialog", &ShowOpenDialog); dict.SetMethod("showSaveDialog", &ShowSaveDialog); +#if defined(OS_MACOSX) + dict.SetMethod("showCertificateTrustDialog", + &certificate_trust::ShowCertificateTrust); +#endif } } // namespace diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index b9692c228e..b2c4c9b09b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -189,6 +189,7 @@ struct Converter { switch (val) { case Type::BACKGROUND_PAGE: type = "backgroundPage"; break; case Type::BROWSER_WINDOW: type = "window"; break; + case Type::BROWSER_VIEW: type = "browserView"; break; case Type::REMOTE: type = "remote"; break; case Type::WEB_VIEW: type = "webview"; break; case Type::OFF_SCREEN: type = "offscreen"; break; @@ -203,10 +204,12 @@ struct Converter { std::string type; if (!ConvertFromV8(isolate, val, &type)) return false; - if (type == "webview") { - *out = Type::WEB_VIEW; - } else if (type == "backgroundPage") { + if (type == "backgroundPage") { *out = Type::BACKGROUND_PAGE; + } else if (type == "browserView") { + *out = Type::BROWSER_VIEW; + } else if (type == "webview") { + *out = Type::WEB_VIEW; } else if (type == "offscreen") { *out = Type::OFF_SCREEN; } else { @@ -307,6 +310,8 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options) type_ = WEB_VIEW; else if (options.Get("isBackgroundPage", &b) && b) type_ = BACKGROUND_PAGE; + else if (options.Get("isBrowserView", &b) && b) + type_ = BROWSER_VIEW; else if (options.Get("offscreen", &b) && b) type_ = OFF_SCREEN; diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index c289503b43..1301ed15f7 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -53,10 +53,11 @@ class WebContents : public mate::TrackableObject, public: enum Type { BACKGROUND_PAGE, // A DevTools extension background page. - BROWSER_WINDOW, // Used by BrowserWindow. - REMOTE, // Thin wrap around an existing WebContents. - WEB_VIEW, // Used by . - OFF_SCREEN, // Used for offscreen rendering + BROWSER_WINDOW, // Used by BrowserWindow. + BROWSER_VIEW, // Used by BrowserView. + REMOTE, // Thin wrap around an existing WebContents. + WEB_VIEW, // Used by . + OFF_SCREEN, // Used for offscreen rendering }; // For node.js callback function type: function(error, buffer) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 6748c9c0dd..c670762491 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -5,6 +5,7 @@ #include "atom/browser/api/atom_api_window.h" #include "atom/common/native_mate_converters/value_converter.h" +#include "atom/browser/api/atom_api_browser_view.h" #include "atom/browser/api/atom_api_menu.h" #include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/browser.h" @@ -816,6 +817,25 @@ std::vector> Window::GetChildWindows() const { return child_windows_.Values(isolate()); } +v8::Local Window::GetBrowserView() const { + if (browser_view_.IsEmpty()) { + return v8::Null(isolate()); + } + + return v8::Local::New(isolate(), browser_view_); +} + +void Window::SetBrowserView(v8::Local value) { + mate::Handle browser_view; + if (value->IsNull()) { + window_->SetBrowserView(nullptr); + browser_view_.Reset(); + } else if (mate::ConvertFromV8(isolate(), value, &browser_view)) { + window_->SetBrowserView(browser_view->view()); + browser_view_.Reset(isolate(), value); + } +} + bool Window::IsModal() const { return window_->is_modal(); } @@ -853,15 +873,20 @@ void Window::RefreshTouchBarItem(const std::string& item_id) { window_->RefreshTouchBarItem(item_id); } +void Window::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { + window_->SetEscapeTouchBarItem(item); +} + int32_t Window::ID() const { return weak_map_id(); } v8::Local Window::WebContents(v8::Isolate* isolate) { - if (web_contents_.IsEmpty()) + if (web_contents_.IsEmpty()) { return v8::Null(isolate); - else - return v8::Local::New(isolate, web_contents_); + } + + return v8::Local::New(isolate, web_contents_); } void Window::RemoveFromParentChildWindows() { @@ -906,6 +931,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, #endif .SetMethod("getParentWindow", &Window::GetParentWindow) .SetMethod("getChildWindows", &Window::GetChildWindows) + .SetMethod("getBrowserView", &Window::GetBrowserView) + .SetMethod("setBrowserView", &Window::SetBrowserView) .SetMethod("isModal", &Window::IsModal) .SetMethod("getNativeWindowHandle", &Window::GetNativeWindowHandle) .SetMethod("getBounds", &Window::GetBounds) @@ -975,6 +1002,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("setVibrancy", &Window::SetVibrancy) .SetMethod("_setTouchBarItems", &Window::SetTouchBar) .SetMethod("_refreshTouchBarItem", &Window::RefreshTouchBarItem) + .SetMethod("_setEscapeTouchBarItem", &Window::SetEscapeTouchBarItem) #if defined(OS_WIN) .SetMethod("hookWindowMessage", &Window::HookWindowMessage) .SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index f30baf79d4..d464af58ea 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -180,6 +180,8 @@ class Window : public mate::TrackableObject, void SetParentWindow(v8::Local value, mate::Arguments* args); v8::Local GetParentWindow() const; std::vector> GetChildWindows() const; + v8::Local GetBrowserView() const; + void SetBrowserView(v8::Local value); bool IsModal() const; v8::Local GetNativeWindowHandle(); @@ -208,6 +210,7 @@ class Window : public mate::TrackableObject, void SetVibrancy(mate::Arguments* args); void SetTouchBar(const std::vector& items); void RefreshTouchBarItem(const std::string& item_id); + void SetEscapeTouchBarItem(const mate::PersistentDictionary& item); v8::Local WebContents(v8::Isolate* isolate); @@ -219,6 +222,7 @@ class Window : public mate::TrackableObject, MessageCallbackMap messages_callback_map_; #endif + v8::Global browser_view_; v8::Global web_contents_; v8::Global menu_; v8::Global parent_window_; diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index b18ab7b70f..b2900a326f 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -43,11 +43,10 @@ void Browser::Quit() { if (!is_quiting_) return; - atom::WindowList* window_list = atom::WindowList::GetInstance(); - if (window_list->empty()) + if (atom::WindowList::IsEmpty()) NotifyAndShutdown(); - - window_list->CloseAllWindows(); + else + atom::WindowList::CloseAllWindows(); } void Browser::Exit(mate::Arguments* args) { @@ -65,14 +64,12 @@ void Browser::Exit(mate::Arguments* args) { is_exiting_ = true; // Must destroy windows before quitting, otherwise bad things can happen. - atom::WindowList* window_list = atom::WindowList::GetInstance(); - if (window_list->empty()) { + if (atom::WindowList::IsEmpty()) { Shutdown(); } else { // Unlike Quit(), we do not ask to close window, but destroy the window // without asking. - for (NativeWindow* window : *window_list) - window->CloseContents(nullptr); // e.g. Destroy() + atom::WindowList::DestroyAllWindows(); } } } diff --git a/atom/browser/browser_linux.cc b/atom/browser/browser_linux.cc index 4dd799dfaf..f569040a21 100644 --- a/atom/browser/browser_linux.cc +++ b/atom/browser/browser_linux.cc @@ -16,9 +16,7 @@ namespace atom { void Browser::Focus() { // Focus on the first visible window. - WindowList* list = WindowList::GetInstance(); - for (WindowList::iterator iter = list->begin(); iter != list->end(); ++iter) { - NativeWindow* window = *iter; + for (const auto& window : WindowList::GetWindows()) { if (window->IsVisible()) { window->Focus(true); break; diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 51604e377c..38a0a003d9 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -204,9 +204,8 @@ std::string Browser::DockGetBadgeText() { } void Browser::DockHide() { - WindowList* list = WindowList::GetInstance(); - for (WindowList::iterator it = list->begin(); it != list->end(); ++it) - [(*it)->GetNativeWindow() setCanHide:NO]; + for (const auto& window : WindowList::GetWindows()) + [window->GetNativeWindow() setCanHide:NO]; ProcessSerialNumber psn = { 0, kCurrentProcess }; TransformProcessType(&psn, kProcessTransformToUIElementApplication); diff --git a/atom/browser/browser_win.cc b/atom/browser/browser_win.cc index 50a9f9da33..ac0f713c88 100644 --- a/atom/browser/browser_win.cc +++ b/atom/browser/browser_win.cc @@ -61,11 +61,11 @@ bool GetProtocolLaunchPath(mate::Arguments* args, base::string16* exe) { // Read in optional args arg std::vector launch_args; if (args->GetNext(&launch_args) && !launch_args.empty()) - *exe = base::StringPrintf(L"\"%s\" %s \"%%1\"", + *exe = base::StringPrintf(L"\"%ls\" %ls \"%%1\"", exe->c_str(), base::JoinString(launch_args, L" ").c_str()); else - *exe = base::StringPrintf(L"\"%s\" \"%%1\"", exe->c_str()); + *exe = base::StringPrintf(L"\"%ls\" \"%%1\"", exe->c_str()); return true; } @@ -76,8 +76,7 @@ bool FormatCommandLineString(base::string16* exe, } if (!launch_args.empty()) { - base::string16 formatString = L"%s %s"; - *exe = base::StringPrintf(formatString.c_str(), + *exe = base::StringPrintf(L"%ls %ls", exe->c_str(), base::JoinString(launch_args, L" ").c_str()); } diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index f7f9e46250..a10f959dce 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -178,9 +178,14 @@ void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) { void CommonWebContentsDelegate::SetOwnerWindow( content::WebContents* web_contents, NativeWindow* owner_window) { - owner_window_ = owner_window->GetWeakPtr(); + owner_window_ = owner_window ? owner_window->GetWeakPtr() : nullptr; NativeWindowRelay* relay = new NativeWindowRelay(owner_window_); - web_contents->SetUserData(relay->key, relay); + if (owner_window) { + web_contents->SetUserData(relay->key, relay); + } else { + web_contents->RemoveUserData(relay->key); + delete relay; + } } void CommonWebContentsDelegate::ResetManagedWebContents() { diff --git a/atom/browser/native_browser_view.cc b/atom/browser/native_browser_view.cc new file mode 100644 index 0000000000..949e5e9ec9 --- /dev/null +++ b/atom/browser/native_browser_view.cc @@ -0,0 +1,18 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/native_browser_view.h" + +#include "atom/browser/api/atom_api_web_contents.h" +#include "brightray/browser/inspectable_web_contents_view.h" + +namespace atom { + +NativeBrowserView::NativeBrowserView( + brightray::InspectableWebContentsView* web_contents_view) + : web_contents_view_(web_contents_view) {} + +NativeBrowserView::~NativeBrowserView() {} + +} // namespace atom diff --git a/atom/browser/native_browser_view.h b/atom/browser/native_browser_view.h new file mode 100644 index 0000000000..4216cc1e34 --- /dev/null +++ b/atom/browser/native_browser_view.h @@ -0,0 +1,57 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NATIVE_BROWSER_VIEW_H_ +#define ATOM_BROWSER_NATIVE_BROWSER_VIEW_H_ + +#include "base/macros.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace brightray { +class InspectableWebContentsView; +} + +namespace gfx { +class Rect; +} + +namespace atom { + +namespace api { +class WebContents; +} + +enum AutoResizeFlags { + kAutoResizeWidth = 0x1, + kAutoResizeHeight = 0x2, +}; + +class NativeBrowserView { + public: + virtual ~NativeBrowserView(); + + static NativeBrowserView* Create( + brightray::InspectableWebContentsView* web_contents_view); + + brightray::InspectableWebContentsView* GetInspectableWebContentsView() { + return web_contents_view_; + } + + virtual void SetAutoResizeFlags(uint8_t flags) = 0; + virtual void SetBounds(const gfx::Rect& bounds) = 0; + virtual void SetBackgroundColor(SkColor color) = 0; + + protected: + explicit NativeBrowserView( + brightray::InspectableWebContentsView* web_contents_view); + + brightray::InspectableWebContentsView* web_contents_view_; + + private: + DISALLOW_COPY_AND_ASSIGN(NativeBrowserView); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NATIVE_BROWSER_VIEW_H_ diff --git a/atom/browser/native_browser_view_mac.h b/atom/browser/native_browser_view_mac.h new file mode 100644 index 0000000000..4e7aa429ce --- /dev/null +++ b/atom/browser/native_browser_view_mac.h @@ -0,0 +1,30 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NATIVE_BROWSER_VIEW_MAC_H_ +#define ATOM_BROWSER_NATIVE_BROWSER_VIEW_MAC_H_ + +#import + +#include "atom/browser/native_browser_view.h" + +namespace atom { + +class NativeBrowserViewMac : public NativeBrowserView { + public: + explicit NativeBrowserViewMac( + brightray::InspectableWebContentsView* web_contents_view); + ~NativeBrowserViewMac() override; + + void SetAutoResizeFlags(uint8_t flags) override; + void SetBounds(const gfx::Rect& bounds) override; + void SetBackgroundColor(SkColor color) override; + + private: + DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewMac); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NATIVE_BROWSER_VIEW_MAC_H_ diff --git a/atom/browser/native_browser_view_mac.mm b/atom/browser/native_browser_view_mac.mm new file mode 100644 index 0000000000..2ce2adc1f4 --- /dev/null +++ b/atom/browser/native_browser_view_mac.mm @@ -0,0 +1,60 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/native_browser_view_mac.h" + +#include "brightray/browser/inspectable_web_contents_view.h" +#include "skia/ext/skia_utils_mac.h" +#include "ui/gfx/geometry/rect.h" + +// Match view::Views behavior where the view sticks to the top-left origin. +const NSAutoresizingMaskOptions kDefaultAutoResizingMask = + NSViewMaxXMargin | NSViewMinYMargin; + +namespace atom { + +NativeBrowserViewMac::NativeBrowserViewMac( + brightray::InspectableWebContentsView* web_contents_view) + : NativeBrowserView(web_contents_view) { + auto* view = GetInspectableWebContentsView()->GetNativeView(); + view.autoresizingMask = kDefaultAutoResizingMask; +} + +NativeBrowserViewMac::~NativeBrowserViewMac() {} + +void NativeBrowserViewMac::SetAutoResizeFlags(uint8_t flags) { + NSAutoresizingMaskOptions autoresizing_mask = kDefaultAutoResizingMask; + if (flags & kAutoResizeWidth) { + autoresizing_mask |= NSViewWidthSizable; + } + if (flags & kAutoResizeHeight) { + autoresizing_mask |= NSViewHeightSizable; + } + + auto* view = GetInspectableWebContentsView()->GetNativeView(); + view.autoresizingMask = autoresizing_mask; +} + +void NativeBrowserViewMac::SetBounds(const gfx::Rect& bounds) { + auto* view = GetInspectableWebContentsView()->GetNativeView(); + auto* superview = view.superview; + const auto superview_height = superview ? superview.frame.size.height : 0; + view.frame = + NSMakeRect(bounds.x(), superview_height - bounds.y() - bounds.height(), + bounds.width(), bounds.height()); +} + +void NativeBrowserViewMac::SetBackgroundColor(SkColor color) { + auto* view = GetInspectableWebContentsView()->GetNativeView(); + view.wantsLayer = YES; + view.layer.backgroundColor = skia::CGColorCreateFromSkColor(color); +} + +// static +NativeBrowserView* NativeBrowserView::Create( + brightray::InspectableWebContentsView* web_contents_view) { + return new NativeBrowserViewMac(web_contents_view); +} + +} // namespace atom diff --git a/atom/browser/native_browser_view_views.cc b/atom/browser/native_browser_view_views.cc new file mode 100644 index 0000000000..08a8123bca --- /dev/null +++ b/atom/browser/native_browser_view_views.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/native_browser_view_views.h" + +#include "brightray/browser/inspectable_web_contents_view.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/views/background.h" +#include "ui/views/view.h" + +namespace atom { + +NativeBrowserViewViews::NativeBrowserViewViews( + brightray::InspectableWebContentsView* web_contents_view) + : NativeBrowserView(web_contents_view) {} + +NativeBrowserViewViews::~NativeBrowserViewViews() {} + +void NativeBrowserViewViews::SetBounds(const gfx::Rect& bounds) { + auto* view = GetInspectableWebContentsView()->GetView(); + view->SetBoundsRect(bounds); +} + +void NativeBrowserViewViews::SetBackgroundColor(SkColor color) { + auto* view = GetInspectableWebContentsView()->GetView(); + view->set_background(views::Background::CreateSolidBackground(color)); +} + +// static +NativeBrowserView* NativeBrowserView::Create( + brightray::InspectableWebContentsView* web_contents_view) { + return new NativeBrowserViewViews(web_contents_view); +} + +} // namespace atom diff --git a/atom/browser/native_browser_view_views.h b/atom/browser/native_browser_view_views.h new file mode 100644 index 0000000000..5dcda13447 --- /dev/null +++ b/atom/browser/native_browser_view_views.h @@ -0,0 +1,33 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NATIVE_BROWSER_VIEW_VIEWS_H_ +#define ATOM_BROWSER_NATIVE_BROWSER_VIEW_VIEWS_H_ + +#include "atom/browser/native_browser_view.h" + +namespace atom { + +class NativeBrowserViewViews : public NativeBrowserView { + public: + explicit NativeBrowserViewViews( + brightray::InspectableWebContentsView* web_contents_view); + ~NativeBrowserViewViews() override; + + uint8_t GetAutoResizeFlags() { return auto_resize_flags_; } + void SetAutoResizeFlags(uint8_t flags) override { + auto_resize_flags_ = flags; + } + void SetBounds(const gfx::Rect& bounds) override; + void SetBackgroundColor(SkColor color) override; + + private: + uint8_t auto_resize_flags_; + + DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewViews); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NATIVE_BROWSER_VIEW_VIEWS_H_ diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 90a823f80b..316cc8dc2e 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -104,8 +104,7 @@ NativeWindow::~NativeWindow() { // static NativeWindow* NativeWindow::FromWebContents( content::WebContents* web_contents) { - WindowList& window_list = *WindowList::GetInstance(); - for (NativeWindow* window : window_list) { + for (const auto& window : WindowList::GetWindows()) { if (window->web_contents() == web_contents) return window; } @@ -347,6 +346,10 @@ void NativeWindow::SetTouchBar( void NativeWindow::RefreshTouchBarItem(const std::string& item_id) { } +void NativeWindow::SetEscapeTouchBarItem( + const mate::PersistentDictionary& item) { +} + void NativeWindow::FocusOnWebView() { web_contents()->GetRenderViewHost()->GetWidget()->Focus(); } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 941f5849a6..56702daef6 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -47,6 +47,8 @@ class Dictionary; namespace atom { +class NativeBrowserView; + struct DraggableRegion; class NativeWindow : public base::SupportsUserData, @@ -144,6 +146,7 @@ class NativeWindow : public base::SupportsUserData, virtual void SetFocusable(bool focusable); virtual void SetMenu(AtomMenuModel* menu); virtual void SetParentWindow(NativeWindow* parent); + virtual void SetBrowserView(NativeBrowserView* browser_view) = 0; virtual gfx::NativeWindow GetNativeWindow() = 0; virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0; @@ -174,6 +177,7 @@ class NativeWindow : public base::SupportsUserData, virtual void SetTouchBar( const std::vector& items); virtual void RefreshTouchBarItem(const std::string& item_id); + virtual void SetEscapeTouchBarItem(const mate::PersistentDictionary& item); // Webview APIs. virtual void FocusOnWebView(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index bd34993fb1..af0f157eca 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -87,6 +87,7 @@ class NativeWindowMac : public NativeWindow, bool IsDocumentEdited() override; void SetIgnoreMouseEvents(bool ignore) override; void SetContentProtection(bool enable) override; + void SetBrowserView(NativeBrowserView* browser_view) override; void SetParentWindow(NativeWindow* parent) override; gfx::NativeWindow GetNativeWindow() override; gfx::AcceleratedWidget GetAcceleratedWidget() override; @@ -103,6 +104,7 @@ class NativeWindowMac : public NativeWindow, void SetTouchBar( const std::vector& items) override; void RefreshTouchBarItem(const std::string& item_id) override; + void SetEscapeTouchBarItem(const mate::PersistentDictionary& item) override; // content::RenderWidgetHost::InputEventObserver: void OnInputEvent(const blink::WebInputEvent& event) override; @@ -163,6 +165,8 @@ class NativeWindowMac : public NativeWindow, // The view that will fill the whole frameless window. base::scoped_nsobject content_view_; + NativeBrowserView* browser_view_; + std::vector draggable_regions_; bool is_kiosk_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 621e786ddc..b695f8eafa 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -7,6 +7,7 @@ #include #include +#include "atom/browser/native_browser_view_mac.h" #include "atom/browser/ui/cocoa/atom_touch_bar.h" #include "atom/browser/window_list.h" #include "atom/common/color_util.h" @@ -19,9 +20,9 @@ #include "brightray/browser/inspectable_web_contents_view.h" #include "brightray/browser/mac/event_dispatching_window.h" #include "content/public/browser/browser_accessibility_state.h" -#include "content/public/browser/web_contents.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" #include "native_mate/dictionary.h" #include "skia/ext/skia_utils_mac.h" #include "third_party/skia/include/core/SkRegion.h" @@ -368,6 +369,7 @@ enum { - (void)enableWindowButtonsOffset; - (void)resetTouchBar:(const std::vector&)settings; - (void)refreshTouchBarItem:(const std::string&)item_id; +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item; @end @@ -410,6 +412,11 @@ enum { return nil; } +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item { + if (atom_touch_bar_ && self.touchBar) + [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:self.touchBar]; +} + // NSWindow overrides. - (void)swipeWithEvent:(NSEvent *)event { @@ -665,6 +672,7 @@ NativeWindowMac::NativeWindowMac( const mate::Dictionary& options, NativeWindow* parent) : NativeWindow(web_contents, options, parent), + browser_view_(nullptr), is_kiosk_(false), was_fullscreen_(false), zoom_to_page_width_(false), @@ -1263,6 +1271,26 @@ void NativeWindowMac::SetContentProtection(bool enable) { : NSWindowSharingReadOnly]; } +void NativeWindowMac::SetBrowserView(NativeBrowserView* browser_view) { + if (browser_view_) { + [browser_view_->GetInspectableWebContentsView()->GetNativeView() + removeFromSuperview]; + browser_view_ = nullptr; + } + + if (!browser_view) { + return; + } + + browser_view_ = browser_view; + auto* native_view = + browser_view->GetInspectableWebContentsView()->GetNativeView(); + [[window_ contentView] addSubview:native_view + positioned:NSWindowAbove + relativeTo:nil]; + native_view.hidden = NO; +} + void NativeWindowMac::SetParentWindow(NativeWindow* parent) { if (is_modal()) return; @@ -1417,6 +1445,10 @@ void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) { [window_ refreshTouchBarItem:item_id]; } +void NativeWindowMac::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { + [window_ setEscapeTouchBarItem:item]; +} + void NativeWindowMac::OnInputEvent(const blink::WebInputEvent& event) { switch (event.type) { case blink::WebInputEvent::GestureScrollBegin: diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index b0722cbc4a..7e6f23947c 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -7,8 +7,8 @@ #include #include +#include "atom/browser/native_browser_view_views.h" #include "atom/browser/ui/views/menu_bar.h" -#include "atom/browser/ui/views/menu_layout.h" #include "atom/browser/window_list.h" #include "atom/common/color_util.h" #include "atom/common/draggable_region.h" @@ -135,6 +135,7 @@ NativeWindowViews::NativeWindowViews( : NativeWindow(web_contents, options, parent), window_(new views::Widget), web_view_(inspectable_web_contents()->GetView()->GetView()), + browser_view_(nullptr), menu_bar_autohide_(false), menu_bar_visible_(false), menu_bar_alt_pressed_(false), @@ -274,9 +275,6 @@ NativeWindowViews::NativeWindowViews( SetWindowType(GetAcceleratedWidget(), window_type); #endif - // Add web view. - SetLayoutManager(new MenuLayout(this, kMenuBarHeight)); - AddChildView(web_view_); #if defined(OS_WIN) @@ -881,6 +879,24 @@ void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) { Layout(); } +void NativeWindowViews::SetBrowserView(NativeBrowserView* browser_view) { + if (browser_view_) { + web_view_->RemoveChildView( + browser_view_->GetInspectableWebContentsView()->GetView()); + browser_view_ = nullptr; + } + + if (!browser_view) { + return; + } + + // Add as child of the main web view to avoid (0, 0) origin from overlapping + // with menu bar. + browser_view_ = browser_view; + web_view_->AddChildView( + browser_view->GetInspectableWebContentsView()->GetView()); +} + void NativeWindowViews::SetParentWindow(NativeWindow* parent) { NativeWindow::SetParentWindow(parent); @@ -1248,6 +1264,43 @@ void NativeWindowViews::HandleKeyboardEvent( } } +void NativeWindowViews::Layout() { + const auto size = GetContentsBounds().size(); + const auto menu_bar_bounds = + menu_bar_visible_ ? gfx::Rect(0, 0, size.width(), kMenuBarHeight) + : gfx::Rect(); + if (menu_bar_) { + menu_bar_->SetBoundsRect(menu_bar_bounds); + } + + const auto old_web_view_size = web_view_ ? web_view_->size() : gfx::Size(); + if (web_view_) { + web_view_->SetBoundsRect( + gfx::Rect(0, menu_bar_bounds.height(), size.width(), + size.height() - menu_bar_bounds.height())); + } + const auto new_web_view_size = web_view_ ? web_view_->size() : gfx::Size(); + + if (browser_view_) { + const auto flags = static_cast(browser_view_) + ->GetAutoResizeFlags(); + int width_delta = 0; + int height_delta = 0; + if (flags & kAutoResizeWidth) { + width_delta = new_web_view_size.width() - old_web_view_size.width(); + } + if (flags & kAutoResizeHeight) { + height_delta = new_web_view_size.height() - old_web_view_size.height(); + } + + auto* view = browser_view_->GetInspectableWebContentsView()->GetView(); + auto new_view_size = view->size(); + new_view_size.set_width(new_view_size.width() + width_delta); + new_view_size.set_height(new_view_size.height() + height_delta); + view->SetSize(new_view_size); + } +} + gfx::Size NativeWindowViews::GetMinimumSize() { return NativeWindow::GetMinimumSize(); } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index a7f02fb272..276cd4adde 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -104,6 +104,7 @@ class NativeWindowViews : public NativeWindow, void SetContentProtection(bool enable) override; void SetFocusable(bool focusable) override; void SetMenu(AtomMenuModel* menu_model) override; + void SetBrowserView(NativeBrowserView* browser_view) override; void SetParentWindow(NativeWindow* parent) override; gfx::NativeWindow GetNativeWindow() override; void SetOverlayIcon(const gfx::Image& overlay, @@ -176,6 +177,7 @@ class NativeWindowViews : public NativeWindow, const content::NativeWebKeyboardEvent& event) override; // views::View: + void Layout() override; gfx::Size GetMinimumSize() override; gfx::Size GetMaximumSize() override; bool AcceleratorPressed(const ui::Accelerator& accelerator) override; @@ -189,6 +191,8 @@ class NativeWindowViews : public NativeWindow, std::unique_ptr window_; views::View* web_view_; // Managed by inspectable_web_contents_. + NativeBrowserView* browser_view_; + std::unique_ptr menu_bar_; bool menu_bar_autohide_; bool menu_bar_visible_; diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 6fc30bf6a3..5509969014 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 1.6.5 + 1.6.6 CFBundleShortVersionString - 1.6.5 + 1.6.6 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.manifest b/atom/browser/resources/win/atom.manifest index 64c07ded17..7608ffb20f 100644 --- a/atom/browser/resources/win/atom.manifest +++ b/atom/browser/resources/win/atom.manifest @@ -32,7 +32,7 @@ - true + true/pm true diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 34879fe41e..d572d20ada 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,6,5,0 - PRODUCTVERSION 1,6,5,0 + FILEVERSION 1,6,6,0 + PRODUCTVERSION 1,6,6,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "1.6.5" + VALUE "FileVersion", "1.6.6" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "1.6.5" + VALUE "ProductVersion", "1.6.6" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/browser/ui/certificate_trust.h b/atom/browser/ui/certificate_trust.h new file mode 100644 index 0000000000..7cbf31ea41 --- /dev/null +++ b/atom/browser/ui/certificate_trust.h @@ -0,0 +1,29 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_CERTIFICATE_TRUST_H_ +#define ATOM_BROWSER_UI_CERTIFICATE_TRUST_H_ + +#include + +#include "base/callback_forward.h" +#include "base/memory/ref_counted.h" +#include "net/cert/x509_certificate.h" + +namespace atom { +class NativeWindow; +} // namespace atom + +namespace certificate_trust { + +typedef base::Callback ShowTrustCallback; + +void ShowCertificateTrust(atom::NativeWindow* parent_window, + const scoped_refptr& cert, + const std::string& message, + const ShowTrustCallback& callback); + +} // namespace certificate_trust + +#endif // ATOM_BROWSER_UI_CERTIFICATE_TRUST_H_ diff --git a/atom/browser/ui/certificate_trust_mac.mm b/atom/browser/ui/certificate_trust_mac.mm new file mode 100644 index 0000000000..e0888dd3ea --- /dev/null +++ b/atom/browser/ui/certificate_trust_mac.mm @@ -0,0 +1,112 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/ui/certificate_trust.h" + +#import +#import + +#include "atom/browser/native_window.h" +#include "base/strings/sys_string_conversions.h" +#include "net/cert/cert_database.h" + +@interface TrustDelegate : NSObject { + @private + certificate_trust::ShowTrustCallback callback_; + SFCertificateTrustPanel* panel_; + scoped_refptr cert_; + SecTrustRef trust_; + CFArrayRef cert_chain_; + SecPolicyRef sec_policy_; +} + +- (id)initWithCallback:(const certificate_trust::ShowTrustCallback&)callback + panel:(SFCertificateTrustPanel*)panel + cert:(const scoped_refptr&)cert + trust:(SecTrustRef)trust + certChain:(CFArrayRef)certChain + secPolicy:(SecPolicyRef)secPolicy; + +- (void)panelDidEnd:(NSWindow*)sheet + returnCode:(int)returnCode + contextInfo:(void*)contextInfo; + +@end + +@implementation TrustDelegate + +- (void)dealloc { + [panel_ release]; + CFRelease(trust_); + CFRelease(cert_chain_); + CFRelease(sec_policy_); + + [super dealloc]; +} + +- (id)initWithCallback:(const certificate_trust::ShowTrustCallback&)callback + panel:(SFCertificateTrustPanel*)panel + cert:(const scoped_refptr&)cert + trust:(SecTrustRef)trust + certChain:(CFArrayRef)certChain + secPolicy:(SecPolicyRef)secPolicy { + if ((self = [super init])) { + callback_ = callback; + panel_ = panel; + cert_ = cert; + trust_ = trust; + cert_chain_ = certChain; + sec_policy_ = secPolicy; + } + + return self; +} + +- (void)panelDidEnd:(NSWindow*)sheet + returnCode:(int)returnCode + contextInfo:(void*)contextInfo { + auto cert_db = net::CertDatabase::GetInstance(); + // This forces Chromium to reload the certificate since it might be trusted + // now. + cert_db->NotifyObserversCertDBChanged(cert_.get()); + + callback_.Run(); + + [self autorelease]; +} + +@end + +namespace certificate_trust { + +void ShowCertificateTrust(atom::NativeWindow* parent_window, + const scoped_refptr& cert, + const std::string& message, + const ShowTrustCallback& callback) { + auto sec_policy = SecPolicyCreateBasicX509(); + auto cert_chain = cert->CreateOSCertChainForCert(); + SecTrustRef trust = nullptr; + SecTrustCreateWithCertificates(cert_chain, sec_policy, &trust); + + NSWindow* window = parent_window ? + parent_window->GetNativeWindow() : + nil; + auto msg = base::SysUTF8ToNSString(message); + + auto panel = [[SFCertificateTrustPanel alloc] init]; + auto delegate = [[TrustDelegate alloc] initWithCallback:callback + panel:panel + cert:cert + trust:trust + certChain:cert_chain + secPolicy:sec_policy]; + [panel beginSheetForWindow:window + modalDelegate:delegate + didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) + contextInfo:nil + trust:trust + message:msg]; +} + +} // namespace certificate_trust diff --git a/atom/browser/ui/cocoa/atom_touch_bar.h b/atom/browser/ui/cocoa/atom_touch_bar.h index 29cdf79b25..26662cf485 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.h +++ b/atom/browser/ui/cocoa/atom_touch_bar.h @@ -31,6 +31,8 @@ - (NSTouchBar*)touchBarFromItemIdentifiers:(NSMutableArray*)items; - (NSMutableArray*)identifiersFromSettings:(const std::vector&)settings; - (void)refreshTouchBarItem:(NSTouchBar*)touchBar id:(const std::string&)item_id; +- (void)addNonDefaultTouchBarItems:(const std::vector&)items; +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item forTouchBar:(NSTouchBar*)touchBar; - (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix; diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index 69926684b6..a3e846df48 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -113,19 +113,10 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; return nil; } - - (void)refreshTouchBarItem:(NSTouchBar*)touchBar - id:(const std::string&)item_id { - if (![self hasItemWithID:item_id]) return; - - mate::PersistentDictionary settings = settings_[item_id]; - std::string item_type; - settings.Get("type", &item_type); - - NSTouchBarItemIdentifier identifier = [self identifierFromID:item_id - type:item_type]; - if (!identifier) return; - + id:(NSTouchBarItemIdentifier)identifier + withType:(const std::string&)item_type + withSettings:(const mate::PersistentDictionary&)settings { NSTouchBarItem* item = [touchBar itemForIdentifier:identifier]; if (!item) return; @@ -145,7 +136,56 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; } else if (item_type == "scrubber") { [self updateScrubber:(NSCustomTouchBarItem*)item withSettings:settings]; } +} +- (void)addNonDefaultTouchBarItems:(const std::vector&)items { + [self identifiersFromSettings:items]; +} + +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item forTouchBar:(NSTouchBar*)touchBar { + std::string type; + std::string item_id; + NSTouchBarItemIdentifier identifier = nil; + if (item.Get("type", &type) && item.Get("id", &item_id)) { + identifier = [self identifierFromID:item_id type:type]; + } + if (identifier) { + [self addNonDefaultTouchBarItems:{ item }]; + touchBar.escapeKeyReplacementItemIdentifier = identifier; + } else { + touchBar.escapeKeyReplacementItemIdentifier = nil; + } +} + +- (void)refreshTouchBarItem:(NSTouchBar*)touchBar + id:(const std::string&)item_id { + if (![self hasItemWithID:item_id]) return; + + mate::PersistentDictionary settings = settings_[item_id]; + std::string item_type; + settings.Get("type", &item_type); + + auto identifier = [self identifierFromID:item_id type:item_type]; + if (!identifier) return; + + std::vector popover_ids; + settings.Get("_popover", &popover_ids); + for (auto& popover_id : popover_ids) { + auto popoverIdentifier = [self identifierFromID:popover_id type:"popover"]; + if (!popoverIdentifier) continue; + + NSPopoverTouchBarItem* popoverItem = + [touchBar itemForIdentifier:popoverIdentifier]; + [self refreshTouchBarItem:popoverItem.popoverTouchBar + id:identifier + withType:item_type + withSettings:settings]; + } + + [self refreshTouchBarItem:touchBar + id:identifier + withType:item_type + withSettings:settings]; } - (void)buttonAction:(id)sender { diff --git a/atom/browser/ui/cocoa/touch_bar_forward_declarations.h b/atom/browser/ui/cocoa/touch_bar_forward_declarations.h index 57d5bd7453..6fe7c820a1 100644 --- a/atom/browser/ui/cocoa/touch_bar_forward_declarations.h +++ b/atom/browser/ui/cocoa/touch_bar_forward_declarations.h @@ -55,6 +55,7 @@ static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierOtherItemsProxy = @property(copy) NSArray* defaultItemIdentifiers; @property(copy, readonly) NSArray* itemIdentifiers; @property(copy, nullable) NSTouchBarItemIdentifier principalItemIdentifier; +@property(copy, nullable) NSTouchBarItemIdentifier escapeKeyReplacementItemIdentifier; @property(copy) NSSet* templateItems; @property(nullable, weak) id delegate; diff --git a/atom/browser/ui/message_box_mac.mm b/atom/browser/ui/message_box_mac.mm index 3550e47cf8..f752f2945c 100644 --- a/atom/browser/ui/message_box_mac.mm +++ b/atom/browser/ui/message_box_mac.mm @@ -71,10 +71,14 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window, switch (type) { case MESSAGE_BOX_TYPE_INFORMATION: - [alert setAlertStyle:NSInformationalAlertStyle]; + alert.alertStyle = NSInformationalAlertStyle; break; case MESSAGE_BOX_TYPE_WARNING: - [alert setAlertStyle:NSWarningAlertStyle]; + case MESSAGE_BOX_TYPE_ERROR: + // NSWarningAlertStyle shows the app icon while NSCriticalAlertStyle + // shows a warning icon with an app icon badge. Since there is no + // error variant, lets just use NSCriticalAlertStyle. + alert.alertStyle = NSCriticalAlertStyle; break; default: break; @@ -192,7 +196,7 @@ void ShowErrorBox(const base::string16& title, const base::string16& content) { NSAlert* alert = [[NSAlert alloc] init]; [alert setMessageText:base::SysUTF16ToNSString(title)]; [alert setInformativeText:base::SysUTF16ToNSString(content)]; - [alert setAlertStyle:NSWarningAlertStyle]; + [alert setAlertStyle:NSCriticalAlertStyle]; [alert runModal]; [alert release]; } diff --git a/atom/browser/ui/views/menu_layout.cc b/atom/browser/ui/views/menu_layout.cc deleted file mode 100644 index d70a4655a1..0000000000 --- a/atom/browser/ui/views/menu_layout.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "atom/browser/ui/views/menu_layout.h" - -#if defined(OS_WIN) -#include "atom/browser/native_window_views.h" -#include "ui/display/win/screen_win.h" -#endif - -namespace atom { - -namespace { - -#if defined(OS_WIN) -gfx::Rect SubtractBorderSize(gfx::Rect bounds) { - gfx::Point borderSize = gfx::Point( - GetSystemMetrics(SM_CXSIZEFRAME) - 1, // width - GetSystemMetrics(SM_CYSIZEFRAME) - 1); // height - gfx::Point dpiAdjustedSize = - display::win::ScreenWin::ScreenToDIPPoint(borderSize); - - bounds.set_x(bounds.x() + dpiAdjustedSize.x()); - bounds.set_y(bounds.y() + dpiAdjustedSize.y()); - bounds.set_width(bounds.width() - 2 * dpiAdjustedSize.x()); - bounds.set_height(bounds.height() - 2 * dpiAdjustedSize.y()); - return bounds; -} -#endif - -} // namespace - -MenuLayout::MenuLayout(NativeWindowViews* window, int menu_height) - : window_(window), - menu_height_(menu_height) { -} - -MenuLayout::~MenuLayout() { -} - -void MenuLayout::Layout(views::View* host) { -#if defined(OS_WIN) - // Reserve border space for maximized frameless window so we won't have the - // content go outside of screen. - if (!window_->has_frame() && window_->IsMaximized()) { - gfx::Rect bounds = SubtractBorderSize(host->GetContentsBounds()); - host->child_at(0)->SetBoundsRect(bounds); - return; - } -#endif - - if (!HasMenu(host)) { - views::FillLayout::Layout(host); - return; - } - - gfx::Size size = host->GetContentsBounds().size(); - gfx::Rect menu_Bar_bounds = gfx::Rect(0, 0, size.width(), menu_height_); - gfx::Rect web_view_bounds = gfx::Rect( - 0, menu_height_, size.width(), size.height() - menu_height_); - - views::View* web_view = host->child_at(0); - views::View* menu_bar = host->child_at(1); - web_view->SetBoundsRect(web_view_bounds); - menu_bar->SetBoundsRect(menu_Bar_bounds); -} - -gfx::Size MenuLayout::GetPreferredSize(const views::View* host) const { - gfx::Size size = views::FillLayout::GetPreferredSize(host); - if (!HasMenu(host)) - return size; - - size.set_height(size.height() + menu_height_); - return size; -} - -int MenuLayout::GetPreferredHeightForWidth( - const views::View* host, int width) const { - int height = views::FillLayout::GetPreferredHeightForWidth(host, width); - if (!HasMenu(host)) - return height; - - return height + menu_height_; -} - -bool MenuLayout::HasMenu(const views::View* host) const { - return host->child_count() == 2; -} - -} // namespace atom diff --git a/atom/browser/ui/views/menu_layout.h b/atom/browser/ui/views/menu_layout.h deleted file mode 100644 index 0a8464a1d4..0000000000 --- a/atom/browser/ui/views/menu_layout.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_UI_VIEWS_MENU_LAYOUT_H_ -#define ATOM_BROWSER_UI_VIEWS_MENU_LAYOUT_H_ - -#include "ui/views/layout/fill_layout.h" - -namespace atom { - -class NativeWindowViews; - -class MenuLayout : public views::FillLayout { - public: - MenuLayout(NativeWindowViews* window, int menu_height); - virtual ~MenuLayout(); - - // views::LayoutManager: - void Layout(views::View* host) override; - gfx::Size GetPreferredSize(const views::View* host) const override; - int GetPreferredHeightForWidth( - const views::View* host, int width) const override; - - private: - bool HasMenu(const views::View* host) const; - - NativeWindowViews* window_; - int menu_height_; - - DISALLOW_COPY_AND_ASSIGN(MenuLayout); -}; - -} // namespace atom - -#endif // ATOM_BROWSER_UI_VIEWS_MENU_LAYOUT_H_ diff --git a/atom/browser/ui/views/submenu_button.cc b/atom/browser/ui/views/submenu_button.cc index 92f2a791cd..617dd3346d 100644 --- a/atom/browser/ui/views/submenu_button.cc +++ b/atom/browser/ui/views/submenu_button.cc @@ -23,8 +23,8 @@ SubmenuButton::SubmenuButton(const base::string16& title, menu_button_listener, false), accelerator_(0), show_underline_(false), - underline_start_(-1), - underline_end_(-1), + underline_start_(0), + underline_end_(0), text_width_(0), text_height_(0), underline_color_(SK_ColorBLACK), @@ -106,7 +106,7 @@ bool SubmenuButton::GetUnderlinePosition(const base::string16& text, void SubmenuButton::GetCharacterPosition( const base::string16& text, int index, int* pos) { - int height; + int height = 0; gfx::Canvas::SizeStringInt(text.substr(0, index), GetFontList(), pos, &height, 0, 0); } diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index fca7cb2334..3908a2774e 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -23,7 +23,6 @@ WinFrameView::WinFrameView() { WinFrameView::~WinFrameView() { } - gfx::Rect WinFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { return views::GetWindowBoundsForClientBounds( diff --git a/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc b/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc index 9cc2ef9e8d..84a6d9aa3e 100644 --- a/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc +++ b/atom/browser/ui/win/atom_desktop_window_tree_host_win.cc @@ -25,12 +25,4 @@ bool AtomDesktopWindowTreeHostWin::PreHandleMSG( return delegate_->PreHandleMSG(message, w_param, l_param, result); } -/** Override the client area inset - * Returning true forces a border of 0 for frameless windows - */ -bool AtomDesktopWindowTreeHostWin::GetClientAreaInsets( - gfx::Insets* insets) const { - return !HasFrame(); -} - } // namespace atom diff --git a/atom/browser/ui/win/atom_desktop_window_tree_host_win.h b/atom/browser/ui/win/atom_desktop_window_tree_host_win.h index 2df70547c5..47e4cb6aed 100644 --- a/atom/browser/ui/win/atom_desktop_window_tree_host_win.h +++ b/atom/browser/ui/win/atom_desktop_window_tree_host_win.h @@ -27,7 +27,6 @@ class AtomDesktopWindowTreeHostWin : public views::DesktopWindowTreeHostWin { protected: bool PreHandleMSG( UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override; - bool GetClientAreaInsets(gfx::Insets* insets) const override; private: MessageHandlerDelegate* delegate_; // weak ref diff --git a/atom/browser/window_list.cc b/atom/browser/window_list.cc index d627f6d120..374389e0a7 100644 --- a/atom/browser/window_list.cc +++ b/atom/browser/window_list.cc @@ -26,6 +26,16 @@ WindowList* WindowList::GetInstance() { return instance_; } +// static +WindowList::WindowVector WindowList::GetWindows() { + return GetInstance()->windows_; +} + +// static +bool WindowList::IsEmpty() { + return GetInstance()->windows_.empty(); +} + // static void WindowList::AddWindow(NativeWindow* window) { DCHECK(window); @@ -76,6 +86,13 @@ void WindowList::CloseAllWindows() { window->Close(); } +// static +void WindowList::DestroyAllWindows() { + WindowVector windows = GetInstance()->windows_; + for (const auto& window : windows) + window->CloseContents(nullptr); // e.g. Destroy() +} + WindowList::WindowList() { } diff --git a/atom/browser/window_list.h b/atom/browser/window_list.h index d9b307352e..e336c8073d 100644 --- a/atom/browser/window_list.h +++ b/atom/browser/window_list.h @@ -19,23 +19,9 @@ class WindowListObserver; class WindowList { public: typedef std::vector WindowVector; - typedef WindowVector::iterator iterator; - typedef WindowVector::const_iterator const_iterator; - // Windows are added to the list before they have constructed windows, - // so the |window()| member function may return NULL. - const_iterator begin() const { return windows_.begin(); } - const_iterator end() const { return windows_.end(); } - - iterator begin() { return windows_.begin(); } - iterator end() { return windows_.end(); } - - bool empty() const { return windows_.empty(); } - size_t size() const { return windows_.size(); } - - NativeWindow* get(size_t index) const { return windows_[index]; } - - static WindowList* GetInstance(); + static WindowVector GetWindows(); + static bool IsEmpty(); // Adds or removes |window| from the list it is associated with. static void AddWindow(NativeWindow* window); @@ -51,7 +37,12 @@ class WindowList { // Closes all windows. static void CloseAllWindows(); + // Destroy all windows. + static void DestroyAllWindows(); + private: + static WindowList* GetInstance(); + WindowList(); ~WindowList(); diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 1054a3dc9f..3afa163b90 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 1 #define ATOM_MINOR_VERSION 6 -#define ATOM_PATCH_VERSION 5 +#define ATOM_PATCH_VERSION 6 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc index 94fff2ff60..b78bc5b8e1 100644 --- a/atom/common/native_mate_converters/net_converter.cc +++ b/atom/common/native_mate_converters/net_converter.cc @@ -26,6 +26,27 @@ namespace mate { +namespace { + +bool CertFromData(const std::string& data, + scoped_refptr* out) { + auto cert_list = net::X509Certificate::CreateCertificateListFromBytes( + data.c_str(), data.length(), + net::X509Certificate::FORMAT_SINGLE_CERTIFICATE); + if (cert_list.empty()) + return false; + + auto leaf_cert = cert_list.front(); + if (!leaf_cert) + return false; + + *out = leaf_cert; + + return true; +} + +} // namespace + // static v8::Local Converter::ToV8( v8::Isolate* isolate, const net::AuthChallengeInfo* val) { @@ -73,6 +94,37 @@ v8::Local Converter>::ToV8( return dict.GetHandle(); } +bool Converter>::FromV8( + v8::Isolate* isolate, v8::Local val, + scoped_refptr* out) { + mate::Dictionary dict; + if (!ConvertFromV8(isolate, val, &dict)) + return false; + + std::string data; + dict.Get("data", &data); + scoped_refptr leaf_cert; + if (!CertFromData(data, &leaf_cert)) + return false; + + scoped_refptr parent; + if (dict.Get("issuerCert", &parent)) { + auto parents = std::vector( + parent->GetIntermediateCertificates()); + parents.insert(parents.begin(), parent->os_cert_handle()); + auto cert = net::X509Certificate::CreateFromHandle( + leaf_cert->os_cert_handle(), parents); + if (!cert) + return false; + + *out = cert; + } else { + *out = leaf_cert; + } + + return true; +} + // static v8::Local Converter::ToV8( v8::Isolate* isolate, const net::CertPrincipal& val) { diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h index 33117ca974..9e3128fdb5 100644 --- a/atom/common/native_mate_converters/net_converter.h +++ b/atom/common/native_mate_converters/net_converter.h @@ -33,6 +33,10 @@ template<> struct Converter> { static v8::Local ToV8(v8::Isolate* isolate, const scoped_refptr& val); + + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + scoped_refptr* out); }; template<> diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index f4696773da..ae757b1da8 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -33,17 +33,18 @@ // Electron's builtin modules. REFERENCE_MODULE(atom_browser_app); REFERENCE_MODULE(atom_browser_auto_updater); +REFERENCE_MODULE(atom_browser_browser_view); REFERENCE_MODULE(atom_browser_content_tracing); -REFERENCE_MODULE(atom_browser_dialog); REFERENCE_MODULE(atom_browser_debugger); REFERENCE_MODULE(atom_browser_desktop_capturer); +REFERENCE_MODULE(atom_browser_dialog); REFERENCE_MODULE(atom_browser_download_item); +REFERENCE_MODULE(atom_browser_global_shortcut); REFERENCE_MODULE(atom_browser_menu); REFERENCE_MODULE(atom_browser_net); REFERENCE_MODULE(atom_browser_power_monitor); REFERENCE_MODULE(atom_browser_power_save_blocker); REFERENCE_MODULE(atom_browser_protocol); -REFERENCE_MODULE(atom_browser_global_shortcut); REFERENCE_MODULE(atom_browser_render_process_preferences); REFERENCE_MODULE(atom_browser_session); REFERENCE_MODULE(atom_browser_system_preferences); diff --git a/atom/renderer/atom_render_frame_observer.cc b/atom/renderer/atom_render_frame_observer.cc new file mode 100644 index 0000000000..d9a41a48d4 --- /dev/null +++ b/atom/renderer/atom_render_frame_observer.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/renderer/atom_render_frame_observer.h" + +#include "content/public/renderer/render_frame.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebScriptSource.h" + +namespace atom { + +AtomRenderFrameObserver::AtomRenderFrameObserver( + content::RenderFrame* frame, + RendererClientBase* renderer_client) + : content::RenderFrameObserver(frame), + render_frame_(frame), + renderer_client_(renderer_client) {} + +void AtomRenderFrameObserver::DidClearWindowObject() { + renderer_client_->DidClearWindowObject(render_frame_); +} + +void AtomRenderFrameObserver::DidCreateScriptContext( + v8::Handle context, + int extension_group, + int world_id) { + if (ShouldNotifyClient(world_id)) + renderer_client_->DidCreateScriptContext(context, render_frame_); + + if (renderer_client_->isolated_world() && IsMainWorld(world_id) + && render_frame_->IsMainFrame()) { + CreateIsolatedWorldContext(); + renderer_client_->SetupMainWorldOverrides(context); + } +} + +void AtomRenderFrameObserver::WillReleaseScriptContext( + v8::Local context, + int world_id) { + if (ShouldNotifyClient(world_id)) + renderer_client_->WillReleaseScriptContext(context, render_frame_); +} + +void AtomRenderFrameObserver::OnDestruct() { + delete this; +} + +void AtomRenderFrameObserver::CreateIsolatedWorldContext() { + auto frame = render_frame_->GetWebFrame(); + + // This maps to the name shown in the context combo box in the Console tab + // of the dev tools. + frame->setIsolatedWorldHumanReadableName( + World::ISOLATED_WORLD, + blink::WebString::fromUTF8("Electron Isolated Context")); + + // Setup document's origin policy in isolated world + frame->setIsolatedWorldSecurityOrigin( + World::ISOLATED_WORLD, frame->document().getSecurityOrigin()); + + // Create initial script context in isolated world + blink::WebScriptSource source("void 0"); + frame->executeScriptInIsolatedWorld( + World::ISOLATED_WORLD, &source, 1, ExtensionGroup::MAIN_GROUP); +} + +bool AtomRenderFrameObserver::IsMainWorld(int world_id) { + return world_id == World::MAIN_WORLD; +} + +bool AtomRenderFrameObserver::IsIsolatedWorld(int world_id) { + return world_id == World::ISOLATED_WORLD; +} + +bool AtomRenderFrameObserver::ShouldNotifyClient(int world_id) { + if (renderer_client_->isolated_world() && render_frame_->IsMainFrame()) + return IsIsolatedWorld(world_id); + else + return IsMainWorld(world_id); +} + +} // namespace atom diff --git a/atom/renderer/atom_render_frame_observer.h b/atom/renderer/atom_render_frame_observer.h new file mode 100644 index 0000000000..51cb21b3b0 --- /dev/null +++ b/atom/renderer/atom_render_frame_observer.h @@ -0,0 +1,53 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_RENDERER_ATOM_RENDER_FRAME_OBSERVER_H_ +#define ATOM_RENDERER_ATOM_RENDER_FRAME_OBSERVER_H_ + +#include "atom/renderer/renderer_client_base.h" +#include "content/public/renderer/render_frame_observer.h" + +namespace atom { + +enum World { + MAIN_WORLD = 0, + // Use a high number far away from 0 to not collide with any other world + // IDs created internally by Chrome. + ISOLATED_WORLD = 999 +}; + +enum ExtensionGroup { + MAIN_GROUP = 1 +}; + +// Helper class to forward the messages to the client. +class AtomRenderFrameObserver : public content::RenderFrameObserver { + public: + AtomRenderFrameObserver(content::RenderFrame* frame, + RendererClientBase* renderer_client); + + // content::RenderFrameObserver: + void DidClearWindowObject() override; + void DidCreateScriptContext(v8::Handle context, + int extension_group, + int world_id) override; + void WillReleaseScriptContext(v8::Local context, + int world_id) override; + void OnDestruct() override; + + private: + bool ShouldNotifyClient(int world_id); + void CreateIsolatedWorldContext(); + bool IsMainWorld(int world_id); + bool IsIsolatedWorld(int world_id); + + content::RenderFrame* render_frame_; + RendererClientBase* renderer_client_; + + DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver); +}; + +} // namespace atom + +#endif // ATOM_RENDERER_ATOM_RENDER_FRAME_OBSERVER_H_ diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 9d015b4f22..5dafe084ce 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -16,16 +16,15 @@ #include "atom/common/node_bindings.h" #include "atom/common/options_switches.h" #include "atom/renderer/api/atom_api_renderer_ipc.h" +#include "atom/renderer/atom_render_frame_observer.h" #include "atom/renderer/atom_render_view_observer.h" #include "atom/renderer/node_array_buffer_bridge.h" #include "atom/renderer/web_worker_observer.h" #include "base/command_line.h" #include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_frame_observer.h" #include "native_mate/dictionary.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebScriptSource.h" #include "atom/common/node_includes.h" @@ -33,127 +32,6 @@ namespace atom { namespace { -enum World { - MAIN_WORLD = 0, - // Use a high number far away from 0 to not collide with any other world - // IDs created internally by Chrome. - ISOLATED_WORLD = 999 -}; - -enum ExtensionGroup { - MAIN_GROUP = 1 -}; - -// Helper class to forward the messages to the client. -class AtomRenderFrameObserver : public content::RenderFrameObserver { - public: - AtomRenderFrameObserver(content::RenderFrame* frame, - AtomRendererClient* renderer_client) - : content::RenderFrameObserver(frame), - render_frame_(frame), - renderer_client_(renderer_client) {} - - // content::RenderFrameObserver: - void DidClearWindowObject() override { - renderer_client_->DidClearWindowObject(render_frame_); - } - - void CreateIsolatedWorldContext() { - auto frame = render_frame_->GetWebFrame(); - - // This maps to the name shown in the context combo box in the Console tab - // of the dev tools. - frame->setIsolatedWorldHumanReadableName( - World::ISOLATED_WORLD, - blink::WebString::fromUTF8("Electron Isolated Context")); - - // Setup document's origin policy in isolated world - frame->setIsolatedWorldSecurityOrigin( - World::ISOLATED_WORLD, frame->document().getSecurityOrigin()); - - // Create initial script context in isolated world - blink::WebScriptSource source("void 0"); - frame->executeScriptInIsolatedWorld( - World::ISOLATED_WORLD, &source, 1, ExtensionGroup::MAIN_GROUP); - } - - void SetupMainWorldOverrides(v8::Handle context) { - // Setup window overrides in the main world context - v8::Isolate* isolate = context->GetIsolate(); - - // Wrap the bundle into a function that receives the binding object as - // an argument. - std::string bundle(node::isolated_bundle_data, - node::isolated_bundle_data + sizeof(node::isolated_bundle_data)); - std::string wrapper = "(function (binding, require) {\n" + bundle + "\n})"; - auto script = v8::Script::Compile( - mate::ConvertToV8(isolate, wrapper)->ToString()); - auto func = v8::Handle::Cast( - script->Run(context).ToLocalChecked()); - - auto binding = v8::Object::New(isolate); - api::Initialize(binding, v8::Null(isolate), context, nullptr); - - // Pass in CLI flags needed to setup window - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - mate::Dictionary dict(isolate, binding); - if (command_line->HasSwitch(switches::kGuestInstanceID)) - dict.Set(options::kGuestInstanceID, - command_line->GetSwitchValueASCII(switches::kGuestInstanceID)); - if (command_line->HasSwitch(switches::kOpenerID)) - dict.Set(options::kOpenerID, - command_line->GetSwitchValueASCII(switches::kOpenerID)); - dict.Set("hiddenPage", command_line->HasSwitch(switches::kHiddenPage)); - - v8::Local args[] = { binding }; - ignore_result(func->Call(context, v8::Null(isolate), 1, args)); - } - - bool IsMainWorld(int world_id) { - return world_id == World::MAIN_WORLD; - } - - bool IsIsolatedWorld(int world_id) { - return world_id == World::ISOLATED_WORLD; - } - - bool ShouldNotifyClient(int world_id) { - if (renderer_client_->isolated_world() && render_frame_->IsMainFrame()) - return IsIsolatedWorld(world_id); - else - return IsMainWorld(world_id); - } - - void DidCreateScriptContext(v8::Handle context, - int extension_group, - int world_id) override { - if (ShouldNotifyClient(world_id)) - renderer_client_->DidCreateScriptContext(context, render_frame_); - - if (renderer_client_->isolated_world() && IsMainWorld(world_id) - && render_frame_->IsMainFrame()) { - CreateIsolatedWorldContext(); - SetupMainWorldOverrides(context); - } - } - - void WillReleaseScriptContext(v8::Local context, - int world_id) override { - if (ShouldNotifyClient(world_id)) - renderer_client_->WillReleaseScriptContext(context, render_frame_); - } - - void OnDestruct() override { - delete this; - } - - private: - content::RenderFrame* render_frame_; - AtomRendererClient* renderer_client_; - - DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver); -}; - bool IsDevToolsExtension(content::RenderFrame* render_frame) { return static_cast(render_frame->GetWebFrame()->document().url()) .SchemeIs("chrome-extension"); @@ -180,7 +58,6 @@ void AtomRendererClient::RenderThreadStarted() { void AtomRendererClient::RenderFrameCreated( content::RenderFrame* render_frame) { - new AtomRenderFrameObserver(render_frame, this); RendererClientBase::RenderFrameCreated(render_frame); } @@ -189,12 +66,6 @@ void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) { RendererClientBase::RenderViewCreated(render_view); } -void AtomRendererClient::DidClearWindowObject( - content::RenderFrame* render_frame) { - // Make sure every page will get a script context created. - render_frame->GetWebFrame()->executeScript(blink::WebScriptSource("void 0")); -} - void AtomRendererClient::RunScriptsAtDocumentStart( content::RenderFrame* render_frame) { // Inform the document start pharse. @@ -307,4 +178,38 @@ v8::Local AtomRendererClient::GetContext( return frame->mainWorldScriptContext(); } +void AtomRendererClient::SetupMainWorldOverrides( + v8::Handle context) { + // Setup window overrides in the main world context + v8::Isolate* isolate = context->GetIsolate(); + + // Wrap the bundle into a function that receives the binding object as + // an argument. + std::string bundle(node::isolated_bundle_data, + node::isolated_bundle_data + sizeof(node::isolated_bundle_data)); + std::string wrapper = "(function (binding, require) {\n" + bundle + "\n})"; + auto script = v8::Script::Compile( + mate::ConvertToV8(isolate, wrapper)->ToString()); + auto func = v8::Handle::Cast( + script->Run(context).ToLocalChecked()); + + auto binding = v8::Object::New(isolate); + api::Initialize(binding, v8::Null(isolate), context, nullptr); + + // Pass in CLI flags needed to setup window + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + mate::Dictionary dict(isolate, binding); + if (command_line->HasSwitch(switches::kGuestInstanceID)) + dict.Set(options::kGuestInstanceID, + command_line->GetSwitchValueASCII(switches::kGuestInstanceID)); + if (command_line->HasSwitch(switches::kOpenerID)) + dict.Set(options::kOpenerID, + command_line->GetSwitchValueASCII(switches::kOpenerID)); + dict.Set("hiddenPage", command_line->HasSwitch(switches::kHiddenPage)); + + v8::Local args[] = { binding }; + ignore_result(func->Call(context, v8::Null(isolate), 1, args)); +} + + } // namespace atom diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index 5a1141d103..3feaff4528 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -20,16 +20,19 @@ class AtomRendererClient : public RendererClientBase { AtomRendererClient(); virtual ~AtomRendererClient(); - void DidClearWindowObject(content::RenderFrame* render_frame); - void DidCreateScriptContext( - v8::Handle context, content::RenderFrame* render_frame); - void WillReleaseScriptContext( - v8::Handle context, content::RenderFrame* render_frame); - // Get the context that the Electron API is running in. v8::Local GetContext( blink::WebFrame* frame, v8::Isolate* isolate); - bool isolated_world() { return isolated_world_; } + + // atom::RendererClientBase: + void DidCreateScriptContext( + v8::Handle context, + content::RenderFrame* render_frame) override; + void WillReleaseScriptContext( + v8::Handle context, + content::RenderFrame* render_frame) override; + void SetupMainWorldOverrides(v8::Handle context) override; + bool isolated_world() override { return isolated_world_; } private: enum NodeIntegration { diff --git a/atom/renderer/atom_sandboxed_renderer_client.cc b/atom/renderer/atom_sandboxed_renderer_client.cc index 80f8cae713..4fe9bd449d 100644 --- a/atom/renderer/atom_sandboxed_renderer_client.cc +++ b/atom/renderer/atom_sandboxed_renderer_client.cc @@ -20,7 +20,6 @@ #include "base/command_line.h" #include "chrome/renderer/printing/print_web_view_helper.h" #include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_observer.h" #include "ipc/ipc_message_macros.h" @@ -89,50 +88,6 @@ void InitializeBindings(v8::Local binding, b.SetMethod("crash", AtomBindings::Crash); } -class AtomSandboxedRenderFrameObserver : public content::RenderFrameObserver { - public: - AtomSandboxedRenderFrameObserver(content::RenderFrame* frame, - AtomSandboxedRendererClient* renderer_client) - : content::RenderFrameObserver(frame), - render_frame_(frame), - world_id_(-1), - renderer_client_(renderer_client) {} - - // content::RenderFrameObserver: - void DidClearWindowObject() override { - // Make sure every page will get a script context created. - render_frame_->GetWebFrame()->executeScript( - blink::WebScriptSource("void 0")); - } - - void DidCreateScriptContext(v8::Handle context, - int extension_group, - int world_id) override { - if (world_id_ != -1 && world_id_ != world_id) - return; - world_id_ = world_id; - renderer_client_->DidCreateScriptContext(context, render_frame_); - } - - void WillReleaseScriptContext(v8::Local context, - int world_id) override { - if (world_id_ != world_id) - return; - renderer_client_->WillReleaseScriptContext(context, render_frame_); - } - - void OnDestruct() override { - delete this; - } - - private: - content::RenderFrame* render_frame_; - int world_id_; - AtomSandboxedRendererClient* renderer_client_; - - DISALLOW_COPY_AND_ASSIGN(AtomSandboxedRenderFrameObserver); -}; - class AtomSandboxedRenderViewObserver : public AtomRenderViewObserver { public: AtomSandboxedRenderViewObserver(content::RenderView* render_view, @@ -181,7 +136,6 @@ AtomSandboxedRendererClient::~AtomSandboxedRendererClient() { void AtomSandboxedRendererClient::RenderFrameCreated( content::RenderFrame* render_frame) { - new AtomSandboxedRenderFrameObserver(render_frame, this); RendererClientBase::RenderFrameCreated(render_frame); } diff --git a/atom/renderer/atom_sandboxed_renderer_client.h b/atom/renderer/atom_sandboxed_renderer_client.h index 5e0614c9c9..a8eae0ba84 100644 --- a/atom/renderer/atom_sandboxed_renderer_client.h +++ b/atom/renderer/atom_sandboxed_renderer_client.h @@ -16,13 +16,18 @@ class AtomSandboxedRendererClient : public RendererClientBase { AtomSandboxedRendererClient(); virtual ~AtomSandboxedRendererClient(); - void DidCreateScriptContext( - v8::Handle context, content::RenderFrame* render_frame); - void WillReleaseScriptContext( - v8::Handle context, content::RenderFrame* render_frame); void InvokeIpcCallback(v8::Handle context, const std::string& callback_name, std::vector> args); + // atom::RendererClientBase: + void DidCreateScriptContext( + v8::Handle context, + content::RenderFrame* render_frame) override; + void WillReleaseScriptContext( + v8::Handle context, + content::RenderFrame* render_frame) override; + void SetupMainWorldOverrides(v8::Handle context) override { } + bool isolated_world() override { return false; } // content::ContentRendererClient: void RenderFrameCreated(content::RenderFrame*) override; void RenderViewCreated(content::RenderView*) override; diff --git a/atom/renderer/renderer_client_base.cc b/atom/renderer/renderer_client_base.cc index 3ee72b3c0d..4d3675e2f6 100644 --- a/atom/renderer/renderer_client_base.cc +++ b/atom/renderer/renderer_client_base.cc @@ -11,6 +11,7 @@ #include "atom/common/color_util.h" #include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" +#include "atom/renderer/atom_render_frame_observer.h" #include "atom/renderer/content_settings_observer.h" #include "atom/renderer/guest_view_container.h" #include "atom/renderer/preferences_manager.h" @@ -27,6 +28,7 @@ #include "third_party/WebKit/public/web/WebFrameWidget.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebPluginParams.h" +#include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" #if defined(OS_MACOSX) @@ -96,21 +98,20 @@ void RendererClientBase::RenderThreadStarted() { #endif #if defined(OS_MACOSX) - // Disable rubber banding by default. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kScrollBounce)) { - base::ScopedCFTypeRef key( - base::SysUTF8ToCFStringRef("NSScrollViewRubberbanding")); - base::ScopedCFTypeRef value( - base::SysUTF8ToCFStringRef("false")); - CFPreferencesSetAppValue(key, value, kCFPreferencesCurrentApplication); - CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); - } + bool scroll_bounce = command_line->HasSwitch(switches::kScrollBounce); + base::ScopedCFTypeRef rubber_banding_key( + base::SysUTF8ToCFStringRef("NSScrollViewRubberbanding")); + CFPreferencesSetAppValue(rubber_banding_key, + scroll_bounce ? kCFBooleanTrue : kCFBooleanFalse, + kCFPreferencesCurrentApplication); + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); #endif } void RendererClientBase::RenderFrameCreated( content::RenderFrame* render_frame) { + new AtomRenderFrameObserver(render_frame, this); new PepperHelper(render_frame); new ContentSettingsObserver(render_frame); new printing::PrintWebViewHelper(render_frame); @@ -151,6 +152,12 @@ void RendererClientBase::RenderViewCreated(content::RenderView* render_view) { } } +void RendererClientBase::DidClearWindowObject( + content::RenderFrame* render_frame) { + // Make sure every page will get a script context created. + render_frame->GetWebFrame()->executeScript(blink::WebScriptSource("void 0")); +} + blink::WebSpeechSynthesizer* RendererClientBase::OverrideSpeechSynthesizer( blink::WebSpeechSynthesizerClient* client) { return new TtsDispatcher(client); diff --git a/atom/renderer/renderer_client_base.h b/atom/renderer/renderer_client_base.h index 3a91255c60..c8958de904 100644 --- a/atom/renderer/renderer_client_base.h +++ b/atom/renderer/renderer_client_base.h @@ -19,6 +19,14 @@ class RendererClientBase : public content::ContentRendererClient { RendererClientBase(); virtual ~RendererClientBase(); + virtual void DidCreateScriptContext( + v8::Handle context, content::RenderFrame* render_frame) = 0; + virtual void WillReleaseScriptContext( + v8::Handle context, content::RenderFrame* render_frame) = 0; + virtual void DidClearWindowObject(content::RenderFrame* render_frame); + virtual void SetupMainWorldOverrides(v8::Handle context) = 0; + virtual bool isolated_world() = 0; + protected: void AddRenderBindings(v8::Isolate* isolate, v8::Local binding_object); diff --git a/atom/utility/atom_content_utility_client.cc b/atom/utility/atom_content_utility_client.cc index 37fa755871..cc36293f43 100644 --- a/atom/utility/atom_content_utility_client.cc +++ b/atom/utility/atom_content_utility_client.cc @@ -19,4 +19,16 @@ AtomContentUtilityClient::AtomContentUtilityClient() { AtomContentUtilityClient::~AtomContentUtilityClient() { } +bool AtomContentUtilityClient::OnMessageReceived( + const IPC::Message& message) { +#if defined(OS_WIN) + for (auto* handler : handlers_) { + if (handler->OnMessageReceived(message)) + return true; + } +#endif + + return false; +} + } // namespace atom diff --git a/atom/utility/atom_content_utility_client.h b/atom/utility/atom_content_utility_client.h index 0edc4d5d80..b4aa7960f6 100644 --- a/atom/utility/atom_content_utility_client.h +++ b/atom/utility/atom_content_utility_client.h @@ -20,6 +20,8 @@ class AtomContentUtilityClient : public content::ContentUtilityClient { AtomContentUtilityClient(); ~AtomContentUtilityClient() override; + bool OnMessageReceived(const IPC::Message& message) override; + private: #if defined(OS_WIN) typedef ScopedVector Handlers; diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.cc b/chromium_src/chrome/browser/printing/print_view_manager_base.cc index bc5d3f31f0..07ec2992f3 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.cc +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.cc @@ -159,6 +159,7 @@ void PrintViewManagerBase::OnDidPrintPage( ShouldQuitFromInnerMessageLoop(); #else + print_job_->AppendPrintedPage(params.page_number); if (metafile_must_be_valid) { bool print_text_with_gdi = document->settings().print_text_with_gdi() && diff --git a/docs-translations/ko-KR/tutorial/windows-store-guide.md b/docs-translations/ko-KR/tutorial/windows-store-guide.md index 34d36d6bc5..23a4bbc32f 100644 --- a/docs-translations/ko-KR/tutorial/windows-store-guide.md +++ b/docs-translations/ko-KR/tutorial/windows-store-guide.md @@ -67,8 +67,7 @@ npm install -g electron-windows-store │ └── atom.asar ├── snapshot_blob.bin ├── squirrel.exe -├── ui_resources_200_percent.pak -└── xinput1_3.dll +└── ui_resources_200_percent.pak ``` ## `electron-windows-store` 실행하기 diff --git a/docs-translations/tr-TR/README.md b/docs-translations/tr-TR/README.md index d9d8a1bdce..a3487d298a 100644 --- a/docs-translations/tr-TR/README.md +++ b/docs-translations/tr-TR/README.md @@ -5,12 +5,12 @@ Eğer öyleyse, atom.io üzerinden [mevcut sürümler](https://electron.atom.io/ ## SSS(Sıkça Sorulan Sorular) Bir problem(issue) bildirmeden önce sıkça sorulan sorulara göz atın: -* [Electron SSS](https://github.com/electron/electron/tree/master/docs/faq/electron-faq.md) +* [Electron SSS](https://github.com/electron/electron/blob/master/docs/faq.md) ## Klavuzlar -* [Desteklenen Platformlar ](https://github.com/electron/electron/tree/master/docs/tutorial/supported-platforms.md) -* [Uygulama Dağıtımı](https://github.com/electron/electron/tree/master/docs/tutorial/application-distribution.md) +* [Desteklenen Platformlar ](tutorial/supported-platforms.md) +* [Uygulama Dağıtımı](tutorial/application-distribution.md) * [Mac Uygulama Mağazası Başvuru Klavuzu](https://github.com/electron/electron/tree/master/docs/tutorial/mac-app-store-submission-guide.md) * [Uygulama Paketleme](https://github.com/electron/electron/tree/master/docs/tutorial/application-packaging.md) * [Native Node Modüllerini Kullanma](https://github.com/electron/electron/tree/master/docs/tutorial/using-native-node-modules.md) diff --git a/docs-translations/tr-TR/project/README.md b/docs-translations/tr-TR/project/README.md new file mode 100644 index 0000000000..d5be777393 --- /dev/null +++ b/docs-translations/tr-TR/project/README.md @@ -0,0 +1,85 @@ +[![Electron Logo](https://electron.atom.io/images/electron-logo.svg)](https://electron.atom.io/) + +[![Travis Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron) +[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/bc56v83355fi3369/branch/master?svg=true)](https://ci.appveyor.com/project/electron-bot/electron/branch/master) +[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev) +[![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) + +:memo: Mevcut çeviriler: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md) | [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es/project/README.md)| [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR/project/README.md) + +Electron framework JavaScript, HTML ve CSS kullanarak çapraz platform +masaüstü uygulamaları yazmanıza yarar. Electron [Node.js](https://nodejs.org/) ile geliştirilmiş; +[Atom editor](https://github.com/atom/atom) ve birçok uygulama [apps](https://electron.atom.io/apps) tarafından kullanılmaktadir. + +Önemli duyurular için Twitter da [@ElectronJS](https://twitter.com/electronjs) adresini takip edin. + +Bu proje katılımcı sözleşmesine bağlıdır. Katılarak, +bu kodun sürdürülebilir olduğunu üstlenmeniz beklenmekte. +Lütfen uygun olmayan davranışları electron@github.com'a rapor edin. + +## Downloads + +Electron prebuilt mimarisini yüklemek için, +[`npm`](https://docs.npmjs.com/): + +```sh +# Development dependency olarak yükleyin +npm install electron --save-dev + +# `electron` komutunu global olarak $PATH'a yükleyin +npm install electron -g +``` + +Prebuilt mimarileri, debug sembolleri, ve fazlası için +[releases page](https://github.com/electron/electron/releases) sayfasını ziyaret edin. + +### Mirrors + +- [China](https://npm.taobao.org/mirrors/electron) + +## Dokümantasyon + +Klavuz ve API referansları [docs](https://github.com/electron/electron/tree/master/docs) klasöründe bulunabilir. +Aynı zamanda nasıl kurulum gerçekleştirileceği ve Electron'un gelişimine nasıl katılacağınızı +açıklayan dosyalar içermektedir. + +## Dökümantasyon Çevirileri + +- [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR) +- [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR) +- [Japanese](https://github.com/electron/electron/tree/master/docs-translations/jp) +- [Spanish](https://github.com/electron/electron/tree/master/docs-translations/es) +- [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN) +- [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW) +- [Turkish](https://github.com/electron/electron/tree/master/docs-translations/tr-TR) +- [Thai](https://github.com/electron/electron/tree/master/docs-Translations/th-TH) +- [Ukrainian](https://github.com/electron/electron/tree/master/docs-translations/uk-UA) +- [Russian](https://github.com/electron/electron/tree/master/docs-translations/ru-RU) +- [French](https://github.com/electron/electron/tree/master/docs-translations/fr-FR) + +## Hızlı Başlangıç + +Minimal Electron uygulamasını calışırken görmek için [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start) +repository'ni klonla ve çalıştır. + +## Topluluk + +Asağıdaki sayfalardan sorular sorabilir ve topluluk ile etkileşime geçebilirsiniz: + +- [`electron`](http://discuss.atom.io/c/electron) Atom forumundaki kategoriler +- `#atom-shell` Freenode kanal'ı +- [`Atom`](http://atom-slack.herokuapp.com/) Slack kanal'ı +- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)* +- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)* +- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)* +- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)* +- [`electron-id`](https://electron-id.slack.com) *(Indonesia)* + +Topluluk tarafından sağlanan örnek uygulamaları, aracları ve kaynaklara ulaşmak için +[awesome-electron](https://github.com/sindresorhus/awesome-electron) sayfasını ziyaret et. + +## Lisans + +[MIT](https://github.com/electron/electron/blob/master/LICENSE) + +Electron veya Github logolarını kullandığınızda, [GitHub logo guidelines](https://github.com/logos) sayfasını okuduğunuzdan emin olun. diff --git a/docs-translations/tr-TR/tutorial/application-distribution.md b/docs-translations/tr-TR/tutorial/application-distribution.md new file mode 100644 index 0000000000..319f8af787 --- /dev/null +++ b/docs-translations/tr-TR/tutorial/application-distribution.md @@ -0,0 +1,178 @@ +# Application Distribution + +Electron uygulamanızı dağıtmak için önce Electron nun [prebuilt mimarilerini] +(https://github.com/electron/electron/releases) indirmeniz gerekmektedir. +Sonrasında, uygulamanızın bulundugu klasör `app` şeklinde isimlendirilmeli ve +Electron kaynaklar klasörüne aşagıda gösterildiği gibi yerleştirilmelidir. +Unutmayın, Electronun prebuilt mimarileri aşağıdaki örneklerde `electron/` +şeklinde belirtilmiştir. + + +MacOS da: + +```text +electron/Electron.app/Contents/Resources/app/ +├── package.json +├── main.js +└── index.html +``` + +Windows ve Linux da: + +```text +electron/resources/app +├── package.json +├── main.js +└── index.html +``` + +Ardından `Electron.app` (veya `electron` Linux'da, `electron.exe` Windows'da) şeklinde çalıstırın, +ve Electron uygulama şeklinde çalışacaktır. +`electron` klasörü son kullanıcıya aktaracağınız dağıtımınız olacaktır. + +## Uygulamanın bir dosya şeklinde paketlenmesi + +Tüm kaynak kodlarını kopyalama yoluyla uygulamanızı dağıtmak haricinde, +uygulamanızı [asar](https://github.com/electron/asar) ile arşiv haline getirerek, +kaynak kodlarınızın kullanıcılar tarafından görülmesini engelliye bilirsiniz. + +`app` klasörü yerine `asar` arşiv dosyası kullanmak için, arşiv dosyanızı `app.asar` +şeklinde isimlendirmeniz gerekiyor, ve bu dosyayı Electron'nun kaynak klasörüne aşağıdaki +gibi yerleştirmelisiniz. Böylelikle Electron arşivi okuyup ondan başlayacaktır. + + +MacOS'da: + +```text +electron/Electron.app/Contents/Resources/ +└── app.asar +``` + +Windows ve Linux'da: + +```text +electron/resources/ +└── app.asar +``` + +Daha fazla bilgi için [Application packaging](application-packaging.md). + +## İndirilen mimarileri yeniden adlandırma + +Uygulamanızı Electron ile paketledikten sonra ve kullanıcılara uygulamanızı dağıtmadan önce +adını değiştirmek isteye bilirsiniz. + +### Windows + +`electron.exe` istediğiniz şekilde yeniden adlandırabilirsiniz. Icon ve diğer +bilgileri bu gibi araçlar [rcedit](https://github.com/atom/rcedit) ile düzenleye bilirsiniz. + +### macOS + +`Electron.app`'i istediğiniz şekilde yeniden adlandırabilirsiniz, ve aşağıdaki dosyalarda +`CFBundleDisplayName`, `CFBundleIdentifier` ve `CFBundleName` kısımlarınıda düzenlemelisiniz. + +* `Electron.app/Contents/Info.plist` +* `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist` + +Görev yöneticisinde `Electron Helper` şeklinde göstermek yerine, +isterseniz helper uygulamasınında adını değiştire bilirsiniz, +ancak dosyanın adını açılabilir olduğundan emin olun. + +Yeniden adlandırılmış uygulamanın klasör yapısı bu şekilde görünecektir: + +``` +MyApp.app/Contents +├── Info.plist +├── MacOS/ +│   └── MyApp +└── Frameworks/ + ├── MyApp Helper EH.app + | ├── Info.plist + | └── MacOS/ + |    └── MyApp Helper EH + ├── MyApp Helper NP.app + | ├── Info.plist + | └── MacOS/ + |    └── MyApp Helper NP + └── MyApp Helper.app + ├── Info.plist + └── MacOS/ +    └── MyApp Helper +``` + +### Linux + +`electron` dosyasını istediğiniz şekilde yeniden adlandırabilirsiniz. + +## Paketleme Araçları + +Uygulamanızı manuel şekilde paketlemek dışında, üçüncü parti +paketleme araçlarıylada otomatik olarak ayni şekilde paketliye bilirsiniz: + +* [electron-builder](https://github.com/electron-userland/electron-builder) +* [electron-packager](https://github.com/electron-userland/electron-packager) + +## Kaynaktan yeniden kurulum yoluyla isim değişikliği + +Ürün adını değiştirip, kaynaktan kurulum yoluylada Electron'nun adını değiştirmek mümkün. +Bunun için `atom.gyp` dosyasını yeniden modifiye edip, tekrardan temiz bir kurulum yapmalısınız. + +### grunt-build-atom-shell + +Manuel olarak Electron kodlarını kontrol edip tekrar kurulum yapmak biraz zor olabilir, +bu yüzden tüm bu işlemleri otomatik olarak gerçekleştirecek bir Grunt görevi oluşturuldu: +[grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell). + +Bu görev otomatik olarak `.gyp` dosyasını düzenleyecek, kaynaktan kurulumu gerçekleştirecek, +sonrasında ise uygulamanızın doğal Node modüllerini, yeni yürütülebilen isim ile eşleştirmek icin +tekrardan kuracaktır. + +### Özel bir Electron kopyası oluşturma + +Electron'un size ait bir kopyasını oluşturmak, neredeyse uygulamanızı kurmak için hiç ihtiyacınız +olmayacak bir işlemdir, "Production Level" uygulamalarda buna dahildir. +`electron-packager` veya `electron-builder` gibi araçlar kullanarak yukarıda ki işlemleri +gerçekleştirmeksizin, "Rebrand" Electron işlemini uygulaya bilirsiniz. + +Eğer kendinize ait yüklenemiyen veya resmi versiyondan red edilmiş, +direk olarak Electron a paketlediğiniz C++ kodunuz var ise, +öncelikle Electron'un bir kopyasını oluşturmalısınız. +Electron'nun destekleyicileri olarak, senaryonuzun çalışmasını çok isteriz, +bu yüzden lütfen yapacağınız değişiklikleri Electron'nun resmi versiyonuna +entegre etmeye calışın, bu sizin için daha kolay olacaktır, ve yardimlarınız +için cok minnettar olacağız. + +#### surf-build İle Özel Dağıtım oluşturulması + +1. Npm yoluyla [Surf](https://github.com/surf-build/surf) yükleyin: + `npm install -g surf-build@latest` + + +2. Yeni bir S3 bucket ve aşağıdakı boş klasör yapısını oluşturun: + + ``` + - atom-shell/ + - symbols/ + - dist/ + ``` + +3. Aşağıdaki Ortam Değişkenlerini ayarlayın: + + * `ELECTRON_GITHUB_TOKEN` - GitHub üzerinden dağıtım oluşturan token + * `ELECTRON_S3_ACCESS_KEY`, `ELECTRON_S3_BUCKET`, `ELECTRON_S3_SECRET_KEY` - + node.js bağlantılarını ve sembollerini yükleyeceğiniz yer + * `ELECTRON_RELEASE` - `true` şeklinde ayarlayın ve yükleme işlemi çalışacaktır, + yapmamanız halinde, `surf-build` sadece CI-type kontrolü yapacak, + tüm pull isteklerine uygun hale getirecektir. + * `CI` - `true` olarak ayarlayın yoksa çalışmayacaktır. + * `GITHUB_TOKEN` - bununla aynı şekilde ayarlayın `ELECTRON_GITHUB_TOKEN` + * `SURF_TEMP` - Windowsda ki 'path too long' sorunundan kaçınmak için `C:\Temp` şeklinde ayarlayın + * `TARGET_ARCH` - `ia32` veya `x64` şeklinde ayarlayın + +4. `script/upload.py` dosyasında ki `ELECTRON_REPO` kısmını, kendi kopyanız ile değiştirmek _zorundasınız_, + özellikle eğer bir Electron proper destekleyicisi iseniz. + +5. `surf-build -r https://github.com/MYORG/electron -s YOUR_COMMIT -n 'surf-PLATFORM-ARCH'` + +6. Kurulum bitene kadar uzunca bekleyin. diff --git a/docs-translations/tr-TR/tutorial/supported-platforms.md b/docs-translations/tr-TR/tutorial/supported-platforms.md new file mode 100644 index 0000000000..4cc131b103 --- /dev/null +++ b/docs-translations/tr-TR/tutorial/supported-platforms.md @@ -0,0 +1,29 @@ +# Desteklenen platformlar + +Aşağıdaki platformlar Electron tarafından desteklenmektedir: + +### macOS + +MacOS için sadece 64bit mimariler sağlanmakta olup, desteklenen minimum macOS versiyonu 10.9 dur. + +### Windows + +Windows 7 ve gelişmiş versiyonlar desteklenmektedir, eski işletim sistemleri desteklenmemektedir +(ve çalışmayacaktır). + +Windows `ia32` (`x86`) ve `x64` (`amd64`) mimarileri desteklenmektedir. +Unutmayın, `ARM` mimarisi al₺tında çalışan Windows işletim sistemleri şuan için desteklenmemektedir. + +### Linux + +Electron `ia32` (`i686`) ve `x64` (`amd64`) Prebuilt mimarileri Ubuntu 12.04 üzerinde kurulmuştur, +`arm` mimarisi ARM v7 ye karşılık olarak, hard-float ABI ve NEON Debian Wheezy ile kurulmuştur. + +Prebuilt +Prebuilt mimarisi ancak Electron'nun yapı platformu ile bağlantılı olan kütüphaneleri içeren dağıtımlar ile çalışır. +Bu yüzden sadece Ubuntu 12.04 üzerinde çalışması garanti ediliyor, fakat aşagidaki platformlarında +Electron Prebuilt mimarisini çalıştıra bileceği doğrulanmıştır. + +* Ubuntu 12.04 ve sonrası +* Fedora 21 +* Debian 8 diff --git a/docs-translations/zh-CN/README.md b/docs-translations/zh-CN/README.md index 8d1fd8500d..706738d60d 100644 --- a/docs-translations/zh-CN/README.md +++ b/docs-translations/zh-CN/README.md @@ -26,6 +26,7 @@ * [使用 Widevine CDM 插件](tutorial/using-widevine-cdm-plugin.md) * [通过自动化持续集成系统(CI)进行测试 (Travis, Jenkins)](tutorial/testing-on-headless-ci.md) * [离屏渲染](tutorial/offscreen-rendering.md) +* [快捷键](tutorial/keyboard-shortcuts.md) ## 教程 @@ -96,3 +97,6 @@ * [调试步骤 (Windows)](development/debug-instructions-windows.md) * [在调试中使用 Symbol Server](development/setting-up-symbol-server.md) * [文档风格指南](styleguide.md) +* [升级 Chrome](development/upgrading-chrome.md) +* [Chromium 开发](development/chromium-development.md) +* [V8 开发](development/v8-development.md) diff --git a/docs-translations/zh-CN/api/accelerator.md b/docs-translations/zh-CN/api/accelerator.md index 0b1e2cd3f4..0e6d44b742 100644 --- a/docs-translations/zh-CN/api/accelerator.md +++ b/docs-translations/zh-CN/api/accelerator.md @@ -4,15 +4,30 @@ 例如: -* `Command+A` -* `Ctrl+Shift+Z` +* `CommandOrControl+A` +* `CommandOrControl+Shift+Z` + +快捷键使用 [`globalShortcut`](global-shortcut.md)里的 [`register`](global-shortcut.md#globalshortcutregisteraccelerator-callback) 方法注册 + +```javascript +const {app, globalShortcut} = require('electron') + +app.on('ready', () => { + // Register a 'CommandOrControl+Y' shortcut listener. + globalShortcut.register('CommandOrControl+Y', () => { + // Do stuff when Y and either Command/Control is pressed. + }) +}) +``` ## 运行平台相关的提示 在 Linux 和 Windows 上,`Command` 键并不存在,因此我们通常用 `CommandOrControl` 来表示“在 macOS 下为 `Command` 键,但在 Linux 和 Windows 下为 `Control` 键。 -`Super` 键是指 Linux 和 Windows 上的 `Windows` 键,但是在 macOS 下为 `Command` 键。 +使用 `Alt` 键 代替 `Option`。`Option` 键只在 macOS 系统上存在,而 `Alt` 键在任何系统上都有效。 + +`Super` 键是指 Linux 和 Windows 上的 `Windows` 键,但是在 macOS 下为 `Cmd` 键。 ## 可用的功能按键 @@ -20,6 +35,8 @@ Linux 和 Windows 下为 `Control` 键。 * `Control`(缩写为 `Ctrl`) * `CommandOrControl`(缩写为 `CmdOrCtrl`) * `Alt` +* `Option` +* `AltGr` * `Shift` * `Super` @@ -31,6 +48,7 @@ Linux 和 Windows 下为 `Control` 键。 * 类似与 `~`、`!`、`@`、`#`、`$` 的标点符号。 * `Plus` * `Space` +* `Tab` * `Backspace` * `Delete` * `Insert` @@ -41,3 +59,4 @@ Linux 和 Windows 下为 `Control` 键。 * `Escape`(缩写为 `Esc`) * `VolumeUp`、`VolumeDown` 和 `VolumeMute` * `MediaNextTrack`、`MediaPreviousTrack`、`MediaStop` 和 `MediaPlayPause` +* `PrintScreen` diff --git a/docs-translations/zh-CN/api/menu-item.md b/docs-translations/zh-CN/api/menu-item.md index c2091674a5..75c3b935fd 100644 --- a/docs-translations/zh-CN/api/menu-item.md +++ b/docs-translations/zh-CN/api/menu-item.md @@ -15,26 +15,24 @@ * `menuItem` MenuItem * `browserWindow` BrowserWindow * `event` Event - * `role` String (可选) - 定义菜单项的行为,在指定 `click` 属性时将会被忽略。 - * `type` String (可选) - 取值 `normal`, `separator`, `submenu`, `checkbox` or `radio`。 + * `role` String (可选) - 定义菜单项的行为,在指定 `click` 属性时将会被忽略。参见 [roles](#roles). + * `type` String (可选) - 取值 `normal`, `separator`, `submenu`, `checkbox` 或 `radio`。 * `label` String - (可选) * `sublabel` String - (可选) * `accelerator` [Accelerator](accelerator.md) (可选) * `icon` ([NativeImage](native-image.md) | String) (可选) * `enabled` Boolean (可选) - 如果为 false,菜单项将显示为灰色不可点击。 - unclickable. * `visible` Boolean (可选) - 如果为 false,菜单项将完全隐藏。 * `checked` Boolean (可选) - 只为 `checkbox` 或 `radio` 类型的菜单项。 * `submenu` (MenuItemConstructorOptions[] | Menu) (可选) - 应当作为 `submenu` 菜单项的特定类型,当它作为 `type: 'submenu'` 菜单项的特定类型时可以忽略。如果它的值不是 `Menu`,将自动转为 `Menu.buildFromTemplate`。 - * `id` String (可选) - 标志一个菜单的唯一性。如果被定义使用,它将被用作这个菜单项的参考位置属性。 + * `id` String (可选) - 菜单的唯一标识。如果被定义使用,它将被用作这个菜单项的参考位置属性。 * `position` String (可选) - 定义菜单的具体指定位置信息。 -在创建菜单项时,如果有匹配的方法,建议指定 `role` 属性, -而不是试图手动实现在一个 `click` 函数中的行为。 -内置的 `role` 行为将提供最好的原生体验。 +### Roles +Roles 允许菜单项有预定义的行为。最好为每个菜单项指定一个行为,而不是自己实现一个 `click` 函数中的行为。内置的 `role` 行为将提供最好的原生体验。 + +当使用 `role` 时,`label` 和 `accelerator` 的值是可选的,会针对每个平台设置默认值。 -当使用 `role' 时,`label' 和 `accelerator` 是可选的,默认为 -到每个平台的适当值。 `role`属性值可以为: @@ -56,6 +54,8 @@ * `resetzoom` - 将对焦页面的缩放级别重置为原始大小 * `zoomin` - 将聚焦页面缩小10% * `zoomout` - 将聚焦页面放大10% +* `editMenu` - 完整的默认 "Edit" 编辑菜单(拷贝,黏贴,等) +* `windowMenu` - 完整的默认 "Window" 窗口菜单(最小化,关闭,等) 在 macOS 上,`role` 还可以有以下值: diff --git a/docs-translations/zh-CN/api/menu.md b/docs-translations/zh-CN/api/menu.md index 5d31d62f1a..ebccfe5ee9 100644 --- a/docs-translations/zh-CN/api/menu.md +++ b/docs-translations/zh-CN/api/menu.md @@ -19,6 +19,8 @@ 在 macOS 上设置应用菜单 `menu`。 在 windows 和 linux,是为每个窗口都在其顶部设置菜单 `menu`。 +设置为 `null` 时,将在 Windows 和 Linux 上删除菜单条,但在 macOS 系统中无效。 + **注意:** 这个API必须在 `app` 模块的 `ready` 事件后调用。 #### `Menu.getApplicationMenu()` @@ -29,7 +31,7 @@ * `action` String -发送 `action` 给应用的第一个响应器.这个用来模仿 Cocoa 菜单的默认行为,通常你只需要使用 `MenuItem` 的属性 `role`. +发送 `action` 给应用的第一个响应器.这个用来模仿 Cocoa 菜单的默认行为,通常你只需要使用 [`MenuItem`](menu-item.md) 的属性 [`role`](menu-item.md#roles). 查看更多 macOS 的原生 action [macOS Cocoa Event Handling Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW7) . @@ -47,15 +49,23 @@ `menu` 对象有如下实例方法 -#### `menu.popup([browserWindow, x, y, positioningItem])` +#### `menu.popup([browserWindow, options])` -* `browserWindow` BrowserWindow (可选) - 默认为 `null`. -* `x` Number (可选) - 默认为 -1. -* `y` Number (**必须** 如果x设置了) - 默认为 -1. -* `positioningItem` Number (可选) _macOS_ - 在指定坐标鼠标位置下面的菜单项的索引. 默认为 +* `browserWindow` BrowserWindow (可选) - 默认为当前激活的窗口. +* `options` Object (可选) + * `x` Number (可选) - 默认为当前光标所在的位置. + * `y` Number (**必须** 如果x设置了) - 默认为当前光标所在的位置. + * `async` Boolean (可选) - 设置为 `true` 时,调用这个方法会立即返回。设置为 `false` 时,当菜单被选择或者被关闭时才会返回。默认为 `false`。 + * `positioningItem` Number (可选) _macOS_ - 指定坐标鼠标位置下面的菜单项的索引. 默认为 -1. -在 `browserWindow` 中弹出 context menu .你可以选择性地提供指定的 `x, y` 来设置菜单应该放在哪里,否则它将默认地放在当前鼠标的位置. +在 `browserWindow` 中弹出菜单. + +#### `menu.closePopup([browserWindow])` + +* `browserWindow` BrowserWindow (可选) - 默认为当前激活的窗口. + +在 `browserWindow` 关闭菜单. #### `menu.append(menuItem)` @@ -95,76 +105,36 @@ const template = [ { label: 'Edit', submenu: [ - { - role: 'undo' - }, - { - role: 'redo' - }, - { - type: 'separator' - }, - { - role: 'cut' - }, - { - role: 'copy' - }, - { - role: 'paste' - }, - { - role: 'pasteandmatchstyle' - }, - { - role: 'delete' - }, - { - role: 'selectall' - } + {role: 'undo'}, + {role: 'redo'}, + {type: 'separator'}, + {role: 'cut'}, + {role: 'copy'}, + {role: 'paste'}, + {role: 'pasteandmatchstyle'}, + {role: 'delete'}, + {role: 'selectall'} ] }, { label: 'View', submenu: [ - { - role: 'reload' - }, - { - role: 'forcereload' - }, - { - role: 'toggledevtools' - }, - { - type: 'separator' - }, - { - role: 'resetzoom' - }, - { - role: 'zoomin' - }, - { - role: 'zoomout' - }, - { - type: 'separator' - }, - { - role: 'togglefullscreen' - } + {role: 'reload'}, + {role: 'forcereload'}, + {role: 'toggledevtools'}, + {type: 'separator'}, + {role: 'resetzoom'}, + {role: 'zoomin'}, + {role: 'zoomout'}, + {type: 'separator'}, + {role: 'togglefullscreen'} ] }, { role: 'window', submenu: [ - { - role: 'minimize' - }, - { - role: 'close' - } + {role: 'minimize'}, + {role: 'close'} ] }, { @@ -182,76 +152,37 @@ if (process.platform === 'darwin') { template.unshift({ label: app.getName(), submenu: [ - { - role: 'about' - }, - { - type: 'separator' - }, - { - role: 'services', - submenu: [] - }, - { - type: 'separator' - }, - { - role: 'hide' - }, - { - role: 'hideothers' - }, - { - role: 'unhide' - }, - { - type: 'separator' - }, - { - role: 'quit' - } + {role: 'about'}, + {type: 'separator'}, + {role: 'services', submenu: []}, + {type: 'separator'}, + {role: 'hide'}, + {role: 'hideothers'}, + {role: 'unhide'}, + {type: 'separator'}, + {role: 'quit'} ] }) - // Edit menu. + + // Edit menu template[1].submenu.push( - { - type: 'separator' - }, + {type: 'separator'}, { label: 'Speech', submenu: [ - { - role: 'startspeaking' - }, - { - role: 'stopspeaking' - } + {role: 'startspeaking'}, + {role: 'stopspeaking'} ] } ) - // Window menu. + + // Window menu template[3].submenu = [ - { - label: 'Close', - accelerator: 'CmdOrCtrl+W', - role: 'close' - }, - { - label: 'Minimize', - accelerator: 'CmdOrCtrl+M', - role: 'minimize' - }, - { - label: 'Zoom', - role: 'zoom' - }, - { - type: 'separator' - }, - { - label: 'Bring All to Front', - role: 'front' - } + {role: 'close'}, + {role: 'minimize'}, + {role: 'zoom'}, + {type: 'separator'}, + {role: 'front'} ] } diff --git a/docs-translations/zh-CN/api/structures/bluetooth-device.md b/docs-translations/zh-CN/api/structures/bluetooth-device.md new file mode 100644 index 0000000000..2fa0c799a1 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/bluetooth-device.md @@ -0,0 +1,4 @@ +# 蓝牙设备 Object + +* `deviceName` String +* `deviceId` String diff --git a/docs-translations/zh-CN/api/structures/certificate-principal.md b/docs-translations/zh-CN/api/structures/certificate-principal.md new file mode 100644 index 0000000000..f4184e8faf --- /dev/null +++ b/docs-translations/zh-CN/api/structures/certificate-principal.md @@ -0,0 +1,8 @@ +# CertificatePrincipal Object + +* `commonName` String - 通用名 +* `organizations` String[] - 组织名 +* `organizationUnits` String[] - 组织单位名称 +* `locality` String - 地区 +* `state` String - 州或省 +* `country` String - 国家或地区 diff --git a/docs-translations/zh-CN/api/structures/certificate.md b/docs-translations/zh-CN/api/structures/certificate.md new file mode 100644 index 0000000000..546cefb42d --- /dev/null +++ b/docs-translations/zh-CN/api/structures/certificate.md @@ -0,0 +1,12 @@ +# Certificate Object 证书对象 + +* `data` String - PEM encoded data +* `issuer` [CertificatePrincipal](certificate-principal.md) - Issuer principal +* `issuerName` String - Issuer's Common Name +* `issuerCert` Certificate - Issuer certificate (if not self-signed) +* `subject` [CertificatePrincipal](certificate-principal.md) - Subject principal +* `subjectName` String - Subject's Common Name +* `serialNumber` String - Hex value represented string +* `validStart` Number - Start date of the certificate being valid in seconds +* `validExpiry` Number - End date of the certificate being valid in seconds +* `fingerprint` String - Fingerprint of the certificate diff --git a/docs-translations/zh-CN/api/structures/cookie.md b/docs-translations/zh-CN/api/structures/cookie.md new file mode 100644 index 0000000000..79f21e1080 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/cookie.md @@ -0,0 +1,12 @@ +# Cookie Object + +* `name` String - cookie 的名称. +* `value` String - cookie 的值. +* `domain` String (optional) - cookie 的域名. +* `hostOnly` Boolean (optional) - cookie 的类型是否为 host-only. +* `path` String (optional) - cookie 的路径. +* `secure` Boolean (optional) - cookie 是否标记为安全. +* `httpOnly` Boolean (optional) - cookie 是否只标记为 HTTP. +* `session` Boolean (optional) - cookie 是否是一个 session cookie, 还是一个带有过期时间的持续 cookie. +* `expirationDate` Double (optional) - cookie 距离 UNIX 时间戳的过期时间,数值为秒。不需要提供给 session + cookies. diff --git a/docs-translations/zh-CN/api/structures/crash-report.md b/docs-translations/zh-CN/api/structures/crash-report.md new file mode 100644 index 0000000000..f16b5acdb6 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/crash-report.md @@ -0,0 +1,4 @@ +# 崩溃报告的对象 + +* `date` String +* `ID` Integer diff --git a/docs-translations/zh-CN/api/structures/desktop-capturer-source.md b/docs-translations/zh-CN/api/structures/desktop-capturer-source.md new file mode 100644 index 0000000000..1ab3db1741 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/desktop-capturer-source.md @@ -0,0 +1,7 @@ +# DesktopCapturerSource Object + +* `id` String - 窗口或者屏幕的标识符,当调用 [`navigator.webkitGetUserMedia`] 时可以被当成 `chromeMediaSourceId` 使用。 +标识符的格式为`window:XX` 或 `screen:XX`,`XX` 是一个随机生成的数字. +* `name` String - 窗口的来源将被命名为 `Entire Screen` 或 `Screen `,而窗口来源的名字将会和窗口的标题匹配. +* `thumbnail` [NativeImage](../native-image.md) - 缩略图. **注:** 通过 `desktopCapturer.getSources` 方法, +不能保证缩略图的大小与 `options` 中指定的 `thumbnailSize` 相同。实际大小取决于窗口或者屏幕的比例。 diff --git a/docs-translations/zh-CN/api/structures/display.md b/docs-translations/zh-CN/api/structures/display.md new file mode 100644 index 0000000000..f5f5b9866b --- /dev/null +++ b/docs-translations/zh-CN/api/structures/display.md @@ -0,0 +1,15 @@ +# Display Object + +* `id` Number - Unique identifier associated with the display. +* `rotation` Number - Can be 0, 90, 180, 270, represents screen rotation in + clock-wise degrees. +* `scaleFactor` Number - Output device's pixel scale factor. +* `touchSupport` String - Can be `available`, `unavailable`, `unknown`. +* `bounds` [Rectangle](rectangle.md) +* `size` [Size](size.md) +* `workArea` [Rectangle](rectangle.md) +* `workAreaSize` [Size](size.md) + +The `Display` object represents a physical display connected to the system. A +fake `Display` may exist on a headless system, or a `Display` may correspond to +a remote, virtual display. diff --git a/docs-translations/zh-CN/api/structures/file-filter.md b/docs-translations/zh-CN/api/structures/file-filter.md new file mode 100644 index 0000000000..014350a60f --- /dev/null +++ b/docs-translations/zh-CN/api/structures/file-filter.md @@ -0,0 +1,4 @@ +# FileFilter Object + +* `name` String +* `extensions` String[] diff --git a/docs-translations/zh-CN/api/structures/jump-list-category.md b/docs-translations/zh-CN/api/structures/jump-list-category.md new file mode 100644 index 0000000000..07627e78c9 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/jump-list-category.md @@ -0,0 +1,21 @@ +# JumpListCategory Object + +* `type` String (optional) - One of the following: + * `tasks` - Items in this category will be placed into the standard `Tasks` + category. There can be only one such category, and it will always be + displayed at the bottom of the Jump List. + * `frequent` - Displays a list of files frequently opened by the app, the + name of the category and its items are set by Windows. + * `recent` - Displays a list of files recently opened by the app, the name + of the category and its items are set by Windows. Items may be added to + this category indirectly using `app.addRecentDocument(path)`. + * `custom` - Displays tasks or file links, `name` must be set by the app. +* `name` String (optional) - Must be set if `type` is `custom`, otherwise it should be + omitted. +* `items` JumpListItem[] (optional) - Array of [`JumpListItem`](jump-list-item.md) objects if `type` is `tasks` or + `custom`, otherwise it should be omitted. + +**Note:** If a `JumpListCategory` object has neither the `type` nor the `name` +property set then its `type` is assumed to be `tasks`. If the `name` property +is set but the `type` property is omitted then the `type` is assumed to be +`custom`. diff --git a/docs-translations/zh-CN/api/structures/jump-list-item.md b/docs-translations/zh-CN/api/structures/jump-list-item.md new file mode 100644 index 0000000000..f17d72e0a4 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/jump-list-item.md @@ -0,0 +1,28 @@ +# JumpListItem Object + +* `type` String (optional) - One of the following: + * `task` - A task will launch an app with specific arguments. + * `separator` - Can be used to separate items in the standard `Tasks` + category. + * `file` - A file link will open a file using the app that created the + Jump List, for this to work the app must be registered as a handler for + the file type (though it doesn't have to be the default handler). +* `path` String (optional) - Path of the file to open, should only be set if `type` is + `file`. +* `program` String (optional) - Path of the program to execute, usually you should + specify `process.execPath` which opens the current program. Should only be + set if `type` is `task`. +* `args` String (optional) - The command line arguments when `program` is executed. Should + only be set if `type` is `task`. +* `title` String (optional) - The text to be displayed for the item in the Jump List. + Should only be set if `type` is `task`. +* `description` String (optional) - Description of the task (displayed in a tooltip). + Should only be set if `type` is `task`. +* `iconPath` String (optional) - The absolute path to an icon to be displayed in a + Jump List, which can be an arbitrary resource file that contains an icon + (e.g. `.ico`, `.exe`, `.dll`). You can usually specify `process.execPath` to + show the program icon. +* `iconIndex` Number (optional) - The index of the icon in the resource file. If a + resource file contains multiple icons this value can be used to specify the + zero-based index of the icon that should be displayed for this task. If a + resource file contains only one icon, this property should be set to zero. diff --git a/docs-translations/zh-CN/api/structures/memory-usage-details.md b/docs-translations/zh-CN/api/structures/memory-usage-details.md new file mode 100644 index 0000000000..d77e07dedf --- /dev/null +++ b/docs-translations/zh-CN/api/structures/memory-usage-details.md @@ -0,0 +1,5 @@ +# MemoryUsageDetails Object + +* `count` Number +* `size` Number +* `liveSize` Number diff --git a/docs-translations/zh-CN/api/structures/mime-typed-buffer.md b/docs-translations/zh-CN/api/structures/mime-typed-buffer.md new file mode 100644 index 0000000000..08e5cd47a4 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/mime-typed-buffer.md @@ -0,0 +1,4 @@ +# MimeTypedBuffer Object + +* `mimeType` String - The mimeType of the Buffer that you are sending +* `data` Buffer - The actual Buffer content diff --git a/docs-translations/zh-CN/api/structures/point.md b/docs-translations/zh-CN/api/structures/point.md new file mode 100644 index 0000000000..69b87cbdf9 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/point.md @@ -0,0 +1,4 @@ +# Point Object + +* `x` Number +* `y` Number diff --git a/docs-translations/zh-CN/api/structures/rectangle.md b/docs-translations/zh-CN/api/structures/rectangle.md new file mode 100644 index 0000000000..0cd000699e --- /dev/null +++ b/docs-translations/zh-CN/api/structures/rectangle.md @@ -0,0 +1,6 @@ +# Rectangle Object + +* `x` Number - The x coordinate of the origin of the rectangle +* `y` Number - The y coordinate of the origin of the rectangle +* `width` Number +* `height` Number diff --git a/docs-translations/zh-CN/api/structures/remove-client-certificate.md b/docs-translations/zh-CN/api/structures/remove-client-certificate.md new file mode 100644 index 0000000000..7ec853f163 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/remove-client-certificate.md @@ -0,0 +1,5 @@ +# RemoveClientCertificate Object + +* `type` String - `clientCertificate`. +* `origin` String - Origin of the server whose associated client certificate + must be removed from the cache. diff --git a/docs-translations/zh-CN/api/structures/remove-password.md b/docs-translations/zh-CN/api/structures/remove-password.md new file mode 100644 index 0000000000..28a9ed8ae1 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/remove-password.md @@ -0,0 +1,15 @@ +# RemovePassword Object + +* `type` String - `password`. +* `origin` String (optional) - When provided, the authentication info + related to the origin will only be removed otherwise the entire cache + will be cleared. +* `scheme` String (optional) - Scheme of the authentication. + Can be `basic`, `digest`, `ntlm`, `negotiate`. Must be provided if + removing by `origin`. +* `realm` String (optional) - Realm of the authentication. Must be provided if + removing by `origin`. +* `username` String (optional) - Credentials of the authentication. Must be + provided if removing by `origin`. +* `password` String (optional) - Credentials of the authentication. Must be + provided if removing by `origin`. diff --git a/docs-translations/zh-CN/api/structures/scrubber-item.md b/docs-translations/zh-CN/api/structures/scrubber-item.md new file mode 100644 index 0000000000..0dd3c4ff0f --- /dev/null +++ b/docs-translations/zh-CN/api/structures/scrubber-item.md @@ -0,0 +1,4 @@ +# ScrubberItem Object + +* `label` String - (Optional) The text to appear in this item +* `icon` NativeImage - (Optional) The image to appear in this item diff --git a/docs-translations/zh-CN/api/structures/segmented-control-segment.md b/docs-translations/zh-CN/api/structures/segmented-control-segment.md new file mode 100644 index 0000000000..ae01a07f32 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/segmented-control-segment.md @@ -0,0 +1,5 @@ +# SegmentedControlSegment Object + +* `label` String - (Optional) The text to appear in this segment +* `icon` NativeImage - (Optional) The image to appear in this segment +* `enabled` Boolean - (Optional) Whether this segment is selectable. Default: true diff --git a/docs-translations/zh-CN/api/structures/shortcut-details.md b/docs-translations/zh-CN/api/structures/shortcut-details.md new file mode 100644 index 0000000000..e7b272d099 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/shortcut-details.md @@ -0,0 +1,15 @@ +# ShortcutDetails Object + +* `target` String - The target to launch from this shortcut. +* `cwd` String (optional) - The working directory. Default is empty. +* `args` String (optional) - The arguments to be applied to `target` when +launching from this shortcut. Default is empty. +* `description` String (optional) - The description of the shortcut. Default +is empty. +* `icon` String (optional) - The path to the icon, can be a DLL or EXE. `icon` +and `iconIndex` have to be set together. Default is empty, which uses the +target's icon. +* `iconIndex` Number (optional) - The resource ID of icon when `icon` is a +DLL or EXE. Default is 0. +* `appUserModelId` String (optional) - The Application User Model ID. Default +is empty. diff --git a/docs-translations/zh-CN/api/structures/size.md b/docs-translations/zh-CN/api/structures/size.md new file mode 100644 index 0000000000..1d9c8b1f5a --- /dev/null +++ b/docs-translations/zh-CN/api/structures/size.md @@ -0,0 +1,4 @@ +# Size Object + +* `width` Number +* `height` Number diff --git a/docs-translations/zh-CN/api/structures/task.md b/docs-translations/zh-CN/api/structures/task.md new file mode 100644 index 0000000000..61a28de879 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/task.md @@ -0,0 +1,14 @@ +# Task Object + +* `program` String - Path of the program to execute, usually you should + specify `process.execPath` which opens the current program. +* `arguments` String - The command line arguments when `program` is + executed. +* `title` String - The string to be displayed in a JumpList. +* `description` String - Description of this task. +* `iconPath` String - The absolute path to an icon to be displayed in a + JumpList, which can be an arbitrary resource file that contains an icon. You + can usually specify `process.execPath` to show the icon of the program. +* `iconIndex` Number - The icon index in the icon file. If an icon file + consists of two or more icons, set this value to identify the icon. If an + icon file consists of one icon, this value is 0. diff --git a/docs-translations/zh-CN/api/structures/thumbar-button.md b/docs-translations/zh-CN/api/structures/thumbar-button.md new file mode 100644 index 0000000000..259195852a --- /dev/null +++ b/docs-translations/zh-CN/api/structures/thumbar-button.md @@ -0,0 +1,21 @@ +# ThumbarButton Object + +* `icon` [NativeImage](../native-image.md) - The icon showing in thumbnail + toolbar. +* `click` Function +* `tooltip` String (optional) - The text of the button's tooltip. +* `flags` String[] (optional) - Control specific states and behaviors of the + button. By default, it is `['enabled']`. + +The `flags` is an array that can include following `String`s: + +* `enabled` - The button is active and available to the user. +* `disabled` - The button is disabled. It is present, but has a visual state + indicating it will not respond to user action. +* `dismissonclick` - When the button is clicked, the thumbnail window closes + immediately. +* `nobackground` - Do not draw a button border, use only the image. +* `hidden` - The button is not shown to the user. +* `noninteractive` - The button is enabled but not interactive; no pressed + button state is drawn. This value is intended for instances where the button + is used in a notification. diff --git a/docs-translations/zh-CN/api/structures/upload-blob.md b/docs-translations/zh-CN/api/structures/upload-blob.md new file mode 100644 index 0000000000..be93cacb49 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/upload-blob.md @@ -0,0 +1,4 @@ +# UploadBlob Object + +* `type` String - `blob`. +* `blobUUID` String - UUID of blob data to upload. diff --git a/docs-translations/zh-CN/api/structures/upload-data.md b/docs-translations/zh-CN/api/structures/upload-data.md new file mode 100644 index 0000000000..8e5c07725a --- /dev/null +++ b/docs-translations/zh-CN/api/structures/upload-data.md @@ -0,0 +1,6 @@ +# UploadData Object + +* `bytes` Buffer - Content being sent. +* `file` String - Path of file being uploaded. +* `blobUUID` String - UUID of blob data. Use [ses.getBlobData](../session.md#sesgetblobdataidentifier-callback) method + to retrieve the data. diff --git a/docs-translations/zh-CN/api/structures/upload-file-system.md b/docs-translations/zh-CN/api/structures/upload-file-system.md new file mode 100644 index 0000000000..d62b0a8ba7 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/upload-file-system.md @@ -0,0 +1,9 @@ +# UploadFileSystem Object + +* `type` String - `fileSystem`. +* `filsSystemURL` String - FileSystem url to read data for upload. +* `offset` Integer - Defaults to `0`. +* `length` Integer - Number of bytes to read from `offset`. + Defaults to `0`. +* `modificationTime` Double - Last Modification time in + number of seconds sine the UNIX epoch. diff --git a/docs-translations/zh-CN/api/structures/upload-file.md b/docs-translations/zh-CN/api/structures/upload-file.md new file mode 100644 index 0000000000..8a21973014 --- /dev/null +++ b/docs-translations/zh-CN/api/structures/upload-file.md @@ -0,0 +1,9 @@ +# UploadFile Object + +* `type` String - `file`. +* `filePath` String - Path of file to be uploaded. +* `offset` Integer - Defaults to `0`. +* `length` Integer - Number of bytes to read from `offset`. + Defaults to `0`. +* `modificationTime` Double - Last Modification time in + number of seconds sine the UNIX epoch. diff --git a/docs-translations/zh-CN/api/structures/upload-raw-data.md b/docs-translations/zh-CN/api/structures/upload-raw-data.md new file mode 100644 index 0000000000..4fe162311f --- /dev/null +++ b/docs-translations/zh-CN/api/structures/upload-raw-data.md @@ -0,0 +1,4 @@ +# UploadRawData Object + +* `type` String - `rawData`. +* `bytes` Buffer - Data to be uploaded. diff --git a/docs-translations/zh-CN/tutorial/windows-store-guide.md b/docs-translations/zh-CN/tutorial/windows-store-guide.md index 67cd39e5a5..a34f40d2ee 100644 --- a/docs-translations/zh-CN/tutorial/windows-store-guide.md +++ b/docs-translations/zh-CN/tutorial/windows-store-guide.md @@ -49,8 +49,7 @@ npm install -g electron-windows-store │   └── atom.asar ├── snapshot_blob.bin ├── squirrel.exe -├── ui_resources_200_percent.pak -└── xinput1_3.dll +└── ui_resources_200_percent.pak ``` ## 步骤 2: 运行 electron-windows-store diff --git a/docs/README.md b/docs/README.md index 24b23f92a7..e36eef9dd2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -103,6 +103,6 @@ an issue: * [Debug Instructions (Windows)](development/debug-instructions-windows.md) * [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md) * [Documentation Styleguide](styleguide.md) -* [Updating Chrome](development/updating-chrome.md) +* [Upgrading Chrome](development/upgrading-chrome.md) * [Chromium Development](development/chromium-development.md) * [V8 Development](development/v8-development.md) diff --git a/docs/api/browser-view.md b/docs/api/browser-view.md new file mode 100644 index 0000000000..3b7e6f9b9b --- /dev/null +++ b/docs/api/browser-view.md @@ -0,0 +1,74 @@ +## Class: BrowserView + +> Create and control views. + +**Note:** The BrowserView API is currently experimental and may change or be +removed in future Electron releases. + +Process: [Main](../glossary.md#main-process) + +A `BrowserView` can be used to embed additional web content into a +`BrowserWindow`. It is like a child window, except that it is positioned +relative to its owning window. It is meant to be an alternative to the +`webview` tag. + +## Example + +```javascript +// In the main process. +const {BrowserView, BrowserWindow} = require('electron') + +let win = new BrowserWindow({width: 800, height: 600}) +win.on('closed', () => { + win = null +}) + +let view = new BrowserView({ + webPreferences: { + nodeIntegration: false + } +}) +win.addChildView(view) +view.setBounds(0, 0, 300, 300) +view.webContents.loadURL('https://electron.atom.io') +``` + +### `new BrowserView([options])` _Experimental_ + +* `options` Object (optional) + * `webPreferences` Object (optional) - See [BrowserWindow](browser-window.md). + +### Instance Properties + +Objects created with `new BrowserView` have the following properties: + +#### `view.webContents` _Experimental_ + +A [`webContents`](web-contents.md) object owned by this view. + +#### `win.id` _Experimental_ + +A `Integer` representing the unique ID of the view. + +### Instance Methods + +Objects created with `new BrowserWindow` have the following instance methods: + +#### `win.setAutoResize(options)` _Experimental_ + +* `options` Object + * `width`: If `true`, the view's width will grow and shrink together with + the window. `false` by default. + * `height`: If `true`, the view's height will grow and shrink together with + the window. `false` by default. + +#### `win.setBounds(bounds)` _Experimental_ + +* `bounds` [Rectangle](structures/rectangle.md) + +Resizes and moves the view to the supplied bounds relative to the window. + +#### `win.setBackgroundColor(color)` _Experimental_ + +* `color` String - Color in `#aarrggbb` or `#argb` form. The alpha channel is + optional. diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 2eacb865ad..3bf9c1fb1a 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -683,10 +683,8 @@ Returns `Boolean` - Whether the window is in fullscreen mode. * `aspectRatio` Float - The aspect ratio to maintain for some portion of the content view. -* `extraSize` Object (optional) - The extra size not to be included while +* `extraSize` [Size](structures/size.md) - The extra size not to be included while maintaining the aspect ratio. - * `width` Integer - * `height` Integer This will make a window maintain an aspect ratio. The extra size allows a developer to have space, specified in pixels, not included within the aspect @@ -1292,6 +1290,13 @@ machine has a touch bar and is running on macOS 10.12.1+. **Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases. +#### `win.setBrowserView(browserView)` _Experimental_ + +* `browserView` [BrowserView](browser-view.md) + +**Note:** The BrowserView API is currently experimental and may change or be +removed in future Electron releases. + [blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5?l=62 [quick-look]: https://en.wikipedia.org/wiki/Quick_Look [vibrancy-docs]: https://developer.apple.com/reference/appkit/nsvisualeffectview?language=objc diff --git a/docs/api/desktop-capturer.md b/docs/api/desktop-capturer.md index f552753445..00542f402f 100644 --- a/docs/api/desktop-capturer.md +++ b/docs/api/desktop-capturer.md @@ -60,9 +60,8 @@ The `desktopCapturer` module has the following methods: * `options` Object * `types` String[] - An array of Strings that lists the types of desktop sources to be captured, available types are `screen` and `window`. - * `thumbnailSize` Object (optional) - The size that the media source thumbnail should be scaled to. - * `width` Integer - Default is `150` - * `height` Integer - Default is `150` + * `thumbnailSize` [Size](structures/size.md) (optional) - The size that the media source thumbnail + should be scaled to. Default is `150` x `150`. * `callback` Function * `error` Error * `sources` [DesktopCapturerSource[]](structures/desktop-capturer-source.md) diff --git a/docs/api/dialog.md b/docs/api/dialog.md index 8885c31514..615e3b2c6f 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -115,8 +115,9 @@ will be passed via `callback(filename)` * `browserWindow` BrowserWindow (optional) * `options` Object * `type` String (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or - `"warning"`. On Windows, "question" displays the same icon as "info", unless - you set an icon using the "icon" option. + `"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless + you set an icon using the `"icon"` option. On macOS, both `"warning"` and + `"error"` display the same warning icon. * `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK". * `defaultId` Integer (optional) - Index of the button in the buttons array which will @@ -175,6 +176,20 @@ it is usually used to report errors in early stage of startup. If called before the app `ready`event on Linux, the message will be emitted to stderr, and no GUI dialog will appear. +### `dialog.showCertificateTrustDialog([browserWindow, ]options, callback)` _macOS_ + +* `browserWindow` BrowserWindow (optional) +* `options` Object + * `certificate` [Certificate](structures/certificate.md) - The certificate to trust/import. + * `message` String - The message to display to the user. +* `callback` Function + +Displays a modal dialog that shows a message and certificate information, and +gives the user the option of trusting/importing the certificate. + +The `browserWindow` argument allows the dialog to attach itself to a parent +window, making it modal. + ## Sheets On macOS, dialogs are presented as sheets attached to a window if you provide diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 3ef5cdc93e..4f091ec6c3 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -98,6 +98,8 @@ By default, the frameless window is non-draggable. Apps need to specify `-webkit-app-region: no-drag` to exclude the non-draggable area from the draggable region. Note that only rectangular shapes are currently supported. +Note: `-webkit-app-region: drag` is known to have problems while the developer tools are open. See this [GitHub issue](https://github.com/electron/electron/issues/3647) for more information including a workaround. + To make the whole window draggable, you can add `-webkit-app-region: drag` as `body`'s style: diff --git a/docs/api/menu.md b/docs/api/menu.md index 42724e1d4a..72d8164270 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -16,8 +16,11 @@ The `menu` class has the following static methods: * `menu` Menu -Sets `menu` as the application menu on macOS. On Windows and Linux, the `menu` -will be set as each window's top menu. +Sets `menu` as the application menu on macOS. On Windows and Linux, the +`menu` will be set as each window's top menu. + +Passing `null` will remove the menu bar on Windows and Linux but has no +effect on macOS. **Note:** This API has to be called after the `ready` event of `app` module. diff --git a/docs/api/native-image.md b/docs/api/native-image.md index 100fb0e1a2..da496436b3 100644 --- a/docs/api/native-image.md +++ b/docs/api/native-image.md @@ -219,10 +219,7 @@ Returns `Boolean` - Whether the image is empty. #### `image.getSize()` -Returns `Object`: - -* `width` Integer -* `height` Integer +Returns [`Size`](structures/size.md) #### `image.setTemplateImage(option)` @@ -236,11 +233,7 @@ Returns `Boolean` - Whether the image is a template image. #### `image.crop(rect)` -* `rect` Object - The area of the image to crop - * `x` Integer - * `y` Integer - * `width` Integer - * `height` Integer +* `rect` [Rectangle](structures/rectangle.md) - The area of the image to crop Returns `NativeImage` - The cropped image. diff --git a/docs/api/screen.md b/docs/api/screen.md index 9704f88134..49f0d9f55c 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -91,10 +91,7 @@ The `screen` module has the following methods: ### `screen.getCursorScreenPoint()` -Returns `Object`: - -* `x` Integer -* `y` Integer +Returns [`Point`](structures/point.md) The current absolute position of the mouse pointer. @@ -108,9 +105,7 @@ Returns [`Display[]`](structures/display.md) - An array of displays that are cur ### `screen.getDisplayNearestPoint(point)` -* `point` Object - * `x` Integer - * `y` Integer +* `point` [Point](structures/point.md) Returns [`Display`](structures/display.md) - The display nearest the specified point. diff --git a/docs/api/session.md b/docs/api/session.md index 7c7831c8ac..7f24937295 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -287,7 +287,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => { #### `ses.setPermissionRequestHandler(handler)` * `handler` Function - * `webContents` Object - [WebContents](web-contents.md) requesting the permission. + * `webContents` [WebContents](web-contents.md) - WebContents requesting the permission. * `permission` String - Enum of 'media', 'geolocation', 'notifications', 'midiSysex', 'pointerLock', 'fullscreen', 'openExternal'. * `callback` Function @@ -388,15 +388,15 @@ The following properties are available on instances of `Session`: #### `ses.cookies` -A Cookies object for this session. +A [Cookies](cookies.md) object for this session. #### `ses.webRequest` -A WebRequest object for this session. +A [WebRequest](web-request.md) object for this session. #### `ses.protocol` -A Protocol object (an instance of [protocol](protocol.md) module) for this session. +A [Protocol](protocol.md) object for this session. ```javascript const {app, session} = require('electron') diff --git a/docs/api/structures/display.md b/docs/api/structures/display.md index d702b35a1b..f5f5b9866b 100644 --- a/docs/api/structures/display.md +++ b/docs/api/structures/display.md @@ -6,13 +6,9 @@ * `scaleFactor` Number - Output device's pixel scale factor. * `touchSupport` String - Can be `available`, `unavailable`, `unknown`. * `bounds` [Rectangle](rectangle.md) -* `size` Object - * `height` Number - * `width` Number +* `size` [Size](size.md) * `workArea` [Rectangle](rectangle.md) -* `workAreaSize` Object - * `height` Number - * `width` Number +* `workAreaSize` [Size](size.md) The `Display` object represents a physical display connected to the system. A fake `Display` may exist on a headless system, or a `Display` may correspond to diff --git a/docs/api/structures/mime-typed-buffer.md b/docs/api/structures/mime-typed-buffer.md index dc1a20d28f..08e5cd47a4 100644 --- a/docs/api/structures/mime-typed-buffer.md +++ b/docs/api/structures/mime-typed-buffer.md @@ -1,4 +1,4 @@ # MimeTypedBuffer Object * `mimeType` String - The mimeType of the Buffer that you are sending -* `buffer` Buffer - The actual Buffer content +* `data` Buffer - The actual Buffer content diff --git a/docs/api/structures/point.md b/docs/api/structures/point.md new file mode 100644 index 0000000000..69b87cbdf9 --- /dev/null +++ b/docs/api/structures/point.md @@ -0,0 +1,4 @@ +# Point Object + +* `x` Number +* `y` Number diff --git a/docs/api/structures/size.md b/docs/api/structures/size.md new file mode 100644 index 0000000000..1d9c8b1f5a --- /dev/null +++ b/docs/api/structures/size.md @@ -0,0 +1,4 @@ +# Size Object + +* `width` Number +* `height` Number diff --git a/docs/api/touch-bar.md b/docs/api/touch-bar.md index 7eb2eb0209..7ac578da46 100644 --- a/docs/api/touch-bar.md +++ b/docs/api/touch-bar.md @@ -4,9 +4,11 @@ Process: [Main](../tutorial/quick-start.md#main-process) -### `new TouchBar(items)` _Experimental_ +### `new TouchBar(options)` _Experimental_ -* `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] +* `options` - Object + * `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] + * `escapeItem` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md)) (optional) Creates a new touch bar with the specified items. Use `BrowserWindow.setTouchBar` to add the `TouchBar` to a window. @@ -14,6 +16,16 @@ Creates a new touch bar with the specified items. Use **Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases. +### Instance Properties + +The following properties are available on instances of `TouchBar`: + +#### `touchBar.escapeItem` + +The `TouchBarItem` that will replace the "esc" button on the touch bar when set. +Setting to `null` restores the default "esc" button. Changing this value +immediately updates the escape item in the touch bar. + ## Examples Below is an example of a simple slot machine touch bar game with a button diff --git a/docs/api/tray.md b/docs/api/tray.md index 0be9702986..141b24bbbf 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -219,9 +219,7 @@ Displays a tray balloon. #### `tray.popUpContextMenu([menu, position])` _macOS_ _Windows_ * `menu` Menu (optional) -* `position` Object (optional) - The pop up position. - * `x` Integer - * `y` Integer +* `position` [Point](structures/point.md) (optional) - The pop up position. Pops up the context menu of the tray icon. When `menu` is passed, the `menu` will be shown instead of the tray icon's context menu. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 87530234a2..98b1cbd2f2 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -375,12 +375,8 @@ Returns: * `type` String * `image` NativeImage (optional) * `scale` Float (optional) - scaling factor for the custom cursor -* `size` Object (optional) - the size of the `image` - * `width` Integer - * `height` Integer -* `hotspot` Object (optional) - coordinates of the custom cursor's hotspot - * `x` Integer - x coordinate - * `y` Integer - y coordinate +* `size` [Size](structures/size.md) (optional) - the size of the `image` +* `hotspot` [Point](structures/point.md) (optional) - coordinates of the custom cursor's hotspot Emitted when the cursor's type changes. The `type` parameter can be `default`, `crosshair`, `pointer`, `text`, `wait`, `help`, `e-resize`, `n-resize`, @@ -1067,24 +1063,16 @@ app.on('ready', () => { (default: `desktop`) * `desktop` - Desktop screen type * `mobile` - Mobile screen type - * `screenSize` Object - Set the emulated screen size (screenPosition == mobile) - * `width` Integer - Set the emulated screen width - * `height` Integer - Set the emulated screen height - * `viewPosition` Object - Position the view on the screen + * `screenSize` [Size](structures/size.md) - Set the emulated screen size (screenPosition == mobile) + * `viewPosition` [Point](structures/point.md) - Position the view on the screen (screenPosition == mobile) (default: `{x: 0, y: 0}`) - * `x` Integer - Set the x axis offset from top left corner - * `y` Integer - Set the y axis offset from top left corner * `deviceScaleFactor` Integer - Set the device scale factor (if zero defaults to original device scale factor) (default: `0`) - * `viewSize` Object - Set the emulated view size (empty means no override) - * `width` Integer - Set the emulated view width - * `height` Integer - Set the emulated view height + * `viewSize` [Size](structures/size.md) - Set the emulated view size (empty means no override) * `fitToView` Boolean - Whether emulated view should be scaled down if necessary to fit into available space (default: `false`) - * `offset` Object - Offset of the emulated view inside available space (not in - fit to view mode) (default: `{x: 0, y: 0}`) - * `x` Float - Set the x axis offset from top left corner - * `y` Float - Set the y axis offset from top left corner + * `offset` [Point](structures/point.md) - Offset of the emulated view inside available space + (not in fit to view mode) (default: `{x: 0, y: 0}`) * `scale` Float - Scale of emulated view inside available space (not in fit to view mode) (default: `1`) diff --git a/docs/api/web-request.md b/docs/api/web-request.md index 6da98d81f1..a271add9da 100644 --- a/docs/api/web-request.md +++ b/docs/api/web-request.md @@ -42,6 +42,8 @@ The following methods are available on instances of `WebRequest`: #### `webRequest.onBeforeRequest([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function * `details` Object * `id` Integer @@ -66,6 +68,8 @@ The `callback` has to be called with an `response` object. #### `webRequest.onBeforeSendHeaders([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function The `listener` will be called with `listener(details, callback)` before sending @@ -90,6 +94,8 @@ The `callback` has to be called with an `response` object. #### `webRequest.onSendHeaders([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function * `details` Object * `id` Integer @@ -106,6 +112,8 @@ response are visible by the time this listener is fired. #### `webRequest.onHeadersReceived([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function The `listener` will be called with `listener(details, callback)` when HTTP @@ -134,6 +142,8 @@ The `callback` has to be called with an `response` object. #### `webRequest.onResponseStarted([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function * `details` Object * `id` Integer @@ -154,6 +164,8 @@ and response headers are available. #### `webRequest.onBeforeRedirect([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function * `details` Object * `id` String @@ -174,6 +186,8 @@ redirect is about to occur. #### `webRequest.onCompleted([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function * `details` Object * `id` Integer @@ -192,6 +206,8 @@ completed. #### `webRequest.onErrorOccurred([filter, ]listener)` * `filter` Object + * `urls` String[] - Array of URL patterns that will be used to filter out the + requests that do not match the URL patterns. * `listener` Function * `details` Object * `id` Integer diff --git a/docs/tutorial/windows-store-guide.md b/docs/tutorial/windows-store-guide.md index 4cca798aec..abf9643181 100644 --- a/docs/tutorial/windows-store-guide.md +++ b/docs/tutorial/windows-store-guide.md @@ -69,8 +69,7 @@ The output should look roughly like this: │   └── atom.asar ├── snapshot_blob.bin ├── squirrel.exe -├── ui_resources_200_percent.pak -└── xinput1_3.dll +└── ui_resources_200_percent.pak ``` ## Step 2: Running electron-windows-store diff --git a/electron.gyp b/electron.gyp index 3dec2ee8a0..8c3718b1cd 100644 --- a/electron.gyp +++ b/electron.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '1.6.5', + 'version%': '1.6.6', 'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c', }, 'includes': [ @@ -126,7 +126,17 @@ 'VCManifestTool': { 'EmbedManifest': 'true', 'AdditionalManifestFiles': 'atom/browser/resources/win/atom.manifest', - } + }, + 'VCLinkerTool': { + # Chrome builds with this minimum environment which makes e.g. + # GetSystemMetrics(SM_CXSIZEFRAME) return Windows XP/2003 + # compatible metrics. See: https://crbug.com/361720 + # + # The following two settings translate to a linker flag + # of /SUBSYSTEM:WINDOWS,5.02 + 'MinimumRequiredVersion': '5.02', + 'SubSystem': '2', + }, }, 'copies': [ { @@ -159,7 +169,6 @@ '<(libchromiumcontent_dir)/natives_blob.bin', '<(libchromiumcontent_dir)/snapshot_blob.bin', 'external_binaries/d3dcompiler_47.dll', - 'external_binaries/xinput1_3.dll', ], }, ], @@ -447,6 +456,8 @@ '-r', './lib/sandboxed_renderer/api/exports/os.js:os', '-r', + './lib/sandboxed_renderer/api/exports/path.js:path', + '-r', './lib/sandboxed_renderer/api/exports/child_process.js:child_process' ], 'isolated_args': [ @@ -549,6 +560,8 @@ '$(SDKROOT)/System/Library/Frameworks/Carbon.framework', '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', '$(SDKROOT)/System/Library/Frameworks/Quartz.framework', + '$(SDKROOT)/System/Library/Frameworks/Security.framework', + '$(SDKROOT)/System/Library/Frameworks/SecurityInterface.framework', ], }, 'mac_bundle': 1, diff --git a/filenames.gypi b/filenames.gypi index f872c2830f..b007e38d93 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -13,23 +13,24 @@ 'lib/browser/api/auto-updater/auto-updater-native.js', 'lib/browser/api/auto-updater/auto-updater-win.js', 'lib/browser/api/auto-updater/squirrel-update-win.js', + 'lib/browser/api/browser-view.js', 'lib/browser/api/browser-window.js', 'lib/browser/api/content-tracing.js', 'lib/browser/api/dialog.js', 'lib/browser/api/exports/electron.js', 'lib/browser/api/global-shortcut.js', 'lib/browser/api/ipc-main.js', - 'lib/browser/api/menu.js', - 'lib/browser/api/menu-item.js', 'lib/browser/api/menu-item-roles.js', + 'lib/browser/api/menu-item.js', + 'lib/browser/api/menu.js', 'lib/browser/api/module-list.js', 'lib/browser/api/navigation-controller.js', 'lib/browser/api/net.js', 'lib/browser/api/power-monitor.js', 'lib/browser/api/power-save-blocker.js', 'lib/browser/api/protocol.js', - 'lib/browser/api/session.js', 'lib/browser/api/screen.js', + 'lib/browser/api/session.js', 'lib/browser/api/system-preferences.js', 'lib/browser/api/touch-bar.js', 'lib/browser/api/tray.js', @@ -103,6 +104,8 @@ 'atom/browser/api/atom_api_app.h', 'atom/browser/api/atom_api_auto_updater.cc', 'atom/browser/api/atom_api_auto_updater.h', + 'atom/browser/api/atom_api_browser_view.cc', + 'atom/browser/api/atom_api_browser_view.h', 'atom/browser/api/atom_api_content_tracing.cc', 'atom/browser/api/atom_api_cookies.cc', 'atom/browser/api/atom_api_cookies.h', @@ -110,27 +113,27 @@ 'atom/browser/api/atom_api_debugger.h', 'atom/browser/api/atom_api_desktop_capturer.cc', 'atom/browser/api/atom_api_desktop_capturer.h', + 'atom/browser/api/atom_api_dialog.cc', 'atom/browser/api/atom_api_download_item.cc', 'atom/browser/api/atom_api_download_item.h', - 'atom/browser/api/atom_api_dialog.cc', 'atom/browser/api/atom_api_global_shortcut.cc', 'atom/browser/api/atom_api_global_shortcut.h', 'atom/browser/api/atom_api_menu.cc', 'atom/browser/api/atom_api_menu.h', - 'atom/browser/api/atom_api_menu_views.cc', - 'atom/browser/api/atom_api_menu_views.h', 'atom/browser/api/atom_api_menu_mac.h', 'atom/browser/api/atom_api_menu_mac.mm', + 'atom/browser/api/atom_api_menu_views.cc', + 'atom/browser/api/atom_api_menu_views.h', 'atom/browser/api/atom_api_net.cc', 'atom/browser/api/atom_api_net.h', 'atom/browser/api/atom_api_power_monitor.cc', 'atom/browser/api/atom_api_power_monitor.h', 'atom/browser/api/atom_api_power_save_blocker.cc', 'atom/browser/api/atom_api_power_save_blocker.h', - 'atom/browser/api/atom_api_render_process_preferences.cc', - 'atom/browser/api/atom_api_render_process_preferences.h', 'atom/browser/api/atom_api_protocol.cc', 'atom/browser/api/atom_api_protocol.h', + 'atom/browser/api/atom_api_render_process_preferences.cc', + 'atom/browser/api/atom_api_render_process_preferences.h', 'atom/browser/api/atom_api_screen.cc', 'atom/browser/api/atom_api_screen.h', 'atom/browser/api/atom_api_session.cc', @@ -218,6 +221,12 @@ 'atom/browser/mac/atom_application_delegate.mm', 'atom/browser/mac/dict_util.h', 'atom/browser/mac/dict_util.mm', + 'atom/browser/native_browser_view.cc', + 'atom/browser/native_browser_view.h', + 'atom/browser/native_browser_view_mac.h', + 'atom/browser/native_browser_view_mac.mm', + 'atom/browser/native_browser_view_views.h', + 'atom/browser/native_browser_view_views.cc', 'atom/browser/native_window.cc', 'atom/browser/native_window.h', 'atom/browser/native_window_views_win.cc', @@ -281,6 +290,8 @@ 'atom/browser/ui/accelerator_util_views.cc', 'atom/browser/ui/atom_menu_model.cc', 'atom/browser/ui/atom_menu_model.h', + 'atom/browser/ui/certificate_trust.h', + 'atom/browser/ui/certificate_trust_mac.mm', 'atom/browser/ui/cocoa/atom_menu_controller.h', 'atom/browser/ui/cocoa/atom_menu_controller.mm', 'atom/browser/ui/cocoa/atom_touch_bar.h', @@ -313,8 +324,6 @@ 'atom/browser/ui/views/menu_bar.h', 'atom/browser/ui/views/menu_delegate.cc', 'atom/browser/ui/views/menu_delegate.h', - 'atom/browser/ui/views/menu_layout.cc', - 'atom/browser/ui/views/menu_layout.h', 'atom/browser/ui/views/menu_model_adapter.cc', 'atom/browser/ui/views/menu_model_adapter.h', 'atom/browser/ui/views/native_frame_view.cc', @@ -468,6 +477,8 @@ 'atom/renderer/api/atom_api_spell_check_client.h', 'atom/renderer/api/atom_api_web_frame.cc', 'atom/renderer/api/atom_api_web_frame.h', + 'atom/renderer/atom_render_frame_observer.cc', + 'atom/renderer/atom_render_frame_observer.h', 'atom/renderer/atom_render_view_observer.cc', 'atom/renderer/atom_render_view_observer.h', 'atom/renderer/atom_renderer_client.cc', diff --git a/lib/browser/api/browser-view.js b/lib/browser/api/browser-view.js new file mode 100644 index 0000000000..60023fef92 --- /dev/null +++ b/lib/browser/api/browser-view.js @@ -0,0 +1,8 @@ +'use strict' + +const {EventEmitter} = require('events') +const {BrowserView} = process.atomBinding('browser_view') + +Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype) + +module.exports = BrowserView diff --git a/lib/browser/api/dialog.js b/lib/browser/api/dialog.js index 834a6a6d7d..9644618047 100644 --- a/lib/browser/api/dialog.js +++ b/lib/browser/api/dialog.js @@ -280,6 +280,27 @@ module.exports = { showErrorBox: function (...args) { return binding.showErrorBox(...args) + }, + + showCertificateTrustDialog: function (...args) { + let [window, options, callback] = parseArgs(...args) + + if (options == null || typeof options !== 'object') { + throw new TypeError('options must be an object') + } + + let {certificate, message} = options + if (certificate == null || typeof certificate !== 'object') { + throw new TypeError('certificate must be an object') + } + + if (message == null) { + message = '' + } else if (typeof message !== 'string') { + throw new TypeError('message must be a string') + } + + return binding.showCertificateTrustDialog(window, certificate, message, callback) } } diff --git a/lib/browser/api/module-list.js b/lib/browser/api/module-list.js index 3274f0b6d4..64b2829064 100644 --- a/lib/browser/api/module-list.js +++ b/lib/browser/api/module-list.js @@ -2,6 +2,7 @@ module.exports = [ {name: 'app', file: 'app'}, {name: 'autoUpdater', file: 'auto-updater'}, + {name: 'BrowserView', file: 'browser-view'}, {name: 'BrowserWindow', file: 'browser-window'}, {name: 'contentTracing', file: 'content-tracing'}, {name: 'dialog', file: 'dialog'}, diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 74951edbac..1a9c3238a9 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -20,22 +20,37 @@ class TouchBar extends EventEmitter { touchBar._addToWindow(window) } - constructor (items) { + constructor (options) { super() + if (options == null) { + throw new Error('Must specify options object as first argument') + } + + let {items, escapeItem} = options + + // FIXME Support array as first argument, remove in 2.0 + if (Array.isArray(options)) { + items = options + escapeItem = null + } + if (!Array.isArray(items)) { - throw new Error('Must specify items array as first argument') + items = [] + } + + this.changeListener = (item) => { + this.emit('change', item.id, item.type) } this.windowListeners = {} this.items = {} this.ordereredItems = [] + this.escapeItem = escapeItem const registerItem = (item) => { this.items[item.id] = item - item.on('change', () => { - this.emit('change', item.id, item.type) - }) + item.on('change', this.changeListener) if (item.child instanceof TouchBar) { item.child.ordereredItems.forEach(registerItem) } @@ -49,6 +64,24 @@ class TouchBar extends EventEmitter { }) } + set escapeItem (item) { + if (item != null && !(item instanceof TouchBarItem)) { + throw new Error('Escape item must be an instance of TouchBarItem') + } + if (this.escapeItem != null) { + this.escapeItem.removeListener('change', this.changeListener) + } + this._escapeItem = item + if (this.escapeItem != null) { + this.escapeItem.on('change', this.changeListener) + } + this.emit('escape-item-change', item) + } + + get escapeItem () { + return this._escapeItem + } + _addToWindow (window) { const {id} = window @@ -62,8 +95,16 @@ class TouchBar extends EventEmitter { } this.on('change', changeListener) + const escapeItemListener = (item) => { + window._setEscapeTouchBarItem(item != null ? item : {}) + } + this.on('escape-item-change', escapeItemListener) + const interactionListener = (event, itemID, details) => { - const item = this.items[itemID] + let item = this.items[itemID] + if (item == null && this.escapeItem != null && this.escapeItem.id === itemID) { + item = this.escapeItem + } if (item != null && item.onInteraction != null) { item.onInteraction(details) } @@ -72,6 +113,7 @@ class TouchBar extends EventEmitter { const removeListeners = () => { this.removeListener('change', changeListener) + this.removeListener('escape-item-change', escapeItemListener) window.removeListener('-touch-bar-interaction', interactionListener) window.removeListener('closed', removeListeners) window._touchBar = null @@ -81,6 +123,7 @@ class TouchBar extends EventEmitter { this.windowListeners[id] = removeListeners window._setTouchBarItems(this.ordereredItems) + escapeItemListener(this.escapeItem) } _removeFromWindow (window) { @@ -104,7 +147,7 @@ class TouchBarItem extends EventEmitter { }, set: function (value) { this[privateName] = value - this.emit('change') + this.emit('change', this) }, enumerable: true }) @@ -180,6 +223,10 @@ TouchBar.TouchBarPopover = class TouchBarPopover extends TouchBarItem { if (!(this.child instanceof TouchBar)) { this.child = new TouchBar(this.child) } + this.child.ordereredItems.forEach((item) => { + item._popover = item._popover || [] + if (!item._popover.includes(this.id)) item._popover.push(this.id) + }) } } diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index 13d6f882c2..8d543f2d7d 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -360,15 +360,16 @@ ipcMain.on('ELECTRON_BROWSER_MEMBER_CALL', function (event, id, method, args) { } }) -ipcMain.on('ELECTRON_BROWSER_MEMBER_SET', function (event, id, name, value) { +ipcMain.on('ELECTRON_BROWSER_MEMBER_SET', function (event, id, name, args) { try { + args = unwrapArgs(event.sender, args) let obj = objectsRegistry.get(id) if (obj == null) { throwRPCError(`Cannot set property '${name}' on missing remote object ${id}`) } - obj[name] = value + obj[name] = args[0] event.returnValue = null } catch (error) { event.returnValue = exceptionToMeta(error) diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index f65d61790a..5e790133d3 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -139,7 +139,8 @@ const setObjectMembers = function (ref, object, metaId, members) { // Only set setter when it is writable. if (member.writable) { descriptor.set = function (value) { - const meta = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_SET', metaId, member.name, value) + const args = wrapArgs([value]) + const meta = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_SET', metaId, member.name, args) // Meta will be non-null when a setter error occurred so parse it // to a value so it gets re-thrown. if (meta != null) { diff --git a/lib/sandboxed_renderer/api/exports/path.js b/lib/sandboxed_renderer/api/exports/path.js new file mode 100644 index 0000000000..f2b2f2a77f --- /dev/null +++ b/lib/sandboxed_renderer/api/exports/path.js @@ -0,0 +1 @@ +module.exports = require('electron').remote.require('path') diff --git a/lib/sandboxed_renderer/init.js b/lib/sandboxed_renderer/init.js index 46b74ee7b0..5194f95154 100644 --- a/lib/sandboxed_renderer/init.js +++ b/lib/sandboxed_renderer/init.js @@ -27,6 +27,7 @@ const preloadModules = new Map([ ['electron', electron], ['fs', fs], ['os', require('os')], + ['path', require('path')], ['url', require('url')], ['timers', require('timers')] ]) @@ -36,8 +37,9 @@ const preloadSrc = fs.readFileSync(preloadPath).toString() // Pass different process object to the preload script(which should not have // access to things like `process.atomBinding`). const preloadProcess = new events.EventEmitter() -preloadProcess.platform = electron.remote.process.platform preloadProcess.crash = () => binding.crash() +process.platform = preloadProcess.platform = electron.remote.process.platform +process.execPath = preloadProcess.execPath = electron.remote.process.execPath process.on('exit', () => preloadProcess.emit('exit')) // This is the `require` function that will be visible to the preload script diff --git a/package.json b/package.json index 015be4a12e..c34a27e275 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "1.6.5", + "version": "1.6.6", "devDependencies": { "asar": "^0.11.0", "browserify": "^13.1.0", diff --git a/script/create-dist.py b/script/create-dist.py index 3d4b62624e..27032400f3 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -43,7 +43,6 @@ TARGET_BINARIES = { 'content_resources_200_percent.pak', 'ui_resources_200_percent.pak', 'views_resources_200_percent.pak', - 'xinput1_3.dll', 'natives_blob.bin', 'snapshot_blob.bin', ], diff --git a/script/lib/config.py b/script/lib/config.py index d033d8a41c..5818571089 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -9,7 +9,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' LIBCHROMIUMCONTENT_COMMIT = os.getenv('LIBCHROMIUMCONTENT_COMMIT') or \ - '8d551064d2b3d11f89ce8d5c4610f34e0408bad8' + '4a0e32606e52c12c50c2e3a0973d015d8cdff494' PLATFORM = { 'cygwin': 'win32', diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 301d6ae4bf..9a9b4334bc 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -137,6 +137,16 @@ describe('app module', function () { done() }) }) + + it('closes all windows', function (done) { + var appPath = path.join(__dirname, 'fixtures', 'api', 'exit-closes-all-windows-app') + var electronPath = remote.getGlobal('process').execPath + appProcess = ChildProcess.spawn(electronPath, [appPath]) + appProcess.on('close', function (code) { + assert.equal(code, 123) + done() + }) + }) }) describe('app.relaunch', function () { diff --git a/spec/api-browser-view-spec.js b/spec/api-browser-view-spec.js new file mode 100644 index 0000000000..3ccb9502c2 --- /dev/null +++ b/spec/api-browser-view-spec.js @@ -0,0 +1,92 @@ +'use strict' + +const assert = require('assert') +const {closeWindow} = require('./window-helpers') + +const {remote} = require('electron') +const {BrowserView, BrowserWindow} = remote + +describe('View module', function () { + var w = null + var view = null + + beforeEach(function () { + w = new BrowserWindow({ + show: false, + width: 400, + height: 400, + webPreferences: { + backgroundThrottling: false + } + }) + }) + + afterEach(function () { + if (view) { + view.destroy() + view = null + } + + return closeWindow(w).then(function () { w = null }) + }) + + describe('BrowserView.setBackgroundColor()', function () { + it('does not throw for valid args', function () { + view = new BrowserView() + view.setBackgroundColor('#000') + }) + + it('throws for invalid args', function () { + view = new BrowserView() + assert.throws(function () { + view.setBackgroundColor(null) + }, /conversion failure/) + }) + }) + + describe('BrowserView.setAutoResize()', function () { + it('does not throw for valid args', function () { + view = new BrowserView() + view.setAutoResize({}) + view.setAutoResize({ width: true, height: false }) + }) + + it('throws for invalid args', function () { + view = new BrowserView() + assert.throws(function () { + view.setAutoResize(null) + }, /conversion failure/) + }) + }) + + describe('BrowserView.setBounds()', function () { + it('does not throw for valid args', function () { + view = new BrowserView() + view.setBounds({ x: 0, y: 0, width: 1, height: 1 }) + }) + + it('throws for invalid args', function () { + view = new BrowserView() + assert.throws(function () { + view.setBounds(null) + }, /conversion failure/) + assert.throws(function () { + view.setBounds({}) + }, /conversion failure/) + }) + }) + + describe('BrowserWindow.setBrowserView()', function () { + it('does not throw for valid args', function () { + view = new BrowserView() + w.setBrowserView(view) + }) + + it('does not throw if called multiple times with same view', function () { + view = new BrowserView() + w.setBrowserView(view) + w.setBrowserView(view) + w.setBrowserView(view) + }) + }) +}) diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index 8a51b5ef2d..a0fde2d54f 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -15,24 +15,32 @@ describe('crashReporter module', function () { if (process.mas) { return } + + var originalTempDirectory = null + var tempDirectory = null + + before(function () { + tempDirectory = temp.mkdirSync('electronCrashReporterSpec-') + originalTempDirectory = app.getPath('temp') + app.setPath('temp', tempDirectory) + }) + + after(function () { + app.setPath('temp', originalTempDirectory) + }) + var fixtures = path.resolve(__dirname, 'fixtures') const generateSpecs = (description, browserWindowOpts) => { describe(description, function () { var w = null - var originalTempDirectory = null - var tempDirectory = null beforeEach(function () { w = new BrowserWindow(Object.assign({ show: false }, browserWindowOpts)) - tempDirectory = temp.mkdirSync('electronCrashReporterSpec-') - originalTempDirectory = app.getPath('temp') - app.setPath('temp', tempDirectory) }) afterEach(function () { - app.setPath('temp', originalTempDirectory) return closeWindow(w).then(function () { w = null }) }) @@ -77,13 +85,15 @@ describe('crashReporter module', function () { it('should not send minidump if uploadToServer is false', function (done) { this.timeout(120000) - if (process.platform === 'darwin') { - crashReporter.setUploadToServer(false) - } - let server let dumpFile - let crashesDir + let crashesDir = crashReporter.getCrashesDirectory() + const existingDumpFiles = new Set() + if (process.platform === 'darwin') { + // crashpad puts the dump files in the "completed" subdirectory + crashesDir = path.join(crashesDir, 'completed') + crashReporter.setUploadToServer(false) + } const testDone = (uploaded) => { if (uploaded) { return done(new Error('fail')) @@ -93,7 +103,6 @@ describe('crashReporter module', function () { crashReporter.setUploadToServer(true) } assert(fs.existsSync(dumpFile)) - fs.unlinkSync(dumpFile) done() } @@ -103,7 +112,7 @@ describe('crashReporter module', function () { if (err) { return } - const dumps = files.filter((file) => /\.dmp$/.test(file)) + const dumps = files.filter((file) => /\.dmp$/.test(file) && !existingDumpFiles.has(file)) if (!dumps.length) { return } @@ -111,34 +120,17 @@ describe('crashReporter module', function () { dumpFile = path.join(crashesDir, dumps[0]) clearInterval(pollInterval) // dump file should not be deleted when not uploading, so we wait - // 500 ms and assert it still exists in `testDone` - setTimeout(testDone, 500) + // 1s and assert it still exists in `testDone` + setTimeout(testDone, 1000) }) } - remote.ipcMain.once('set-crash-directory', (event, dir) => { - if (process.platform === 'linux') { - crashesDir = dir - } else { - crashesDir = crashReporter.getCrashesDirectory() - if (process.platform === 'darwin') { - // crashpad uses an extra subdirectory - crashesDir = path.join(crashesDir, 'completed') - } - } - - // Before starting, remove all dump files in the crash directory. - // This is required because: - // - mac crashpad not seem to allow changing the crash directory after - // the first "start" call. - // - Other tests in this suite may leave dumps there. - // - We want to verify in `testDone` that a dump file is created and - // not deleted. + remote.ipcMain.once('list-existing-dumps', (event) => { fs.readdir(crashesDir, (err, files) => { if (!err) { for (const file of files) { if (/\.dmp$/.test(file)) { - fs.unlinkSync(path.join(crashesDir, file)) + existingDumpFiles.add(file) } } } diff --git a/spec/api-dialog-spec.js b/spec/api-dialog-spec.js index 6b245c2b65..601e28ca53 100644 --- a/spec/api-dialog-spec.js +++ b/spec/api-dialog-spec.js @@ -93,4 +93,20 @@ describe('dialog module', () => { }, /Error processing argument at index 1/) }) }) + + describe('showCertificateTrustDialog', () => { + it('throws errors when the options are invalid', () => { + assert.throws(() => { + dialog.showCertificateTrustDialog() + }, /options must be an object/) + + assert.throws(() => { + dialog.showCertificateTrustDialog({}) + }, /certificate must be an object/) + + assert.throws(() => { + dialog.showCertificateTrustDialog({certificate: {}, message: false}) + }, /message must be a string/) + }) + }) }) diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index c5e38e83e4..fb4278d180 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -175,8 +175,14 @@ describe('ipc module', function () { it('can change its properties', function () { var property = remote.require(path.join(fixtures, 'module', 'property.js')) assert.equal(property.property, 1127) + + property.property = null + assert.equal(property.property, null) + property.property = undefined + assert.equal(property.property, undefined) property.property = 1007 assert.equal(property.property, 1007) + assert.equal(property.getFunctionProperty(), 'foo-browser') property.func.property = 'bar' assert.equal(property.getFunctionProperty(), 'bar-browser') @@ -199,6 +205,14 @@ describe('ipc module', function () { }, /setting error/) }) + it('can set a remote property with a remote object', function () { + const foo = remote.require(path.join(fixtures, 'module', 'remote-object-set.js')) + + assert.doesNotThrow(function () { + foo.bar = remote.getCurrentWindow() + }) + }) + it('can construct an object from its member', function () { var call = remote.require(path.join(fixtures, 'module', 'call.js')) var obj = new call.constructor() diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index dc024553a8..a5c3df8210 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -26,22 +26,34 @@ const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte describe('net module', function () { - describe('HTTP basics', function () { - let server - beforeEach(function (done) { - server = http.createServer() - server.listen(0, '127.0.0.1', function () { - server.url = 'http://127.0.0.1:' + server.address().port - done() + let server + const connections = new Set() + + beforeEach(function (done) { + server = http.createServer() + server.listen(0, '127.0.0.1', function () { + server.url = `http://127.0.0.1:${server.address().port}` + done() + }) + server.on('connection', (connection) => { + connections.add(connection) + connection.once('close', () => { + connections.delete(connection) }) }) + }) - afterEach(function () { - server.close(function () { - }) + afterEach(function (done) { + for (const connection of connections) { + connection.destroy() + } + server.close(function () { server = null + done() }) + }) + describe('HTTP basics', function () { it('should be able to issue a basic GET request', function (done) { const requestUrl = '/requestUrl' server.on('request', function (request, response) { @@ -224,19 +236,7 @@ describe('net module', function () { }) describe('ClientRequest API', function () { - let server - beforeEach(function (done) { - server = http.createServer() - server.listen(0, '127.0.0.1', function () { - server.url = 'http://127.0.0.1:' + server.address().port - done() - }) - }) - afterEach(function () { - server.close(function () { - }) - server = null session.defaultSession.webRequest.onBeforeRequest(null) }) @@ -1363,21 +1363,8 @@ describe('net module', function () { urlRequest.end() }) }) + describe('IncomingMessage API', function () { - let server - beforeEach(function (done) { - server = http.createServer() - server.listen(0, '127.0.0.1', function () { - server.url = 'http://127.0.0.1:' + server.address().port - done() - }) - }) - - afterEach(function () { - server.close() - server = null - }) - it('response object should implement the IncomingMessage API', function (done) { const requestUrl = '/requestUrl' const customHeaderName = 'Some-Custom-Header-Name' @@ -1544,21 +1531,8 @@ describe('net module', function () { urlRequest.end() }) }) + describe('Stability and performance', function (done) { - let server - beforeEach(function (done) { - server = http.createServer() - server.listen(0, '127.0.0.1', function () { - server.url = 'http://127.0.0.1:' + server.address().port - done() - }) - }) - - afterEach(function () { - server.close() - server = null - }) - it('should free unreferenced, never-started request objects without crash', function (done) { const requestUrl = '/requestUrl' ipcRenderer.once('api-net-spec-done', function () { @@ -1574,6 +1548,7 @@ describe('net module', function () { }) `) }) + it('should not collect on-going requests without crash', function (done) { const requestUrl = '/requestUrl' server.on('request', function (request, response) { @@ -1615,6 +1590,7 @@ describe('net module', function () { urlRequest.end() `) }) + it('should collect unreferenced, ended requests without crash', function (done) { const requestUrl = '/requestUrl' server.on('request', function (request, response) { diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index a8e90502f5..420ef3fc7b 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -6,20 +6,32 @@ const {TouchBarButton, TouchBarColorPicker, TouchBarGroup} = TouchBar const {TouchBarLabel, TouchBarPopover, TouchBarScrubber, TouchBarSegmentedControl, TouchBarSlider, TouchBarSpacer} = TouchBar describe('TouchBar module', function () { - it('throws an error when created without an items array', function () { + it('throws an error when created without an options object', function () { assert.throws(() => { const touchBar = new TouchBar() touchBar.toString() - }, /Must specify items array as first argument/) + }, /Must specify options object as first argument/) }) it('throws an error when created with invalid items', function () { assert.throws(() => { - const touchBar = new TouchBar([1, true, {}, []]) + const touchBar = new TouchBar({items: [1, true, {}, []]}) touchBar.toString() }, /Each item must be an instance of TouchBarItem/) }) + it('throws an error when an invalid escape item is set', function () { + assert.throws(() => { + const touchBar = new TouchBar({items: [], escapeItem: 'esc'}) + touchBar.toString() + }, /Escape item must be an instance of TouchBarItem/) + + assert.throws(() => { + const touchBar = new TouchBar({items: []}) + touchBar.escapeItem = 'esc' + }, /Escape item must be an instance of TouchBarItem/) + }) + describe('BrowserWindow behavior', function () { let window @@ -55,10 +67,40 @@ describe('TouchBar module', function () { showArrowButtons: true }) ]) + const escapeButton = new TouchBarButton({ + label: 'foo' + }) window.setTouchBar(touchBar) + touchBar.escapeItem = escapeButton label.label = 'baz' + escapeButton.label = 'hello' window.setTouchBar() window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})])) + touchBar.escapeItem = null + }) + + it('calls the callback on the items when a window interaction event fires', function (done) { + const button = new TouchBarButton({ + label: 'bar', + click: () => { + done() + } + }) + const touchBar = new TouchBar({items: [button]}) + window.setTouchBar(touchBar) + window.emit('-touch-bar-interaction', {}, button.id) + }) + + it('calls the callback on the escape item when a window interaction event fires', function (done) { + const button = new TouchBarButton({ + label: 'bar', + click: () => { + done() + } + }) + const touchBar = new TouchBar({escapeItem: button}) + window.setTouchBar(touchBar) + window.emit('-touch-bar-interaction', {}, button.id) }) }) }) diff --git a/spec/fixtures/api/crash.html b/spec/fixtures/api/crash.html index 6f013a2c7b..6a1433a0e6 100644 --- a/spec/fixtures/api/crash.html +++ b/spec/fixtures/api/crash.html @@ -17,7 +17,7 @@ crashReporter.start({ } }); if (!uploadToServer) { - ipcRenderer.sendSync('set-crash-directory', crashReporter.getCrashesDirectory()) + ipcRenderer.sendSync('list-existing-dumps') } setImmediate(function() { process.crash(); }); diff --git a/spec/fixtures/api/exit-closes-all-windows-app/main.js b/spec/fixtures/api/exit-closes-all-windows-app/main.js new file mode 100644 index 0000000000..c97d8d1f19 --- /dev/null +++ b/spec/fixtures/api/exit-closes-all-windows-app/main.js @@ -0,0 +1,19 @@ +const {app, BrowserWindow} = require('electron') + +const windows = [] + +function createWindow (id) { + const window = new BrowserWindow({show: false}) + window.loadURL(`data:,window${id}`) + windows.push(window) +} + +app.once('ready', () => { + for (let i = 1; i <= 5; i++) { + createWindow(i) + } + + setImmediate(function () { + app.exit(123) + }) +}) diff --git a/spec/fixtures/api/exit-closes-all-windows-app/package.json b/spec/fixtures/api/exit-closes-all-windows-app/package.json new file mode 100644 index 0000000000..ae52532315 --- /dev/null +++ b/spec/fixtures/api/exit-closes-all-windows-app/package.json @@ -0,0 +1,4 @@ +{ + "name": "electron-exit-closes-all-windows", + "main": "main.js" +} diff --git a/spec/fixtures/module/remote-object-set.js b/spec/fixtures/module/remote-object-set.js new file mode 100644 index 0000000000..5fefbf5cf3 --- /dev/null +++ b/spec/fixtures/module/remote-object-set.js @@ -0,0 +1,11 @@ +const {BrowserWindow} = require('electron') + +class Foo { + set bar (value) { + if (!(value instanceof BrowserWindow)) { + throw new Error('setting error') + } + } +} + +module.exports = new Foo() diff --git a/spec/node-spec.js b/spec/node-spec.js index 98db1efeb0..8f1d7163bb 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -91,6 +91,16 @@ describe('node feature', function () { done() }) }) + + it('works when sending a message to a process forked with the --eval argument', function (done) { + const source = "process.on('message', (message) => { process.send(message) })" + const forked = ChildProcess.fork('--eval', [source]) + forked.once('message', (message) => { + assert.equal(message, 'hello') + done() + }) + forked.send('hello') + }) }) describe('child_process.spawn', function () { diff --git a/vendor/brightray b/vendor/brightray index baccc07794..909c492654 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit baccc077948f504c6a6db58e855fd33938b2b625 +Subproject commit 909c49265493bd095c27cefd999567be2107899a diff --git a/vendor/node b/vendor/node index a6663598aa..3fe90cfcf5 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit a6663598aa78832e7955cb93c51a098eac787abb +Subproject commit 3fe90cfcf54dd946980e59daf550a7cdb2317c8f