diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index e9dfd9f47f4b..49b0a89d8362 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -79,6 +79,10 @@ const int kDefaultHeight = 300; v8::Persistent template_; +// The wrapWebContents funtion which is implemented in JavaScript +using WrapWebContentsCallback = base::Callback)>; +WrapWebContentsCallback g_wrap_web_contents; + // Get the window that has the |guest| embedded. NativeWindow* GetWindowFromGuest(const content::WebContents* guest) { WebViewManager::WebViewInfo info; @@ -530,10 +534,17 @@ void WebContents::ExecuteJavaScript(const base::string16& code) { web_contents()->GetMainFrame()->ExecuteJavaScript(code); } -void WebContents::OpenDevTools() { +void WebContents::OpenDevTools(mate::Arguments* args) { if (!inspectable_web_contents()) return; - inspectable_web_contents()->SetCanDock(false); + bool detach = false; + if (is_guest()) { + detach = true; + } else if (args && args->Length() == 1) { + mate::Dictionary options; + args->GetNext(&options) && options.Get("detach", &detach); + } + inspectable_web_contents()->SetCanDock(!detach); inspectable_web_contents()->ShowDevTools(); } @@ -549,10 +560,17 @@ bool WebContents::IsDevToolsOpened() { return inspectable_web_contents()->IsDevToolsViewShowing(); } +void WebContents::ToggleDevTools() { + if (IsDevToolsOpened()) + CloseDevTools(); + else + OpenDevTools(nullptr); +} + void WebContents::InspectElement(int x, int y) { if (!inspectable_web_contents()) return; - OpenDevTools(); + OpenDevTools(nullptr); scoped_refptr agent( content::DevToolsAgentHost::GetOrCreateFor(web_contents())); agent->InspectElement(x, y); @@ -564,7 +582,7 @@ void WebContents::InspectServiceWorker() { for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) { if (agent_host->GetType() == content::DevToolsAgentHost::TYPE_SERVICE_WORKER) { - OpenDevTools(); + OpenDevTools(nullptr); inspectable_web_contents()->AttachTo(agent_host); break; } @@ -741,6 +759,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("openDevTools", &WebContents::OpenDevTools) .SetMethod("closeDevTools", &WebContents::CloseDevTools) .SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened) + .SetMethod("toggleDevTools", &WebContents::ToggleDevTools) .SetMethod("inspectElement", &WebContents::InspectElement) .SetMethod("undo", &WebContents::Undo) .SetMethod("redo", &WebContents::Redo) @@ -800,19 +819,33 @@ gfx::Size WebContents::GetDefaultSize() const { // static mate::Handle WebContents::CreateFrom( v8::Isolate* isolate, brightray::InspectableWebContents* web_contents) { - return mate::CreateHandle(isolate, new WebContents(web_contents)); + auto handle = mate::CreateHandle(isolate, new WebContents(web_contents)); + g_wrap_web_contents.Run(handle.ToV8()); + return handle; } // static mate::Handle WebContents::CreateFrom( v8::Isolate* isolate, content::WebContents* web_contents) { - return mate::CreateHandle(isolate, new WebContents(web_contents)); + auto handle = mate::CreateHandle(isolate, new WebContents(web_contents)); + g_wrap_web_contents.Run(handle.ToV8()); + return handle; } // static mate::Handle WebContents::Create( v8::Isolate* isolate, const mate::Dictionary& options) { - return mate::CreateHandle(isolate, new WebContents(options)); + auto handle = mate::CreateHandle(isolate, new WebContents(options)); + g_wrap_web_contents.Run(handle.ToV8()); + return handle; +} + +void SetWrapWebContents(const WrapWebContentsCallback& callback) { + g_wrap_web_contents = callback; +} + +void ClearWrapWebContents() { + g_wrap_web_contents.Reset(); } } // namespace api @@ -827,6 +860,8 @@ void Initialize(v8::Local exports, v8::Local unused, v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); dict.SetMethod("create", &atom::api::WebContents::Create); + dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents); + dict.SetMethod("_clearWrapWebContents", &atom::api::ClearWrapWebContents); } } // namespace diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 486c61c5dda8..f16680b53d00 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -22,6 +22,7 @@ class InspectableWebContents; } namespace mate { +class Arguments; class Dictionary; } @@ -78,9 +79,10 @@ class WebContents : public mate::EventEmitter, void SetUserAgent(const std::string& user_agent); void InsertCSS(const std::string& css); void ExecuteJavaScript(const base::string16& code); - void OpenDevTools(); + void OpenDevTools(mate::Arguments* args); void CloseDevTools(); bool IsDevToolsOpened(); + void ToggleDevTools(); void InspectElement(int x, int y); void InspectServiceWorker(); void HasServiceWorker(const base::Callback&); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index fec072e27f9e..76aaa3baaff5 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -165,6 +165,26 @@ void Window::OnDevToolsFocus() { Emit("devtools-focused"); } +void Window::OnDevToolsOpened() { + Emit("devtools-opened"); + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Locker locker(isolate); + v8::HandleScope handle_scope(isolate); + auto handle = + WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents()); + devtools_web_contents_.Reset(isolate, handle.ToV8()); +} + +void Window::OnDevToolsClosed() { + Emit("devtools-closed"); + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Locker locker(isolate); + v8::HandleScope handle_scope(isolate); + devtools_web_contents_.Reset(); +} + // static mate::Wrappable* Window::New(v8::Isolate* isolate, const mate::Dictionary& options) { @@ -356,26 +376,6 @@ bool Window::IsKiosk() { return window_->IsKiosk(); } -void Window::OpenDevTools(bool can_dock) { - window_->OpenDevTools(can_dock); -} - -void Window::CloseDevTools() { - window_->CloseDevTools(); -} - -bool Window::IsDevToolsOpened() { - return window_->IsDevToolsOpened(); -} - -void Window::InspectElement(int x, int y) { - window_->InspectElement(x, y); -} - -void Window::InspectServiceWorker() { - window_->InspectServiceWorker(); -} - void Window::FocusOnWebView() { window_->FocusOnWebView(); } @@ -472,13 +472,20 @@ bool Window::IsVisibleOnAllWorkspaces() { return window_->IsVisibleOnAllWorkspaces(); } -mate::Handle Window::GetWebContents(v8::Isolate* isolate) const { - return WebContents::CreateFrom(isolate, window_->managed_web_contents()); +v8::Local Window::WebContents(v8::Isolate* isolate) { + if (web_contents_.IsEmpty()) { + auto handle = + WebContents::CreateFrom(isolate, window_->managed_web_contents()); + web_contents_.Reset(isolate, handle.ToV8()); + } + return v8::Local::New(isolate, web_contents_); } -mate::Handle Window::GetDevToolsWebContents( - v8::Isolate* isolate) const { - return WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents()); +v8::Local Window::DevToolsWebContents(v8::Isolate* isolate) { + if (devtools_web_contents_.IsEmpty()) + return v8::Null(isolate); + else + return v8::Local::New(isolate, devtools_web_contents_); } // static @@ -529,10 +536,6 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename) .SetMethod("setDocumentEdited", &Window::SetDocumentEdited) .SetMethod("isDocumentEdited", &Window::IsDocumentEdited) - .SetMethod("_openDevTools", &Window::OpenDevTools) - .SetMethod("closeDevTools", &Window::CloseDevTools) - .SetMethod("isDevToolsOpened", &Window::IsDevToolsOpened) - .SetMethod("_inspectElement", &Window::InspectElement) .SetMethod("focusOnWebView", &Window::FocusOnWebView) .SetMethod("blurWebView", &Window::BlurWebView) .SetMethod("isWebViewFocused", &Window::IsWebViewFocused) @@ -553,9 +556,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("showDefinitionForSelection", &Window::ShowDefinitionForSelection) #endif - .SetMethod("_getWebContents", &Window::GetWebContents) - .SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents) - .SetMethod("_inspectServiceWorker", &Window::InspectServiceWorker); + .SetProperty("webContents", &Window::WebContents) + .SetProperty("devToolsWebContents", &Window::DevToolsWebContents); } } // namespace api diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 72d2c842d8e8..43a32e86f45a 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -78,6 +78,8 @@ class Window : public mate::EventEmitter, void OnRendererUnresponsive() override; void OnRendererResponsive() override; void OnDevToolsFocus() override; + void OnDevToolsOpened() override; + void OnDevToolsClosed() override; private: // APIs for NativeWindow. @@ -121,11 +123,6 @@ class Window : public mate::EventEmitter, void SetSkipTaskbar(bool skip); void SetKiosk(bool kiosk); bool IsKiosk(); - void OpenDevTools(bool can_dock); - void CloseDevTools(); - bool IsDevToolsOpened(); - void InspectElement(int x, int y); - void InspectServiceWorker(); void FocusOnWebView(); void BlurWebView(); bool IsWebViewFocused(); @@ -151,9 +148,11 @@ class Window : public mate::EventEmitter, void SetVisibleOnAllWorkspaces(bool visible); bool IsVisibleOnAllWorkspaces(); - // APIs for WebContents. - mate::Handle GetWebContents(v8::Isolate* isolate) const; - mate::Handle GetDevToolsWebContents(v8::Isolate* isolate) const; + v8::Local WebContents(v8::Isolate* isolate); + v8::Local DevToolsWebContents(v8::Isolate* isolate); + + v8::Global web_contents_; + v8::Global devtools_web_contents_; scoped_ptr window_; diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 7e4711e817c4..f0691b19b8fa 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -2,7 +2,6 @@ EventEmitter = require('events').EventEmitter IDWeakMap = require 'id-weak-map' app = require 'app' ipc = require 'ipc' -wrapWebContents = require('web-contents').wrap BrowserWindow = process.atomBinding('window').BrowserWindow BrowserWindow::__proto__ = EventEmitter.prototype @@ -16,10 +15,6 @@ BrowserWindow::_init = -> menu = app.getApplicationMenu() @setMenu menu if menu? - @webContents = @getWebContents() - @devToolsWebContents = null - @webContents.once 'destroyed', => @webContents = null - # Remember the window ID. Object.defineProperty this, 'id', value: BrowserWindow.windows.add(this) @@ -40,35 +35,6 @@ BrowserWindow::_init = -> @once 'closed', => BrowserWindow.windows.remove @id if BrowserWindow.windows.has @id -BrowserWindow::openDevTools = (options={}) -> - options.detach ?= false - @_openDevTools !options.detach - - # Force devToolsWebContents to be created. - @devToolsWebContents = @getDevToolsWebContents() - @devToolsWebContents.once 'destroyed', => @devToolsWebContents = null - - # Emit devtools events. - @devToolsWebContents.once 'did-finish-load', => @emit 'devtools-opened' - @devToolsWebContents.once 'destroyed', => @emit 'devtools-closed' - -BrowserWindow::toggleDevTools = -> - if @isDevToolsOpened() then @closeDevTools() else @openDevTools() - -BrowserWindow::inspectElement = (x, y) -> - @openDevTools true - @_inspectElement x, y - -BrowserWindow::inspectServiceWorker = -> - @openDevTools true - @_inspectServiceWorker() - -BrowserWindow::getWebContents = -> - wrapWebContents @_getWebContents() - -BrowserWindow::getDevToolsWebContents = -> - wrapWebContents @_getDevToolsWebContents() - BrowserWindow::setMenu = (menu) -> throw new TypeError('Invalid menu') unless menu is null or menu?.constructor?.name is 'Menu' @@ -110,7 +76,12 @@ BrowserWindow::stop = -> @webContents.stop() BrowserWindow::getRoutingId = -> @webContents.getRoutingId() BrowserWindow::getProcessId = -> @webContents.getProcessId() BrowserWindow::isCrashed = -> @webContents.isCrashed() -BrowserWindow::executeJavaScriptInDevTools = (code) -> - @devToolsWebContents.executeJavaScript code +BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents?.executeJavaScript code +BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments +BrowserWindow::closeDevTools = -> @webContents.closeDevTools() +BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened() +BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools() +BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments +BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker() module.exports = BrowserWindow diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index eb86c94500ce..b8c101423d04 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -3,9 +3,7 @@ NavigationController = require './navigation-controller' binding = process.atomBinding 'web_contents' ipc = require 'ipc' -module.exports.wrap = (webContents) -> - return null unless webContents.isAlive() - +wrapWebContents = (webContents) -> # webContents is an EventEmitter. webContents.__proto__ = EventEmitter.prototype @@ -62,5 +60,8 @@ module.exports.wrap = (webContents) -> webContents +binding._setWrapWebContents wrapWebContents +process.once 'exit', binding._clearWrapWebContents + module.exports.create = (options={}) -> - @wrap binding.create(options) + binding.create(options) diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index b1a660444e02..1a64f2498582 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -4,6 +4,9 @@ #include "atom/browser/common_web_contents_delegate.h" +#include +#include + #include "atom/browser/atom_javascript_dialog_manager.h" #include "atom/browser/native_window.h" #include "atom/browser/ui/file_dialog.h" diff --git a/atom/browser/common_web_contents_delegate.h b/atom/browser/common_web_contents_delegate.h index 5d80ac42c36f..8909d1931457 100644 --- a/atom/browser/common_web_contents_delegate.h +++ b/atom/browser/common_web_contents_delegate.h @@ -6,6 +6,8 @@ #define ATOM_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_ #include +#include +#include #include "brightray/browser/default_web_contents_delegate.h" #include "brightray/browser/inspectable_web_contents_impl.h" @@ -42,7 +44,7 @@ class CommonWebContentsDelegate return web_contents_.get(); } - bool is_guest() const { return is_guest_; }; + bool is_guest() const { return is_guest_; } protected: // content::WebContentsDelegate: diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 4f3fab7fcf10..07ad83f1acee 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -29,14 +29,11 @@ #include "brightray/browser/inspectable_web_contents_view.h" #include "chrome/browser/printing/print_view_manager_basic.h" #include "content/browser/renderer_host/render_widget_host_impl.h" -#include "content/public/browser/devtools_agent_host.h" -#include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/plugin_service.h" -#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" @@ -289,35 +286,6 @@ bool NativeWindow::HasModalDialog() { return has_dialog_attached_; } -void NativeWindow::OpenDevTools(bool can_dock) { - inspectable_web_contents()->SetCanDock(can_dock); - inspectable_web_contents()->ShowDevTools(); -} - -void NativeWindow::CloseDevTools() { - inspectable_web_contents()->CloseDevTools(); -} - -bool NativeWindow::IsDevToolsOpened() { - return inspectable_web_contents()->IsDevToolsViewShowing(); -} - -void NativeWindow::InspectElement(int x, int y) { - scoped_refptr agent( - content::DevToolsAgentHost::GetOrCreateFor(GetWebContents())); - agent->InspectElement(x, y); -} - -void NativeWindow::InspectServiceWorker() { - for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) { - if (agent_host->GetType() == - content::DevToolsAgentHost::TYPE_SERVICE_WORKER) { - inspectable_web_contents()->AttachTo(agent_host); - break; - } - } -} - void NativeWindow::FocusOnWebView() { GetWebContents()->GetRenderViewHost()->Focus(); } @@ -733,6 +701,14 @@ void NativeWindow::DevToolsFocused() { FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus()); } +void NativeWindow::DevToolsOpened() { + FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened()); +} + +void NativeWindow::DevToolsClosed() { + FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed()); +} + void NativeWindow::ScheduleUnresponsiveEvent(int ms) { if (!window_unresposive_closure_.IsCancelled()) return; diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index f6b88e4e401a..191e326df06d 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -144,11 +144,6 @@ class NativeWindow : public CommonWebContentsDelegate, virtual bool IsVisibleOnAllWorkspaces() = 0; virtual bool IsClosed() const { return is_closed_; } - virtual void OpenDevTools(bool can_dock); - virtual void CloseDevTools(); - virtual bool IsDevToolsOpened(); - virtual void InspectElement(int x, int y); - virtual void InspectServiceWorker(); virtual void FocusOnWebView(); virtual void BlurWebView(); @@ -273,6 +268,8 @@ class NativeWindow : public CommonWebContentsDelegate, // Implementations of brightray::InspectableWebContentsDelegate. void DevToolsFocused() override; + void DevToolsOpened() override; + void DevToolsClosed() override; // Whether window has standard frame. bool has_frame_; diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 417731fb3474..335a63149953 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -55,8 +55,10 @@ class NativeWindowObserver { virtual void OnWindowEnterHtmlFullScreen() {} virtual void OnWindowLeaveHtmlFullScreen() {} - // Called when devtools window gets focused. + // Redirect devtools events. virtual void OnDevToolsFocus() {} + virtual void OnDevToolsOpened() {} + virtual void OnDevToolsClosed() {} // Called when renderer is hung. virtual void OnRendererUnresponsive() {} diff --git a/vendor/brightray b/vendor/brightray index 190c3dd16291..20af087dd3ba 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 190c3dd1629141027f0962d0fab82c58853e7c85 +Subproject commit 20af087dd3ba01b601f8ad176899610c9479b382