From 26e93e8798439a809181f716ba3c098b3c8d3449 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Apr 2014 16:45:25 +0800 Subject: [PATCH 01/18] Initial empty api_web_contents. --- atom.gyp | 2 ++ atom/browser/api/atom_api_web_contents.cc | 34 ++++++++++++++++++ atom/browser/api/atom_api_web_contents.h | 42 +++++++++++++++++++++++ atom/browser/api/atom_api_window.cc | 12 +++++++ atom/browser/api/atom_api_window.h | 5 +++ 5 files changed, 95 insertions(+) create mode 100644 atom/browser/api/atom_api_web_contents.cc create mode 100644 atom/browser/api/atom_api_web_contents.h diff --git a/atom.gyp b/atom.gyp index a56ae6139a4c..fb1b7e79ff4d 100644 --- a/atom.gyp +++ b/atom.gyp @@ -62,6 +62,8 @@ 'atom/browser/api/atom_api_power_monitor.h', 'atom/browser/api/atom_api_protocol.cc', 'atom/browser/api/atom_api_protocol.h', + 'atom/browser/api/atom_api_web_contents.cc', + 'atom/browser/api/atom_api_web_contents.h', 'atom/browser/api/atom_api_window.cc', 'atom/browser/api/atom_api_window.h', 'atom/browser/api/atom_browser_bindings.cc', diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc new file mode 100644 index 000000000000..47925db1f131 --- /dev/null +++ b/atom/browser/api/atom_api_web_contents.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "atom/browser/api/atom_api_web_contents.h" + +#include "content/public/browser/web_contents.h" +#include "native_mate/object_template_builder.h" + +namespace atom { + +namespace api { + +WebContents::WebContents(content::WebContents* web_contents) + : web_contents_(web_contents) { +} + +WebContents::~WebContents() { +} + +mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return mate::ObjectTemplateBuilder(isolate); +} + +// static +mate::Handle WebContents::Create( + v8::Isolate* isolate, content::WebContents* web_contents) { + return CreateHandle(isolate, new WebContents(web_contents)); +} + +} // namespace api + +} // namespace atom diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h new file mode 100644 index 000000000000..5cad17da7772 --- /dev/null +++ b/atom/browser/api/atom_api_web_contents.h @@ -0,0 +1,42 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_ +#define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_ + +#include "atom/browser/api/event_emitter.h" +#include "native_mate/handle.h" + +namespace content { +class WebContents; +} + +namespace atom { + +namespace api { + +class WebContents : public mate::EventEmitter { + public: + static mate::Handle Create(v8::Isolate* isolate, + content::WebContents* web_contents); + + protected: + explicit WebContents(content::WebContents* web_contents); + virtual ~WebContents(); + + // mate::Wrappable implementations: + virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate); + + private: + content::WebContents* web_contents_; // Weak. + + DISALLOW_COPY_AND_ASSIGN(WebContents); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_ diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index c30db210593d..e17e3b3e7b22 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -4,6 +4,7 @@ #include "atom/browser/api/atom_api_window.h" +#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/native_window.h" #include "atom/common/native_mate_converters/function_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" @@ -326,6 +327,15 @@ void Window::CapturePage(mate::Arguments* args) { window_->CapturePage(rect, base::Bind(&OnCapturePageDone, callback)); } +mate::Handle Window::GetWebContents(v8::Isolate* isolate) const { + return WebContents::Create(isolate, window_->GetWebContents()); +} + +mate::Handle Window::GetDevToolsWebContents( + v8::Isolate* isolate) const { + return WebContents::Create(isolate, window_->GetDevToolsWebContents()); +} + string16 Window::GetPageTitle() { return window_->GetWebContents()->GetTitle(); } @@ -462,6 +472,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("blurWebView", &Window::BlurWebView) .SetMethod("isWebViewFocused", &Window::IsWebViewFocused) .SetMethod("capturePage", &Window::CapturePage) + .SetMethod("getWebContents", &Window::GetWebContents) + .SetMethod("getDevToolsWebContents", &Window::GetDevToolsWebContents) .SetMethod("getPageTitle", &Window::GetPageTitle) .SetMethod("isLoading", &Window::IsLoading) .SetMethod("isWaitingForResponse", &Window::IsWaitingForResponse) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index d9663231a9e0..cd3b13e86a36 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "atom/browser/native_window_observer.h" #include "atom/browser/api/event_emitter.h" +#include "native_mate/handle.h" class GURL; @@ -29,6 +30,8 @@ class NativeWindow; namespace api { +class WebContents; + class Window : public mate::EventEmitter, public NativeWindowObserver { public: @@ -100,6 +103,8 @@ class Window : public mate::EventEmitter, void CapturePage(mate::Arguments* args); // APIs for WebContents. + mate::Handle GetWebContents(v8::Isolate* isolate) const; + mate::Handle GetDevToolsWebContents(v8::Isolate* isolate) const; string16 GetPageTitle(); bool IsLoading(); bool IsWaitingForResponse(); From 79babe858def14add3bf0687a6729be180fab362 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Apr 2014 17:00:41 +0800 Subject: [PATCH 02/18] Move some APIs from Window to WebContents. --- atom/browser/api/atom_api_web_contents.cc | 45 +++++++++++++++++++++- atom/browser/api/atom_api_web_contents.h | 11 ++++++ atom/browser/api/atom_api_window.cc | 43 --------------------- atom/browser/api/atom_api_window.h | 8 ---- atom/browser/api/lib/browser-window.coffee | 12 ++++++ 5 files changed, 67 insertions(+), 52 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 47925db1f131..37b81f4e4115 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -4,6 +4,9 @@ #include "atom/browser/api/atom_api_web_contents.h" +#include "atom/common/native_mate_converters/gurl_converter.h" +#include "atom/common/native_mate_converters/string16_converter.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "native_mate/object_template_builder.h" @@ -18,9 +21,49 @@ WebContents::WebContents(content::WebContents* web_contents) WebContents::~WebContents() { } +GURL WebContents::GetURL() const { + return web_contents_->GetURL(); +} + +string16 WebContents::GetTitle() const { + return web_contents_->GetTitle(); +} + +bool WebContents::IsLoading() const { + return web_contents_->IsLoading(); +} + +bool WebContents::IsWaitingForResponse() const { + return web_contents_->IsWaitingForResponse(); +} + +void WebContents::Stop() { + web_contents_->Stop(); +} + +int WebContents::GetRoutingID() const { + return web_contents_->GetRoutingID(); +} + +int WebContents::GetProcessID() const { + return web_contents_->GetRenderProcessHost()->GetID(); +} + +bool WebContents::IsCrashed() const { + return web_contents_->IsCrashed(); +} + mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { - return mate::ObjectTemplateBuilder(isolate); + return mate::ObjectTemplateBuilder(isolate) + .SetMethod("getUrl", &WebContents::GetURL) + .SetMethod("getTitle", &WebContents::GetTitle) + .SetMethod("isLoading", &WebContents::IsLoading) + .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) + .SetMethod("stop", &WebContents::Stop) + .SetMethod("getRoutingId", &WebContents::GetRoutingID) + .SetMethod("getProcessId", &WebContents::GetProcessID) + .SetMethod("isCrashed", &WebContents::IsCrashed); } // static diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 5cad17da7772..8b8a5266d3d2 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -8,6 +8,8 @@ #include "atom/browser/api/event_emitter.h" #include "native_mate/handle.h" +class GURL; + namespace content { class WebContents; } @@ -21,6 +23,15 @@ class WebContents : public mate::EventEmitter { static mate::Handle Create(v8::Isolate* isolate, content::WebContents* web_contents); + GURL GetURL() const; + string16 GetTitle() const; + bool IsLoading() const; + bool IsWaitingForResponse() const; + void Stop(); + int GetRoutingID() const; + int GetProcessID() const; + bool IsCrashed() const; + protected: explicit WebContents(content::WebContents* web_contents); virtual ~WebContents(); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index e17e3b3e7b22..ceb300b448ba 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -336,34 +336,6 @@ mate::Handle Window::GetDevToolsWebContents( return WebContents::Create(isolate, window_->GetDevToolsWebContents()); } -string16 Window::GetPageTitle() { - return window_->GetWebContents()->GetTitle(); -} - -bool Window::IsLoading() { - return window_->GetWebContents()->IsLoading(); -} - -bool Window::IsWaitingForResponse() { - return window_->GetWebContents()->IsWaitingForResponse(); -} - -void Window::Stop() { - window_->GetWebContents()->Stop(); -} - -int Window::GetRoutingID() { - return window_->GetWebContents()->GetRoutingID(); -} - -int Window::GetProcessID() { - return window_->GetWebContents()->GetRenderProcessHost()->GetID(); -} - -bool Window::IsCrashed() { - return window_->GetWebContents()->IsCrashed(); -} - mate::Dictionary Window::GetDevTools(v8::Isolate* isolate) { mate::Dictionary dict(mate::Dictionary::CreateEmpty(isolate)); content::WebContents* web_contents = window_->GetDevToolsWebContents(); @@ -385,13 +357,6 @@ void Window::LoadURL(const GURL& url) { controller.LoadURLWithParams(params); } -GURL Window::GetURL() { - NavigationController& controller = window_->GetWebContents()->GetController(); - if (!controller.GetActiveEntry()) - return GURL(); - return controller.GetActiveEntry()->GetVirtualURL(); -} - bool Window::CanGoBack() { return window_->GetWebContents()->GetController().CanGoBack(); } @@ -474,18 +439,10 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("capturePage", &Window::CapturePage) .SetMethod("getWebContents", &Window::GetWebContents) .SetMethod("getDevToolsWebContents", &Window::GetDevToolsWebContents) - .SetMethod("getPageTitle", &Window::GetPageTitle) - .SetMethod("isLoading", &Window::IsLoading) - .SetMethod("isWaitingForResponse", &Window::IsWaitingForResponse) - .SetMethod("stop", &Window::Stop) - .SetMethod("getRoutingId", &Window::GetRoutingID) - .SetMethod("getProcessId", &Window::GetProcessID) - .SetMethod("isCrashed", &Window::IsCrashed) .SetMethod("getDevTools", &Window::GetDevTools) .SetMethod("executeJavaScriptInDevTools", &Window::ExecuteJavaScriptInDevTools) .SetMethod("loadUrl", &Window::LoadURL) - .SetMethod("getUrl", &Window::GetURL) .SetMethod("canGoBack", &Window::CanGoBack) .SetMethod("canGoForward", &Window::CanGoForward) .SetMethod("canGoToOffset", &Window::CanGoToOffset) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index cd3b13e86a36..5c3927926bfe 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -105,13 +105,6 @@ class Window : public mate::EventEmitter, // APIs for WebContents. mate::Handle GetWebContents(v8::Isolate* isolate) const; mate::Handle GetDevToolsWebContents(v8::Isolate* isolate) const; - string16 GetPageTitle(); - bool IsLoading(); - bool IsWaitingForResponse(); - void Stop(); - int GetRoutingID(); - int GetProcessID(); - bool IsCrashed(); // APIs for devtools. mate::Dictionary GetDevTools(v8::Isolate* isolate); @@ -119,7 +112,6 @@ class Window : public mate::EventEmitter, // APIs for NavigationController. void LoadURL(const GURL& url); - GURL GetURL(); bool CanGoBack(); bool CanGoForward(); bool CanGoToOffset(int offset); diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 18dacbf2e6e7..eb3d01e73eda 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -14,6 +14,8 @@ BrowserWindow::_init = -> menu = app.getApplicationMenu() @setMenu menu if menu? + @webContents = @getWebContents() + # Remember the window. id = BrowserWindow.windows.add this @@ -62,4 +64,14 @@ BrowserWindow.fromDevTools = (processId, routingId) -> return window if devtools.processId == processId and devtools.routingId == routingId +# Be compatible with old API. +BrowserWindow::getUrl = -> @webContents.getUrl() +BrowserWindow::getPageTitle = -> @webContents.getTitle() +BrowserWindow::isLoading = -> @webContents.isLoading() +BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse() +BrowserWindow::stop = -> @webContents.stop() +BrowserWindow::getRoutingId = -> @webContents.getRoutingId() +BrowserWindow::getProcessId = -> @webContents.getProcessId() +BrowserWindow::isCrashed = -> @webContents.isCrashed() + module.exports = BrowserWindow From 00ed814962419e0714bec1050513ca6399f441ba Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 10:34:40 +0800 Subject: [PATCH 03/18] Add executeJavaScript method for webContents. --- atom/browser/api/atom_api_web_contents.cc | 9 ++++++++- atom/browser/api/atom_api_web_contents.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 37b81f4e4115..d737914011c1 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -7,6 +7,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "native_mate/object_template_builder.h" @@ -53,6 +54,11 @@ bool WebContents::IsCrashed() const { return web_contents_->IsCrashed(); } +void WebContents::ExecuteJavaScript(const string16& code) { + web_contents_->GetRenderViewHost()->ExecuteJavascriptInWebFrame( + string16(), code); +} + mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) @@ -63,7 +69,8 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("stop", &WebContents::Stop) .SetMethod("getRoutingId", &WebContents::GetRoutingID) .SetMethod("getProcessId", &WebContents::GetProcessID) - .SetMethod("isCrashed", &WebContents::IsCrashed); + .SetMethod("isCrashed", &WebContents::IsCrashed) + .SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript); } // static diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 8b8a5266d3d2..c1311f9bb938 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -31,6 +31,7 @@ class WebContents : public mate::EventEmitter { int GetRoutingID() const; int GetProcessID() const; bool IsCrashed() const; + void ExecuteJavaScript(const string16& code); protected: explicit WebContents(content::WebContents* web_contents); From c5f8fbf471bda38fccf854dfd1608f080ac55018 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 10:48:11 +0800 Subject: [PATCH 04/18] Add getter for devToolsWebContents. --- atom/browser/api/atom_api_window.cc | 15 --------------- atom/browser/api/atom_api_window.h | 4 ---- atom/browser/api/lib/browser-window.coffee | 12 ++++++++++++ atom/browser/native_window.cc | 8 ++------ atom/browser/native_window.h | 1 - 5 files changed, 14 insertions(+), 26 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index ceb300b448ba..c0a9d1f58796 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -336,18 +336,6 @@ mate::Handle Window::GetDevToolsWebContents( return WebContents::Create(isolate, window_->GetDevToolsWebContents()); } -mate::Dictionary Window::GetDevTools(v8::Isolate* isolate) { - mate::Dictionary dict(mate::Dictionary::CreateEmpty(isolate)); - content::WebContents* web_contents = window_->GetDevToolsWebContents(); - dict.Set("processId", web_contents->GetRenderProcessHost()->GetID()); - dict.Set("routingId", web_contents->GetRoutingID()); - return dict; -} - -void Window::ExecuteJavaScriptInDevTools(const std::string& code) { - window_->ExecuteJavaScriptInDevTools(code); -} - void Window::LoadURL(const GURL& url) { NavigationController& controller = window_->GetWebContents()->GetController(); @@ -439,9 +427,6 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("capturePage", &Window::CapturePage) .SetMethod("getWebContents", &Window::GetWebContents) .SetMethod("getDevToolsWebContents", &Window::GetDevToolsWebContents) - .SetMethod("getDevTools", &Window::GetDevTools) - .SetMethod("executeJavaScriptInDevTools", - &Window::ExecuteJavaScriptInDevTools) .SetMethod("loadUrl", &Window::LoadURL) .SetMethod("canGoBack", &Window::CanGoBack) .SetMethod("canGoForward", &Window::CanGoForward) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 5c3927926bfe..d119f965724c 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -106,10 +106,6 @@ class Window : public mate::EventEmitter, mate::Handle GetWebContents(v8::Isolate* isolate) const; mate::Handle GetDevToolsWebContents(v8::Isolate* isolate) const; - // APIs for devtools. - mate::Dictionary GetDevTools(v8::Isolate* isolate); - void ExecuteJavaScriptInDevTools(const std::string& code); - // APIs for NavigationController. void LoadURL(const GURL& url); bool CanGoBack(); diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index eb3d01e73eda..d9cfb5ac47a8 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -14,7 +14,14 @@ BrowserWindow::_init = -> menu = app.getApplicationMenu() @setMenu menu if menu? + # Define getter for webContents. @webContents = @getWebContents() + @__devToolsWebContents = null + @__defineGetter__ 'devToolsWebContents', -> + if @isDevToolsOpened() + @__devToolsWebContents ?= @getDevToolsWebContents() + else + @__devToolsWebContents = null # Remember the window. id = BrowserWindow.windows.add this @@ -73,5 +80,10 @@ BrowserWindow::stop = -> @webContents.stop() BrowserWindow::getRoutingId = -> @webContents.getRoutingId() BrowserWindow::getProcessId = -> @webContents.getProcessId() BrowserWindow::isCrashed = -> @webContents.isCrashed() +BrowserWindow::getDevTools = -> + processId: @devToolsWebContents.getProcessId() + routingId: @devToolsWebContents.getRoutingId() +BrowserWindow::executeJavaScriptInDevTools = (code) -> + @devToolsWebContents.executeJavaScript code module.exports = BrowserWindow diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index e4627d2ec2eb..c695b6aaac64 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -229,11 +229,6 @@ void NativeWindow::InspectElement(int x, int y) { agent->InspectElement(x, y); } -void NativeWindow::ExecuteJavaScriptInDevTools(const std::string& script) { - GetDevToolsWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame( - string16(), base::UTF8ToUTF16(script)); -} - void NativeWindow::FocusOnWebView() { GetWebContents()->GetRenderViewHost()->Focus(); } @@ -628,7 +623,8 @@ void NativeWindow::CallDevToolsFunction(const std::string& function_name, } } } - ExecuteJavaScriptInDevTools(function_name + "(" + params + ");"); + GetDevToolsWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame( + string16(), base::UTF8ToUTF16(function_name + "(" + params + ");")); } void NativeWindow::OnRendererMessage(const string16& channel, diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index f10e509e4e92..7c97bfe28006 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -136,7 +136,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, virtual void CloseDevTools(); virtual bool IsDevToolsOpened(); virtual void InspectElement(int x, int y); - virtual void ExecuteJavaScriptInDevTools(const std::string& script); virtual void FocusOnWebView(); virtual void BlurWebView(); From b02bcc00167b647df8f5fff5496c99d59bdcd46e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 10:57:45 +0800 Subject: [PATCH 05/18] Get webContents on request. --- atom/browser/api/lib/browser-window.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index d9cfb5ac47a8..1687604f2f97 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -15,7 +15,9 @@ BrowserWindow::_init = -> @setMenu menu if menu? # Define getter for webContents. - @webContents = @getWebContents() + @__webContents = null + @__defineGetter__ 'webContents', -> + @__webContents ?= @getWebContents() @__devToolsWebContents = null @__defineGetter__ 'devToolsWebContents', -> if @isDevToolsOpened() From 9eeec9aa0b983c08abb81fe8b23df66d53830fd3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 11:22:51 +0800 Subject: [PATCH 06/18] Be safe on lifetime of webContents. --- atom/browser/api/atom_api_web_contents.cc | 10 ++++++++++ atom/browser/api/atom_api_web_contents.h | 16 ++++++++-------- atom/browser/api/lib/browser-window.coffee | 18 +++++++++++++----- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index d737914011c1..782e5893f459 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -17,11 +17,20 @@ namespace api { WebContents::WebContents(content::WebContents* web_contents) : web_contents_(web_contents) { + Observe(web_contents_); } WebContents::~WebContents() { } +void WebContents::WebContentsDestroyed(content::WebContents*) { + web_contents_ = NULL; +} + +bool WebContents::IsAlive() const { + return web_contents_ != NULL; +} + GURL WebContents::GetURL() const { return web_contents_->GetURL(); } @@ -62,6 +71,7 @@ void WebContents::ExecuteJavaScript(const string16& code) { mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) + .SetMethod("isAlive", &WebContents::IsAlive) .SetMethod("getUrl", &WebContents::GetURL) .SetMethod("getTitle", &WebContents::GetTitle) .SetMethod("isLoading", &WebContents::IsLoading) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index c1311f9bb938..b15b604903ad 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -6,23 +6,20 @@ #define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_ #include "atom/browser/api/event_emitter.h" +#include "content/public/browser/web_contents_observer.h" #include "native_mate/handle.h" -class GURL; - -namespace content { -class WebContents; -} - namespace atom { namespace api { -class WebContents : public mate::EventEmitter { +class WebContents : public mate::EventEmitter, + public content::WebContentsObserver { public: static mate::Handle Create(v8::Isolate* isolate, content::WebContents* web_contents); + bool IsAlive() const; GURL GetURL() const; string16 GetTitle() const; bool IsLoading() const; @@ -39,7 +36,10 @@ class WebContents : public mate::EventEmitter { // mate::Wrappable implementations: virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate); + v8::Isolate* isolate) OVERRIDE; + + // content::WebContentsObserver implementations: + virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE; private: content::WebContents* web_contents_; // Weak. diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 1687604f2f97..04b0a6f4ea33 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -15,15 +15,23 @@ BrowserWindow::_init = -> @setMenu menu if menu? # Define getter for webContents. - @__webContents = null + webContents = null @__defineGetter__ 'webContents', -> - @__webContents ?= @getWebContents() - @__devToolsWebContents = null + webContents ?= @getWebContents() + # Return null if webContents is destroyed. + webContents = null unless webContents?.isAlive() + webContents + + # And devToolsWebContents. + devToolsWebContents = null @__defineGetter__ 'devToolsWebContents', -> if @isDevToolsOpened() - @__devToolsWebContents ?= @getDevToolsWebContents() + # Get the new devToolsWebContents if previous one has been destroyed, it + # could happen when the devtools has been closed and then reopened. + devToolsWebContents = null unless devToolsWebContents?.isAlive() + devToolsWebContents ?= @getDevToolsWebContents() else - @__devToolsWebContents = null + devToolsWebContents = null # Remember the window. id = BrowserWindow.windows.add this From 859606e88c8ae04c428bfb8151da1b1d63616c4c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 11:51:05 +0800 Subject: [PATCH 07/18] Move webContents events away from window. --- atom/browser/api/atom_api_web_contents.cc | 15 +++++++++++++ atom/browser/api/atom_api_web_contents.h | 2 ++ atom/browser/api/atom_api_window.cc | 15 ++----------- atom/browser/api/atom_api_window.h | 2 -- atom/browser/api/lib/browser-window.coffee | 25 +++++++++++++--------- atom/browser/native_window.cc | 18 ---------------- atom/browser/native_window.h | 2 -- atom/browser/native_window_observer.h | 6 ------ 8 files changed, 34 insertions(+), 51 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 782e5893f459..52c6735dfff0 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -23,7 +23,22 @@ WebContents::WebContents(content::WebContents* web_contents) WebContents::~WebContents() { } +void WebContents::RenderViewDeleted(content::RenderViewHost*) { + base::ListValue args; + args.AppendInteger(GetProcessID()); + args.AppendInteger(GetRoutingID()); + Emit("render-view-deleted", args); +} + +void WebContents::RenderProcessGone(base::TerminationStatus status) { + Emit("crashed"); +} + void WebContents::WebContentsDestroyed(content::WebContents*) { + // The RenderViewDeleted is not called when the WebContents is destroyed + // directly. + RenderViewDeleted(web_contents_->GetRenderViewHost()); + web_contents_ = NULL; } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index b15b604903ad..e9a22a00b720 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -39,6 +39,8 @@ class WebContents : public mate::EventEmitter, v8::Isolate* isolate) OVERRIDE; // content::WebContentsObserver implementations: + virtual void RenderViewDeleted(content::RenderViewHost*) OVERRIDE; + virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE; private: diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index c0a9d1f58796..24bd64811e12 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -115,17 +115,6 @@ void Window::OnRendererResponsive() { Emit("responsive"); } -void Window::OnRenderViewDeleted(int process_id, int routing_id) { - base::ListValue args; - args.AppendInteger(process_id); - args.AppendInteger(routing_id); - Emit("render-view-deleted", args); -} - -void Window::OnRendererCrashed() { - Emit("crashed"); -} - // static mate::Wrappable* Window::New(mate::Arguments* args, const base::DictionaryValue& options) { @@ -425,8 +414,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("blurWebView", &Window::BlurWebView) .SetMethod("isWebViewFocused", &Window::IsWebViewFocused) .SetMethod("capturePage", &Window::CapturePage) - .SetMethod("getWebContents", &Window::GetWebContents) - .SetMethod("getDevToolsWebContents", &Window::GetDevToolsWebContents) + .SetMethod("_getWebContents", &Window::GetWebContents) + .SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents) .SetMethod("loadUrl", &Window::LoadURL) .SetMethod("canGoBack", &Window::CanGoBack) .SetMethod("canGoForward", &Window::CanGoForward) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index d119f965724c..1cf9169a9f37 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -56,8 +56,6 @@ class Window : public mate::EventEmitter, virtual void OnWindowBlur() OVERRIDE; virtual void OnRendererUnresponsive() OVERRIDE; virtual void OnRendererResponsive() OVERRIDE; - virtual void OnRenderViewDeleted(int process_id, int routing_id) OVERRIDE; - virtual void OnRendererCrashed() OVERRIDE; private: // APIs for NativeWindow. diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 04b0a6f4ea33..8db7680ad2e2 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -14,19 +14,13 @@ BrowserWindow::_init = -> menu = app.getApplicationMenu() @setMenu menu if menu? - # Define getter for webContents. - webContents = null - @__defineGetter__ 'webContents', -> - webContents ?= @getWebContents() - # Return null if webContents is destroyed. - webContents = null unless webContents?.isAlive() - webContents + @webContents = @getWebContents() - # And devToolsWebContents. + # Define getter for devToolsWebContents. devToolsWebContents = null @__defineGetter__ 'devToolsWebContents', -> if @isDevToolsOpened() - # Get the new devToolsWebContents if previous one has been destroyed, it + # Get a new devToolsWebContents if previous one has been destroyed, it # could happen when the devtools has been closed and then reopened. devToolsWebContents = null unless devToolsWebContents?.isAlive() devToolsWebContents ?= @getDevToolsWebContents() @@ -43,12 +37,23 @@ BrowserWindow::_init = -> # Tell the rpc server that a render view has been deleted and we need to # release all objects owned by it. - @on 'render-view-deleted', (event, processId, routingId) -> + @webContents.on 'render-view-deleted', (event, processId, routingId) -> process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', processId, routingId BrowserWindow::toggleDevTools = -> if @isDevToolsOpened() then @closeDevTools() else @openDevTools() +BrowserWindow::getWebContents = -> + webContents = @_getWebContents() + webContents.__proto__ = EventEmitter.prototype + webContents + +BrowserWindow::getDevToolsWebContents = -> + webContents = @_getDevToolsWebContents() + webContents.__proto__ = EventEmitter.prototype + webContents = null unless webContents.isAlive() + webContents + BrowserWindow::restart = -> @loadUrl(@getUrl()) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index c695b6aaac64..8e1daa4dfa0b 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -300,14 +300,6 @@ void NativeWindow::DestroyWebContents() { if (!inspectable_web_contents_) return; - // The OnRenderViewDeleted is not called when the WebContents is destroyed - // directly (e.g. when closing the window), so we make sure it's always - // emitted to users by sending it before window is closed.. - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, - OnRenderViewDeleted( - GetWebContents()->GetRenderProcessHost()->GetID(), - GetWebContents()->GetRoutingID())); - inspectable_web_contents_.reset(); } @@ -477,16 +469,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) { FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive()); } -void NativeWindow::RenderViewDeleted(content::RenderViewHost* rvh) { - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, - OnRenderViewDeleted(rvh->GetProcess()->GetID(), - rvh->GetRoutingID())); -} - -void NativeWindow::RenderProcessGone(base::TerminationStatus status) { - FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererCrashed()); -} - void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) { // Do nothing, we override this method just to avoid compilation error since // there are two virtual functions named BeforeUnloadFired. diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 7c97bfe28006..ba8beecb78eb 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -229,8 +229,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, virtual void RendererResponsive(content::WebContents* source) OVERRIDE; // Implementations of content::WebContentsObserver. - virtual void RenderViewDeleted(content::RenderViewHost*) OVERRIDE; - virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; virtual void BeforeUnloadFired(const base::TimeTicks& proceed_time) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 5d697480050f..52700e5bfe65 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -34,12 +34,6 @@ class NativeWindowObserver { // Called when renderer recovers. virtual void OnRendererResponsive() {} - - // Called when a render view has been deleted. - virtual void OnRenderViewDeleted(int process_id, int routing_id) {} - - // Called when renderer has crashed. - virtual void OnRendererCrashed() {} }; } // namespace atom From 744895f9d80ec087ceac1f9d35bf307a46fcf698 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 11:59:33 +0800 Subject: [PATCH 08/18] Add destroyed event for webContents. --- atom/browser/api/atom_api_web_contents.cc | 1 + atom/browser/api/lib/browser-window.coffee | 1 + 2 files changed, 2 insertions(+) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 52c6735dfff0..9205bdf8b4c0 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -39,6 +39,7 @@ void WebContents::WebContentsDestroyed(content::WebContents*) { // directly. RenderViewDeleted(web_contents_->GetRenderViewHost()); + Emit("destroyed"); web_contents_ = NULL; } diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 8db7680ad2e2..c357078a9c10 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -15,6 +15,7 @@ BrowserWindow::_init = -> @setMenu menu if menu? @webContents = @getWebContents() + @webContents.once 'destroyed', => @webContents = null # Define getter for devToolsWebContents. devToolsWebContents = null From 4135040449bdb61da1d9b25204cca8167b70b239 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 12:22:16 +0800 Subject: [PATCH 09/18] Move loading events to webContents. --- atom/browser/api/atom_api_web_contents.cc | 15 ++++++++++++++ atom/browser/api/atom_api_web_contents.h | 9 ++++++++ atom/browser/api/atom_api_window.cc | 6 ------ atom/browser/api/atom_api_window.h | 1 - atom/browser/native_window.cc | 7 ------- atom/browser/native_window.h | 1 - atom/browser/native_window_observer.h | 3 --- spec/api-browser-window-spec.coffee | 25 +++++++---------------- 8 files changed, 31 insertions(+), 36 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 9205bdf8b4c0..ac3ec4abf616 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -34,6 +34,21 @@ void WebContents::RenderProcessGone(base::TerminationStatus status) { Emit("crashed"); } +void WebContents::DidFinishLoad(int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + content::RenderViewHost* render_view_host) { + Emit("did-finish-load"); +} + +void WebContents::DidStartLoading(content::RenderViewHost* render_view_host) { + Emit("did-start-loading"); +} + +void WebContents::DidStopLoading(content::RenderViewHost* render_view_host) { + Emit("did-stop-loading"); +} + void WebContents::WebContentsDestroyed(content::WebContents*) { // The RenderViewDeleted is not called when the WebContents is destroyed // directly. diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index e9a22a00b720..5bdf3c0d645c 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -41,6 +41,15 @@ class WebContents : public mate::EventEmitter, // content::WebContentsObserver implementations: virtual void RenderViewDeleted(content::RenderViewHost*) OVERRIDE; virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; + virtual void DidFinishLoad( + int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DidStartLoading( + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DidStopLoading( + content::RenderViewHost* render_view_host) OVERRIDE; virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE; private: diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 24bd64811e12..482382f230fc 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -87,12 +87,6 @@ void Window::OnPageTitleUpdated(bool* prevent_default, *prevent_default = Emit("page-title-updated", args); } -void Window::OnLoadingStateChanged(bool is_loading) { - base::ListValue args; - args.AppendBoolean(is_loading); - Emit("loading-state-changed", args); -} - void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 1cf9169a9f37..e406e83c0a73 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -50,7 +50,6 @@ class Window : public mate::EventEmitter, // Implementations of NativeWindowObserver: virtual void OnPageTitleUpdated(bool* prevent_default, const std::string& title) OVERRIDE; - virtual void OnLoadingStateChanged(bool is_loading) OVERRIDE; virtual void WillCloseWindow(bool* prevent_default) OVERRIDE; virtual void OnWindowClosed() OVERRIDE; virtual void OnWindowBlur() OVERRIDE; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 8e1daa4dfa0b..cd5c7cd5a6b3 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -424,13 +424,6 @@ void NativeWindow::DeactivateContents(content::WebContents* contents) { BlurWebView(); } -void NativeWindow::LoadingStateChanged(content::WebContents* source) { - bool is_loading = source->IsLoading(); - FOR_EACH_OBSERVER(NativeWindowObserver, - observers_, - OnLoadingStateChanged(is_loading)); -} - void NativeWindow::MoveContents(content::WebContents* source, const gfx::Rect& pos) { SetPosition(pos.origin()); diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index ba8beecb78eb..c6bd037e2875 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -219,7 +219,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, virtual bool CanOverscrollContent() const OVERRIDE; virtual void ActivateContents(content::WebContents* contents) OVERRIDE; virtual void DeactivateContents(content::WebContents* contents) OVERRIDE; - virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE; virtual void MoveContents(content::WebContents* source, const gfx::Rect& pos) OVERRIDE; virtual void CloseContents(content::WebContents* source) OVERRIDE; diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 52700e5bfe65..a7cb41fdaeea 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -17,9 +17,6 @@ class NativeWindowObserver { virtual void OnPageTitleUpdated(bool* prevent_default, const std::string& title) {} - // Called when the window is starting or is done loading a page. - virtual void OnLoadingStateChanged(bool is_loading) {} - // Called when the window is gonna closed. virtual void WillCloseWindow(bool* prevent_default) {} diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 343ba4645bab..87e3a5249cda 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -18,9 +18,8 @@ describe 'browser-window module', -> describe 'BrowserWindow.close()', -> it 'should emit unload handler', (done) -> - w.on 'loading-state-changed', (event, isLoading) -> - if (!isLoading) - w.close() + w.webContents.on 'did-finish-load', -> + w.close() w.on 'closed', -> test = path.join(fixtures, 'api', 'unload') content = fs.readFileSync(test) @@ -32,9 +31,8 @@ describe 'browser-window module', -> it 'should emit beforeunload handler', (done) -> w.on 'onbeforeunload', -> done() - w.on 'loading-state-changed', (event, isLoading) -> - if (!isLoading) - w.close() + w.webContents.on 'did-finish-load', -> + w.close() w.loadUrl 'file://' + path.join(fixtures, 'api', 'beforeunload-false.html') describe 'window.close()', -> @@ -53,18 +51,9 @@ describe 'browser-window module', -> w.loadUrl 'file://' + path.join(fixtures, 'api', 'close-beforeunload-false.html') describe 'BrowserWindow.loadUrl(url)', -> - it 'should emit loading-state-changed event', (done) -> - count = 0 - w.on 'loading-state-changed', (event, isLoading) -> - if count == 0 - assert.equal isLoading, true - else if count == 1 - assert.equal isLoading, false - done() - else - assert false - - ++count + it 'should emit did-start-loading event', (done) -> + w.webContents.on 'did-start-loading', -> + done() w.loadUrl 'about:blank' describe 'BrowserWindow.focus()', -> From e70d195cde12543d5b36a3cedc375a0b15386724 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 12:40:04 +0800 Subject: [PATCH 10/18] Fix releasing the wrong renderer view. --- atom/browser/api/atom_api_web_contents.cc | 6 +++--- atom/browser/lib/objects-registry.coffee | 2 +- atom/browser/lib/rpc-server.coffee | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index ac3ec4abf616..26fd3eee418e 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -23,10 +23,10 @@ WebContents::WebContents(content::WebContents* web_contents) WebContents::~WebContents() { } -void WebContents::RenderViewDeleted(content::RenderViewHost*) { +void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) { base::ListValue args; - args.AppendInteger(GetProcessID()); - args.AppendInteger(GetRoutingID()); + args.AppendInteger(render_view_host->GetProcess()->GetID()); + args.AppendInteger(render_view_host->GetRoutingID()); Emit("render-view-deleted", args); } diff --git a/atom/browser/lib/objects-registry.coffee b/atom/browser/lib/objects-registry.coffee index 1bae8f6e4e50..f6c4a50d338e 100644 --- a/atom/browser/lib/objects-registry.coffee +++ b/atom/browser/lib/objects-registry.coffee @@ -78,7 +78,7 @@ class ObjectsRegistry extends EventEmitter # Clear all references to objects from renderer view. clear: (processId, routingId) -> - @emit "release-renderer-view-#{processId}-#{routingId}" + @emit "clear-#{processId}-#{routingId}" ObjectsStore.releaseForRenderView processId, routingId module.exports = new ObjectsRegistry diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index e10f875328e3..05ac5ec1a19a 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -53,7 +53,7 @@ unwrapArgs = (processId, routingId, args) -> -> returnValue when 'function' rendererReleased = false - objectsRegistry.once "release-renderer-view-#{processId}-#{routingId}", -> + objectsRegistry.once "clear-#{processId}-#{routingId}", -> rendererReleased = true ret = -> From c8a82e6e505e38c663d8d2be2754ee855ba17ab5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 12:52:30 +0800 Subject: [PATCH 11/18] Move navigator related APIs to webContents. --- atom/browser/api/atom_api_web_contents.cc | 53 ++++++++++++++++++ atom/browser/api/atom_api_web_contents.h | 10 ++++ atom/browser/api/atom_api_window.cc | 63 +--------------------- atom/browser/api/atom_api_window.h | 12 ----- atom/browser/api/lib/browser-window.coffee | 3 ++ 5 files changed, 67 insertions(+), 74 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 26fd3eee418e..1548cf3e0954 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -62,6 +62,13 @@ bool WebContents::IsAlive() const { return web_contents_ != NULL; } +void WebContents::LoadURL(const GURL& url) { + content::NavigationController::LoadURLParams params(url); + params.transition_type = content::PAGE_TRANSITION_TYPED; + params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; + web_contents_->GetController().LoadURLWithParams(params); +} + GURL WebContents::GetURL() const { return web_contents_->GetURL(); } @@ -82,6 +89,42 @@ void WebContents::Stop() { web_contents_->Stop(); } +void WebContents::Reload() { + web_contents_->GetController().Reload(false); +} + +void WebContents::ReloadIgnoringCache() { + web_contents_->GetController().ReloadIgnoringCache(false); +} + +bool WebContents::CanGoBack() const { + return web_contents_->GetController().CanGoBack(); +} + +bool WebContents::CanGoForward() const { + return web_contents_->GetController().CanGoForward(); +} + +bool WebContents::CanGoToOffset(int offset) const { + return web_contents_->GetController().CanGoToOffset(offset); +} + +void WebContents::GoBack() { + web_contents_->GetController().GoBack(); +} + +void WebContents::GoForward() { + web_contents_->GetController().GoForward(); +} + +void WebContents::GoToIndex(int index) { + web_contents_->GetController().GoToIndex(index); +} + +void WebContents::GoToOffset(int offset) { + web_contents_->GetController().GoToOffset(offset); +} + int WebContents::GetRoutingID() const { return web_contents_->GetRoutingID(); } @@ -103,11 +146,21 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) .SetMethod("isAlive", &WebContents::IsAlive) + .SetMethod("loadUrl", &WebContents::LoadURL) .SetMethod("getUrl", &WebContents::GetURL) .SetMethod("getTitle", &WebContents::GetTitle) .SetMethod("isLoading", &WebContents::IsLoading) .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) .SetMethod("stop", &WebContents::Stop) + .SetMethod("reload", &WebContents::Reload) + .SetMethod("reloadIgnoringCache", &WebContents::ReloadIgnoringCache) + .SetMethod("canGoBack", &WebContents::CanGoBack) + .SetMethod("canGoForward", &WebContents::CanGoForward) + .SetMethod("canGoToOffset", &WebContents::CanGoToOffset) + .SetMethod("goBack", &WebContents::GoBack) + .SetMethod("goForward", &WebContents::GoForward) + .SetMethod("goToIndex", &WebContents::GoToIndex) + .SetMethod("goToOffset", &WebContents::GoToOffset) .SetMethod("getRoutingId", &WebContents::GetRoutingID) .SetMethod("getProcessId", &WebContents::GetProcessID) .SetMethod("isCrashed", &WebContents::IsCrashed) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 5bdf3c0d645c..13e229db123f 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -20,11 +20,21 @@ class WebContents : public mate::EventEmitter, content::WebContents* web_contents); bool IsAlive() const; + void LoadURL(const GURL& url); GURL GetURL() const; string16 GetTitle() const; bool IsLoading() const; bool IsWaitingForResponse() const; void Stop(); + void Reload(); + void ReloadIgnoringCache(); + bool CanGoBack() const; + bool CanGoForward() const; + bool CanGoToOffset(int offset) const; + void GoBack(); + void GoForward(); + void GoToIndex(int index); + void GoToOffset(int offset); int GetRoutingID() const; int GetProcessID() const; bool IsCrashed() const; diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 482382f230fc..dae2abb93ebf 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -7,13 +7,9 @@ #include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/native_window.h" #include "atom/common/native_mate_converters/function_converter.h" -#include "atom/common/native_mate_converters/gurl_converter.h" -#include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/value_converter.h" #include "base/bind.h" #include "base/callback.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/web_contents.h" #include "content/public/browser/render_process_host.h" #include "native_mate/constructor.h" #include "native_mate/dictionary.h" @@ -23,8 +19,6 @@ #include "atom/common/node_includes.h" -using content::NavigationController; - namespace mate { template<> @@ -319,51 +313,6 @@ mate::Handle Window::GetDevToolsWebContents( return WebContents::Create(isolate, window_->GetDevToolsWebContents()); } -void Window::LoadURL(const GURL& url) { - NavigationController& controller = window_->GetWebContents()->GetController(); - - content::NavigationController::LoadURLParams params(url); - params.transition_type = content::PAGE_TRANSITION_TYPED; - params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; - controller.LoadURLWithParams(params); -} - -bool Window::CanGoBack() { - return window_->GetWebContents()->GetController().CanGoBack(); -} - -bool Window::CanGoForward() { - return window_->GetWebContents()->GetController().CanGoForward(); -} - -bool Window::CanGoToOffset(int offset) { - return window_->GetWebContents()->GetController().CanGoToOffset(offset); -} - -void Window::GoBack() { - window_->GetWebContents()->GetController().GoBack(); -} - -void Window::GoForward() { - window_->GetWebContents()->GetController().GoForward(); -} - -void Window::GoToIndex(int index) { - window_->GetWebContents()->GetController().GoToIndex(index); -} - -void Window::GoToOffset(int offset) { - window_->GetWebContents()->GetController().GoToOffset(offset); -} - -void Window::Reload() { - window_->GetWebContents()->GetController().Reload(false); -} - -void Window::ReloadIgnoringCache() { - window_->GetWebContents()->GetController().ReloadIgnoringCache(false); -} - // static void Window::BuildPrototype(v8::Isolate* isolate, v8::Handle prototype) { @@ -409,17 +358,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("isWebViewFocused", &Window::IsWebViewFocused) .SetMethod("capturePage", &Window::CapturePage) .SetMethod("_getWebContents", &Window::GetWebContents) - .SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents) - .SetMethod("loadUrl", &Window::LoadURL) - .SetMethod("canGoBack", &Window::CanGoBack) - .SetMethod("canGoForward", &Window::CanGoForward) - .SetMethod("canGoToOffset", &Window::CanGoToOffset) - .SetMethod("goBack", &Window::GoBack) - .SetMethod("goForward", &Window::GoForward) - .SetMethod("goToIndex", &Window::GoToIndex) - .SetMethod("goToOffset", &Window::GoToOffset) - .SetMethod("reload", &Window::Reload) - .SetMethod("reloadIgnoringCache", &Window::ReloadIgnoringCache); + .SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents); } } // namespace api diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index e406e83c0a73..4d762bee90b3 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -103,18 +103,6 @@ class Window : public mate::EventEmitter, mate::Handle GetWebContents(v8::Isolate* isolate) const; mate::Handle GetDevToolsWebContents(v8::Isolate* isolate) const; - // APIs for NavigationController. - void LoadURL(const GURL& url); - bool CanGoBack(); - bool CanGoForward(); - bool CanGoToOffset(int offset); - void GoBack(); - void GoForward(); - void GoToIndex(int index); - void GoToOffset(int offset); - void Reload(); - void ReloadIgnoringCache(); - scoped_ptr window_; DISALLOW_COPY_AND_ASSIGN(Window); diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index c357078a9c10..df2c5393d131 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -88,7 +88,10 @@ BrowserWindow.fromDevTools = (processId, routingId) -> devtools.routingId == routingId # Be compatible with old API. +BrowserWindow::loadUrl = (url) -> @webContents.loadUrl(url) BrowserWindow::getUrl = -> @webContents.getUrl() +BrowserWindow::reload = -> @webContents.reload() +BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache() BrowserWindow::getPageTitle = -> @webContents.getTitle() BrowserWindow::isLoading = -> @webContents.isLoading() BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse() From 272effd470bee03c1b987c1a4b358cdb17a2f588 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 13:10:16 +0800 Subject: [PATCH 12/18] Add send for webContents. --- atom/browser/api/atom_api_web_contents.cc | 62 ++++++++++++----------- atom/browser/api/atom_api_web_contents.h | 2 +- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 1548cf3e0954..7efcd0a1a9c7 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -4,8 +4,10 @@ #include "atom/browser/api/atom_api_web_contents.h" +#include "atom/common/api/api_messages.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/value_converter.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" @@ -16,11 +18,8 @@ namespace atom { namespace api { WebContents::WebContents(content::WebContents* web_contents) - : web_contents_(web_contents) { - Observe(web_contents_); -} - -WebContents::~WebContents() { + : content::WebContentsObserver(web_contents), + web_contents_(web_contents) { } void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) { @@ -50,98 +49,100 @@ void WebContents::DidStopLoading(content::RenderViewHost* render_view_host) { } void WebContents::WebContentsDestroyed(content::WebContents*) { - // The RenderViewDeleted is not called when the WebContents is destroyed - // directly. + // The RenderViewDeleted was not called when the WebContents is destroyed. RenderViewDeleted(web_contents_->GetRenderViewHost()); - Emit("destroyed"); - web_contents_ = NULL; } bool WebContents::IsAlive() const { - return web_contents_ != NULL; + return web_contents() != NULL; } void WebContents::LoadURL(const GURL& url) { content::NavigationController::LoadURLParams params(url); params.transition_type = content::PAGE_TRANSITION_TYPED; params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; - web_contents_->GetController().LoadURLWithParams(params); + web_contents()->GetController().LoadURLWithParams(params); } GURL WebContents::GetURL() const { - return web_contents_->GetURL(); + return web_contents()->GetURL(); } string16 WebContents::GetTitle() const { - return web_contents_->GetTitle(); + return web_contents()->GetTitle(); } bool WebContents::IsLoading() const { - return web_contents_->IsLoading(); + return web_contents()->IsLoading(); } bool WebContents::IsWaitingForResponse() const { - return web_contents_->IsWaitingForResponse(); + return web_contents()->IsWaitingForResponse(); } void WebContents::Stop() { - web_contents_->Stop(); + web_contents()->Stop(); } void WebContents::Reload() { - web_contents_->GetController().Reload(false); + web_contents()->GetController().Reload(false); } void WebContents::ReloadIgnoringCache() { - web_contents_->GetController().ReloadIgnoringCache(false); + web_contents()->GetController().ReloadIgnoringCache(false); } bool WebContents::CanGoBack() const { - return web_contents_->GetController().CanGoBack(); + return web_contents()->GetController().CanGoBack(); } bool WebContents::CanGoForward() const { - return web_contents_->GetController().CanGoForward(); + return web_contents()->GetController().CanGoForward(); } bool WebContents::CanGoToOffset(int offset) const { - return web_contents_->GetController().CanGoToOffset(offset); + return web_contents()->GetController().CanGoToOffset(offset); } void WebContents::GoBack() { - web_contents_->GetController().GoBack(); + web_contents()->GetController().GoBack(); } void WebContents::GoForward() { - web_contents_->GetController().GoForward(); + web_contents()->GetController().GoForward(); } void WebContents::GoToIndex(int index) { - web_contents_->GetController().GoToIndex(index); + web_contents()->GetController().GoToIndex(index); } void WebContents::GoToOffset(int offset) { - web_contents_->GetController().GoToOffset(offset); + web_contents()->GetController().GoToOffset(offset); } int WebContents::GetRoutingID() const { - return web_contents_->GetRoutingID(); + return web_contents()->GetRoutingID(); } int WebContents::GetProcessID() const { - return web_contents_->GetRenderProcessHost()->GetID(); + return web_contents()->GetRenderProcessHost()->GetID(); } bool WebContents::IsCrashed() const { - return web_contents_->IsCrashed(); + return web_contents()->IsCrashed(); } void WebContents::ExecuteJavaScript(const string16& code) { - web_contents_->GetRenderViewHost()->ExecuteJavascriptInWebFrame( + web_contents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame( string16(), code); } +bool WebContents::SendIPCMessage(const string16& channel, + const base::ListValue& args) { + return Send(new AtomViewMsg_Message(routing_id(), channel, args)); +} + mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) @@ -164,7 +165,8 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("getRoutingId", &WebContents::GetRoutingID) .SetMethod("getProcessId", &WebContents::GetProcessID) .SetMethod("isCrashed", &WebContents::IsCrashed) - .SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript); + .SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript) + .SetMethod("send", &WebContents::SendIPCMessage); } // static diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 13e229db123f..da32c492d358 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -39,10 +39,10 @@ class WebContents : public mate::EventEmitter, int GetProcessID() const; bool IsCrashed() const; void ExecuteJavaScript(const string16& code); + bool SendIPCMessage(const string16& channel, const base::ListValue& args); protected: explicit WebContents(content::WebContents* web_contents); - virtual ~WebContents(); // mate::Wrappable implementations: virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( From 1815f8b40d1f5e84c62d68555fbb383dd7261b08 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 13:14:11 +0800 Subject: [PATCH 13/18] Make send and loadUrl also supported methods of BrowserWindow. --- atom/browser/api/lib/browser-window.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index df2c5393d131..746d18167efd 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -87,8 +87,11 @@ BrowserWindow.fromDevTools = (processId, routingId) -> return window if devtools.processId == processId and devtools.routingId == routingId +# Helpers. +BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments +BrowserWindow::send = -> @webContents.send.apply @webContents, arguments + # Be compatible with old API. -BrowserWindow::loadUrl = (url) -> @webContents.loadUrl(url) BrowserWindow::getUrl = -> @webContents.getUrl() BrowserWindow::reload = -> @webContents.reload() BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache() From c0875864dc6c251480f648c428320fe222af34ef Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 16:13:16 +0800 Subject: [PATCH 14/18] Handle IPC messages in webContents instead of BrowserWindow. --- atom.gyp | 5 - atom/browser/api/atom_api_browser_ipc.cc | 37 -------- atom/browser/api/atom_api_web_contents.cc | 28 +++++- atom/browser/api/atom_api_web_contents.h | 9 ++ atom/browser/api/atom_browser_bindings.cc | 93 ------------------- atom/browser/api/atom_browser_bindings.h | 49 ---------- atom/browser/api/event_emitter.cc | 9 ++ atom/browser/api/event_emitter.h | 16 +++- atom/browser/api/lib/browser-window.coffee | 31 +++++-- atom/browser/api/lib/ipc.coffee | 31 +------ atom/browser/atom_browser_main_parts.cc | 4 +- atom/browser/atom_browser_main_parts.h | 5 +- .../browser/devtools_web_contents_observer.cc | 64 ------------- atom/browser/devtools_web_contents_observer.h | 41 -------- atom/browser/lib/rpc-server.coffee | 70 +++++++------- atom/browser/native_window.cc | 31 ------- atom/browser/native_window.h | 11 --- atom/common/api/atom_extensions.h | 1 - atom/renderer/api/lib/ipc.coffee | 12 +-- spec/api-ipc-spec.coffee | 4 +- spec/static/main.js | 8 +- 21 files changed, 138 insertions(+), 421 deletions(-) delete mode 100644 atom/browser/api/atom_api_browser_ipc.cc delete mode 100644 atom/browser/api/atom_browser_bindings.cc delete mode 100644 atom/browser/api/atom_browser_bindings.h delete mode 100644 atom/browser/devtools_web_contents_observer.cc delete mode 100644 atom/browser/devtools_web_contents_observer.h diff --git a/atom.gyp b/atom.gyp index fb1b7e79ff4d..2e2bc0359327 100644 --- a/atom.gyp +++ b/atom.gyp @@ -48,7 +48,6 @@ '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_ipc.cc', 'atom/browser/api/atom_api_dialog.cc', 'atom/browser/api/atom_api_menu.cc', 'atom/browser/api/atom_api_menu.h', @@ -66,8 +65,6 @@ 'atom/browser/api/atom_api_web_contents.h', 'atom/browser/api/atom_api_window.cc', 'atom/browser/api/atom_api_window.h', - 'atom/browser/api/atom_browser_bindings.cc', - 'atom/browser/api/atom_browser_bindings.h', 'atom/browser/api/event.cc', 'atom/browser/api/event.h', 'atom/browser/api/event_emitter.cc', @@ -95,8 +92,6 @@ 'atom/browser/browser_observer.h', 'atom/browser/devtools_delegate.cc', 'atom/browser/devtools_delegate.h', - 'atom/browser/devtools_web_contents_observer.cc', - 'atom/browser/devtools_web_contents_observer.h', 'atom/browser/mac/atom_application.h', 'atom/browser/mac/atom_application.mm', 'atom/browser/mac/atom_application_delegate.h', diff --git a/atom/browser/api/atom_api_browser_ipc.cc b/atom/browser/api/atom_api_browser_ipc.cc deleted file mode 100644 index da0da3fab302..000000000000 --- a/atom/browser/api/atom_api_browser_ipc.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/common/api/api_messages.h" -#include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/native_mate_converters/value_converter.h" -#include "content/public/browser/render_view_host.h" -#include "native_mate/dictionary.h" - -#include "atom/common/node_includes.h" - -using content::RenderViewHost; - -namespace { - -bool Send(const string16& channel, int process_id, int routing_id, - const base::ListValue& arguments) { - RenderViewHost* render_view_host(RenderViewHost::FromID( - process_id, routing_id)); - if (!render_view_host) { - node::ThrowError("Invalid render view host"); - return false; - } - - return render_view_host->Send(new AtomViewMsg_Message(routing_id, channel, - arguments)); -} - -void Initialize(v8::Handle exports) { - mate::Dictionary dict(v8::Isolate::GetCurrent(), exports); - dict.SetMethod("send", &Send); -} - -} // namespace - -NODE_MODULE(atom_browser_ipc, Initialize) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 7efcd0a1a9c7..8195a336c260 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -8,6 +8,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/value_converter.h" +#include "base/strings/utf_string_conversions.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" @@ -48,6 +49,18 @@ void WebContents::DidStopLoading(content::RenderViewHost* render_view_host) { Emit("did-stop-loading"); } +bool WebContents::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WebContents, message) + IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage) + IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync, + OnRendererMessageSync) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; +} + void WebContents::WebContentsDestroyed(content::WebContents*) { // The RenderViewDeleted was not called when the WebContents is destroyed. RenderViewDeleted(web_contents_->GetRenderViewHost()); @@ -166,7 +179,20 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("getProcessId", &WebContents::GetProcessID) .SetMethod("isCrashed", &WebContents::IsCrashed) .SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript) - .SetMethod("send", &WebContents::SendIPCMessage); + .SetMethod("_send", &WebContents::SendIPCMessage); +} + +void WebContents::OnRendererMessage(const string16& channel, + const base::ListValue& args) { + // webContents.emit(channel, new Event(), args...); + Emit(UTF16ToUTF8(channel), args, web_contents(), NULL); +} + +void WebContents::OnRendererMessageSync(const string16& channel, + const base::ListValue& args, + IPC::Message* message) { + // webContents.emit(channel, new Event(sender, message), args...); + Emit(UTF16ToUTF8(channel), args, web_contents(), message); } // static diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index da32c492d358..fb4c6082e7ee 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -60,9 +60,18 @@ class WebContents : public mate::EventEmitter, content::RenderViewHost* render_view_host) OVERRIDE; virtual void DidStopLoading( content::RenderViewHost* render_view_host) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE; private: + // Called when received a message from renderer. + void OnRendererMessage(const string16& channel, const base::ListValue& args); + + // Called when received a synchronous message from renderer. + void OnRendererMessageSync(const string16& channel, + const base::ListValue& args, + IPC::Message* message); + content::WebContents* web_contents_; // Weak. DISALLOW_COPY_AND_ASSIGN(WebContents); diff --git a/atom/browser/api/atom_browser_bindings.cc b/atom/browser/api/atom_browser_bindings.cc deleted file mode 100644 index b6b0ae6e280c..000000000000 --- a/atom/browser/api/atom_browser_bindings.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/browser/api/atom_browser_bindings.h" - -#include - -#include "atom/browser/api/event.h" -#include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/native_mate_converters/v8_value_converter.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" - -#include "atom/common/node_includes.h" - -namespace atom { - -AtomBrowserBindings::AtomBrowserBindings() { -} - -void AtomBrowserBindings::OnRendererMessage(int process_id, - int routing_id, - const string16& channel, - const base::ListValue& args) { - v8::Locker locker(node_isolate); - v8::HandleScope handle_scope(node_isolate); - - scoped_ptr converter(new V8ValueConverter); - - // process.emit(channel, 'message', process_id, routing_id); - std::vector> arguments; - arguments.reserve(3 + args.GetSize()); - arguments.push_back(mate::ConvertToV8(node_isolate, channel)); - const base::Value* value; - if (args.Get(0, &value)) - arguments.push_back(converter->ToV8Value(value, global_env->context())); - arguments.push_back(v8::Integer::New(process_id)); - arguments.push_back(v8::Integer::New(routing_id)); - - for (size_t i = 1; i < args.GetSize(); i++) { - const base::Value* value; - if (args.Get(i, &value)) - arguments.push_back(converter->ToV8Value(value, global_env->context())); - } - - node::MakeCallback(global_env->process_object(), - "emit", - arguments.size(), - &arguments[0]); -} - -void AtomBrowserBindings::OnRendererMessageSync( - int process_id, - int routing_id, - const string16& channel, - const base::ListValue& args, - content::WebContents* sender, - IPC::Message* message) { - v8::Locker locker(node_isolate); - v8::HandleScope handle_scope(node_isolate); - - scoped_ptr converter(new V8ValueConverter); - - // Create the event object. - mate::Handle event = mate::Event::Create(node_isolate); - event->SetSenderAndMessage(sender, message); - - // process.emit(channel, 'sync-message', event, process_id, routing_id); - std::vector> arguments; - arguments.reserve(3 + args.GetSize()); - arguments.push_back(mate::ConvertToV8(node_isolate, channel)); - const base::Value* value; - if (args.Get(0, &value)) - arguments.push_back(converter->ToV8Value(value, global_env->context())); - arguments.push_back(event.ToV8()); - arguments.push_back(v8::Integer::New(process_id)); - arguments.push_back(v8::Integer::New(routing_id)); - - for (size_t i = 1; i < args.GetSize(); i++) { - const base::Value* value; - if (args.Get(i, &value)) - arguments.push_back(converter->ToV8Value(value, global_env->context())); - } - - node::MakeCallback(global_env->process_object(), - "emit", - arguments.size(), - &arguments[0]); -} - -} // namespace atom diff --git a/atom/browser/api/atom_browser_bindings.h b/atom/browser/api/atom_browser_bindings.h deleted file mode 100644 index e967a4020f82..000000000000 --- a/atom/browser/api/atom_browser_bindings.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2013 GitHub, Inc. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_ -#define ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_ - -#include "atom/common/api/atom_bindings.h" -#include "base/strings/string16.h" - -namespace base { -class ListValue; -} - -namespace content { -class WebContents; -} - -namespace IPC { -class Message; -} - -namespace atom { - -class AtomBrowserBindings : public AtomBindings { - public: - AtomBrowserBindings(); - - // Called when received a message from renderer. - void OnRendererMessage(int process_id, - int routing_id, - const string16& channel, - const base::ListValue& args); - - // Called when received a synchronous message from renderer. - void OnRendererMessageSync(int process_id, - int routing_id, - const string16& channel, - const base::ListValue& args, - content::WebContents* sender, - IPC::Message* message); - - private: - DISALLOW_COPY_AND_ASSIGN(AtomBrowserBindings); -}; - -} // namespace atom - -#endif // ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_ diff --git a/atom/browser/api/event_emitter.cc b/atom/browser/api/event_emitter.cc index 5192c63488e1..45ede157d939 100644 --- a/atom/browser/api/event_emitter.cc +++ b/atom/browser/api/event_emitter.cc @@ -24,6 +24,13 @@ bool EventEmitter::Emit(const base::StringPiece& name) { bool EventEmitter::Emit(const base::StringPiece& name, const base::ListValue& args) { + return Emit(name, args, NULL, NULL); +} + +bool EventEmitter::Emit(const base::StringPiece& name, + const base::ListValue& args, + content::WebContents* sender, + IPC::Message* message) { v8::Locker locker(node_isolate); v8::HandleScope handle_scope(node_isolate); @@ -31,6 +38,8 @@ bool EventEmitter::Emit(const base::StringPiece& name, scoped_ptr converter(new atom::V8ValueConverter); mate::Handle event = mate::Event::Create(node_isolate); + if (sender && message) + event->SetSenderAndMessage(sender, message); // v8_args = [name, event, args...]; std::vector> v8_args; diff --git a/atom/browser/api/event_emitter.h b/atom/browser/api/event_emitter.h index 44e586c020d5..9a570319d478 100644 --- a/atom/browser/api/event_emitter.h +++ b/atom/browser/api/event_emitter.h @@ -11,6 +11,14 @@ namespace base { class ListValue; } +namespace content { +class WebContents; +} + +namespace IPC { +class Message; +} + namespace mate { // Provide helperers to emit event in JavaScript. @@ -18,12 +26,16 @@ class EventEmitter : public Wrappable { protected: EventEmitter(); - // this.emit(name); + // this.emit(name, new Event()); bool Emit(const base::StringPiece& name); - // this.emit(name, args...); + // this.emit(name, new Event(), args...); bool Emit(const base::StringPiece& name, const base::ListValue& args); + // this.emit(name, new Event(sender, message), args...); + bool Emit(const base::StringPiece& name, const base::ListValue& args, + content::WebContents* sender, IPC::Message* message); + private: DISALLOW_COPY_AND_ASSIGN(EventEmitter); }; diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index 746d18167efd..f4e3a23ef69b 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,10 +1,32 @@ EventEmitter = require('events').EventEmitter IDWeakMap = require 'id-weak-map' app = require 'app' +ipc = require 'ipc' BrowserWindow = process.atomBinding('window').BrowserWindow BrowserWindow::__proto__ = EventEmitter.prototype +wrapWebContents = (webContents) -> + return null unless webContents.isAlive() + # webContents is an EventEmitter. + webContents.__proto__ = EventEmitter.prototype + + # Wrap around the send method. + webContents.send = (args...) -> + @_send 'ATOM_INTERNAL_MESSAGE', [args...] + + # Dispatch the ipc messages. + webContents.on 'ipc-message', (event, channel, args...) => + Object.defineProperty event, 'sender', value: webContents + ipc.emit channel, event, args... + webContents.on 'ipc-message-sync', (event, channel, args...) => + set = (value) -> event.sendReply JSON.stringify(value) + Object.defineProperty event, 'returnValue', {set} + Object.defineProperty event, 'sender', value: webContents + ipc.emit channel, event, args... + + webContents + # Store all created windows in the weak map. BrowserWindow.windows = new IDWeakMap @@ -45,15 +67,10 @@ BrowserWindow::toggleDevTools = -> if @isDevToolsOpened() then @closeDevTools() else @openDevTools() BrowserWindow::getWebContents = -> - webContents = @_getWebContents() - webContents.__proto__ = EventEmitter.prototype - webContents + wrapWebContents @_getWebContents() BrowserWindow::getDevToolsWebContents = -> - webContents = @_getDevToolsWebContents() - webContents.__proto__ = EventEmitter.prototype - webContents = null unless webContents.isAlive() - webContents + wrapWebContents @_getDevToolsWebContents() BrowserWindow::restart = -> @loadUrl(@getUrl()) diff --git a/atom/browser/api/lib/ipc.coffee b/atom/browser/api/lib/ipc.coffee index c93ed4f20576..71cf1d17e491 100644 --- a/atom/browser/api/lib/ipc.coffee +++ b/atom/browser/api/lib/ipc.coffee @@ -1,32 +1,3 @@ EventEmitter = require('events').EventEmitter -send = process.atomBinding('ipc').send -sendWrap = (channel, processId, routingId, args...) -> - BrowserWindow = require 'browser-window' - if processId?.constructor is BrowserWindow - window = processId - args = [routingId, args...] - processId = window.getProcessId() - routingId = window.getRoutingId() - - send channel, processId, routingId, [args...] - -class Ipc extends EventEmitter - constructor: -> - process.on 'ATOM_INTERNAL_MESSAGE', (args...) => - @emit(args...) - process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (channel, event, args...) => - set = (value) -> event.sendReply JSON.stringify(value) - - Object.defineProperty event, 'returnValue', {set} - Object.defineProperty event, 'result', {set} - - @emit(channel, event, args...) - - send: (processId, routingId, args...) -> - @sendChannel(processId, routingId, 'message', args...) - - sendChannel: (args...) -> - sendWrap('ATOM_INTERNAL_MESSAGE', args...) - -module.exports = new Ipc +module.exports = new EventEmitter diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 139b15801424..ef8c95b260b1 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -4,10 +4,10 @@ #include "atom/browser/atom_browser_main_parts.h" -#include "atom/browser/api/atom_browser_bindings.h" #include "atom/browser/atom_browser_client.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/browser.h" +#include "atom/common/api/atom_bindings.h" #include "atom/common/node_bindings.h" #include "net/proxy/proxy_resolver_v8.h" @@ -23,7 +23,7 @@ namespace atom { AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL; AtomBrowserMainParts::AtomBrowserMainParts() - : atom_bindings_(new AtomBrowserBindings), + : atom_bindings_(new AtomBindings), browser_(new Browser), node_bindings_(NodeBindings::Create(true)) { DCHECK(!self_) << "Cannot have two AtomBrowserMainParts"; diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 896f36e00e02..41de38699e11 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -9,7 +9,7 @@ namespace atom { -class AtomBrowserBindings; +class AtomBindings; class Browser; class NodeBindings; @@ -20,7 +20,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { static AtomBrowserMainParts* Get(); - AtomBrowserBindings* atom_bindings() { return atom_bindings_.get(); } Browser* browser() { return browser_.get(); } protected: @@ -37,7 +36,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { #endif private: - scoped_ptr atom_bindings_; + scoped_ptr atom_bindings_; scoped_ptr browser_; scoped_ptr node_bindings_; diff --git a/atom/browser/devtools_web_contents_observer.cc b/atom/browser/devtools_web_contents_observer.cc deleted file mode 100644 index 331a1253ca6c..000000000000 --- a/atom/browser/devtools_web_contents_observer.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "atom/browser/devtools_web_contents_observer.h" - -#include "atom/browser/api/atom_browser_bindings.h" -#include "atom/browser/atom_browser_main_parts.h" -#include "atom/browser/native_window.h" -#include "atom/common/api/api_messages.h" -#include "base/logging.h" -#include "content/public/browser/render_process_host.h" -#include "ipc/ipc_message_macros.h" - -namespace atom { - -DevToolsWebContentsObserver::DevToolsWebContentsObserver( - NativeWindow* native_window, - content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), - inspected_window_(native_window) { - DCHECK(native_window); -} - -DevToolsWebContentsObserver::~DevToolsWebContentsObserver() { -} - -bool DevToolsWebContentsObserver::OnMessageReceived( - const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(DevToolsWebContentsObserver, message) - IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage) - IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync, - OnRendererMessageSync) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled; -} - -void DevToolsWebContentsObserver::OnRendererMessage( - const string16& channel, - const base::ListValue& args) { - AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage( - web_contents()->GetRenderProcessHost()->GetID(), - web_contents()->GetRoutingID(), - channel, - args); -} - -void DevToolsWebContentsObserver::OnRendererMessageSync( - const string16& channel, - const base::ListValue& args, - IPC::Message* reply_msg) { - AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync( - web_contents()->GetRenderProcessHost()->GetID(), - web_contents()->GetRoutingID(), - channel, - args, - web_contents(), - reply_msg); -} - -} // namespace atom diff --git a/atom/browser/devtools_web_contents_observer.h b/atom/browser/devtools_web_contents_observer.h deleted file mode 100644 index 3fc2222a43b7..000000000000 --- a/atom/browser/devtools_web_contents_observer.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2014 GitHub, Inc. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_ -#define ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_ - -#include "content/public/browser/web_contents_observer.h" - -namespace base { -class ListValue; -} - -namespace atom { - -class NativeWindow; - -class DevToolsWebContentsObserver : public content::WebContentsObserver { - public: - DevToolsWebContentsObserver(NativeWindow* native_window, - content::WebContents* web_contents); - virtual ~DevToolsWebContentsObserver(); - - protected: - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - void OnRendererMessage(const string16& channel, - const base::ListValue& args); - void OnRendererMessageSync(const string16& channel, - const base::ListValue& args, - IPC::Message* reply_msg); - - private: - NativeWindow* inspected_window_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver); -}; - -} // namespace atom - -#endif // ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_ diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 05ac5ec1a19a..73dc54059fe8 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -4,7 +4,7 @@ objectsRegistry = require './objects-registry.js' v8Util = process.atomBinding 'v8_util' # Convert a real value into meta data. -valueToMeta = (processId, routingId, value) -> +valueToMeta = (sender, value) -> meta = type: typeof value meta.type = 'value' if value is null @@ -15,13 +15,15 @@ valueToMeta = (processId, routingId, value) -> if meta.type is 'array' meta.members = [] - meta.members.push valueToMeta(processId, routingId, el) for el in value + meta.members.push valueToMeta(sender, el) for el in value else if meta.type is 'object' or meta.type is 'function' meta.name = value.constructor.name # Reference the original value if it's an object, because when it's # passed to renderer we would assume the renderer keeps a reference of # it. + processId = sender.getProcessId() + routingId = sender.getRoutingId() [meta.id, meta.storeId] = objectsRegistry.add processId, routingId, value meta.members = [] @@ -37,12 +39,14 @@ errorToMeta = (error) -> type: 'error', message: error.message, stack: (error.stack || error) # Convert array of meta data from renderer into array of real values. -unwrapArgs = (processId, routingId, args) -> +unwrapArgs = (sender, args) -> + processId = sender.getProcessId() + routingId = sender.getRoutingId() metaToValue = (meta) -> switch meta.type when 'value' then meta.value when 'remote-object' then objectsRegistry.get meta.id - when 'array' then unwrapArgs processId, routingId, meta.value + when 'array' then unwrapArgs sender, meta.value when 'object' ret = v8Util.createObjectWithName meta.name for member in meta.members @@ -58,10 +62,10 @@ unwrapArgs = (processId, routingId, args) -> ret = -> throw new Error('Calling a callback of released renderer view') if rendererReleased - ipc.sendChannel processId, routingId, 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(processId, routingId, arguments) + sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments) v8Util.setDestructor ret, -> return if rendererReleased - ipc.sendChannel processId, routingId, 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id + sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id ret else throw new TypeError("Unknown type: #{meta.type}") @@ -69,78 +73,80 @@ unwrapArgs = (processId, routingId, args) -> # Call a function and send reply asynchronously if it's a an asynchronous # style function and the caller didn't pass a callback. -callFunction = (event, processId, routingId, func, caller, args) -> +callFunction = (event, func, caller, args) -> if v8Util.getHiddenValue(func, 'asynchronous') and typeof args[args.length - 1] isnt 'function' args.push (ret) -> - event.returnValue = valueToMeta processId, routingId, ret + event.returnValue = valueToMeta event.sender, ret func.apply caller, args else ret = func.apply caller, args - event.returnValue = valueToMeta processId, routingId, ret + event.returnValue = valueToMeta event.sender, ret # Send by BrowserWindow when its render view is deleted. process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (processId, routingId) -> objectsRegistry.clear processId, routingId -ipc.on 'ATOM_BROWSER_REQUIRE', (event, processId, routingId, module) -> +ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) -> try - event.returnValue = valueToMeta processId, routingId, require(module) + event.returnValue = valueToMeta event.sender, require(module) catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_GLOBAL', (event, processId, routingId, name) -> +ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) -> try - event.returnValue = valueToMeta processId, routingId, global[name] + event.returnValue = valueToMeta event.sender, global[name] catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, processId, routingId) -> +ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) -> try BrowserWindow = require 'browser-window' + processId = event.sender.getProcessId() + routingId = event.sender.getRoutingId() window = BrowserWindow.fromProcessIdAndRoutingId processId, routingId window = BrowserWindow.fromDevTools processId, routingId unless window? - event.returnValue = valueToMeta processId, routingId, window + event.returnValue = valueToMeta event.sender, window catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, processId, routingId, id, args) -> +ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) -> try - args = unwrapArgs processId, routingId, args + args = unwrapArgs event.sender, args constructor = objectsRegistry.get id # Call new with array of arguments. # http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible obj = new (Function::bind.apply(constructor, [null].concat(args))) - event.returnValue = valueToMeta processId, routingId, obj + event.returnValue = valueToMeta event.sender, obj catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, processId, routingId, id, args) -> +ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) -> try - args = unwrapArgs processId, routingId, args + args = unwrapArgs event.sender, args func = objectsRegistry.get id - callFunction event, processId, routingId, func, global, args + callFunction event, func, global, args catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, processId, routingId, id, method, args) -> +ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) -> try - args = unwrapArgs processId, routingId, args + args = unwrapArgs event.sender, args constructor = objectsRegistry.get(id)[method] # Call new with array of arguments. obj = new (Function::bind.apply(constructor, [null].concat(args))) - event.returnValue = valueToMeta processId, routingId, obj + event.returnValue = valueToMeta event.sender, obj catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, processId, routingId, id, method, args) -> +ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) -> try - args = unwrapArgs processId, routingId, args + args = unwrapArgs event.sender, args obj = objectsRegistry.get id - callFunction event, processId, routingId, obj[method], obj, args + callFunction event, obj[method], obj, args catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, processId, routingId, id, name, value) -> +ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) -> try obj = objectsRegistry.get id obj[name] = value @@ -148,12 +154,14 @@ ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, processId, routingId, id, name, value) catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, processId, routingId, id, name) -> +ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) -> try obj = objectsRegistry.get id - event.returnValue = valueToMeta processId, routingId, obj[name] + event.returnValue = valueToMeta event.sender, obj[name] catch e event.returnValue = errorToMeta e -ipc.on 'ATOM_BROWSER_DEREFERENCE', (processId, routingId, storeId) -> +ipc.on 'ATOM_BROWSER_DEREFERENCE', (event, storeId) -> + processId = event.sender.getProcessId() + routingId = event.sender.getRoutingId() objectsRegistry.remove processId, routingId, storeId diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index cd5c7cd5a6b3..7e54870bd64d 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -8,13 +8,10 @@ #include #include -#include "atom/browser/api/atom_browser_bindings.h" #include "atom/browser/atom_browser_context.h" -#include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_javascript_dialog_manager.h" #include "atom/browser/browser.h" #include "atom/browser/devtools_delegate.h" -#include "atom/browser/devtools_web_contents_observer.h" #include "atom/browser/ui/file_dialog.h" #include "atom/browser/window_list.h" #include "atom/common/api/api_messages.h" @@ -195,12 +192,8 @@ bool NativeWindow::HasModalDialog() { void NativeWindow::OpenDevTools() { if (devtools_window_) { devtools_window_->Focus(true); - devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver( - this, devtools_window_->GetWebContents())); } else { inspectable_web_contents()->ShowDevTools(); - devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver( - this, GetDevToolsWebContents())); #if defined(OS_MACOSX) // Temporary fix for flashing devtools, try removing this after upgraded to // Chrome 32. @@ -470,9 +463,6 @@ void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) { bool NativeWindow::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(NativeWindow, message) - IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage) - IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync, - OnRendererMessageSync) IPC_MESSAGE_HANDLER(AtomViewHostMsg_UpdateDraggableRegions, UpdateDraggableRegions) IPC_MESSAGE_UNHANDLED(handled = false) @@ -602,25 +592,4 @@ void NativeWindow::CallDevToolsFunction(const std::string& function_name, string16(), base::UTF8ToUTF16(function_name + "(" + params + ");")); } -void NativeWindow::OnRendererMessage(const string16& channel, - const base::ListValue& args) { - AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage( - GetWebContents()->GetRenderProcessHost()->GetID(), - GetWebContents()->GetRoutingID(), - channel, - args); -} - -void NativeWindow::OnRendererMessageSync(const string16& channel, - const base::ListValue& args, - IPC::Message* reply_msg) { - AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync( - GetWebContents()->GetRenderProcessHost()->GetID(), - GetWebContents()->GetRoutingID(), - channel, - args, - GetWebContents(), - reply_msg); -} - } // namespace atom diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index c6bd037e2875..1d638063c267 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -46,7 +46,6 @@ namespace atom { class AtomJavaScriptDialogManager; class DevToolsDelegate; -class DevToolsWebContentsObserver; struct DraggableRegion; class NativeWindow : public brightray::DefaultWebContentsDelegate, @@ -270,13 +269,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, bool succeed, const SkBitmap& bitmap); - void OnRendererMessage(const string16& channel, - const base::ListValue& args); - - void OnRendererMessageSync(const string16& channel, - const base::ListValue& args, - IPC::Message* reply_msg); - // Notification manager. content::NotificationRegistrar registrar_; @@ -301,9 +293,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, base::WeakPtr devtools_window_; scoped_ptr devtools_delegate_; - // WebContentsObserver for the WebContents of devtools. - scoped_ptr devtools_web_contents_observer_; - scoped_ptr dialog_manager_; // Notice that inspectable_web_contents_ must be placed after dialog_manager_, diff --git a/atom/common/api/atom_extensions.h b/atom/common/api/atom_extensions.h index 5bba348c0ed4..62a0826403c5 100644 --- a/atom/common/api/atom_extensions.h +++ b/atom/common/api/atom_extensions.h @@ -12,7 +12,6 @@ NODE_EXT_LIST_START NODE_EXT_LIST_ITEM(atom_browser_app) NODE_EXT_LIST_ITEM(atom_browser_auto_updater) NODE_EXT_LIST_ITEM(atom_browser_dialog) -NODE_EXT_LIST_ITEM(atom_browser_ipc) NODE_EXT_LIST_ITEM(atom_browser_menu) NODE_EXT_LIST_ITEM(atom_browser_power_monitor) NODE_EXT_LIST_ITEM(atom_browser_protocol) diff --git a/atom/renderer/api/lib/ipc.coffee b/atom/renderer/api/lib/ipc.coffee index 545e6a2168a8..3d4ec30ba356 100644 --- a/atom/renderer/api/lib/ipc.coffee +++ b/atom/renderer/api/lib/ipc.coffee @@ -10,15 +10,13 @@ class Ipc extends EventEmitter process.removeAllListeners 'ATOM_INTERNAL_MESSAGE' send: (args...) -> - @sendChannel 'message', args... - - sendChannel: (args...) -> - ipc.send 'ATOM_INTERNAL_MESSAGE', [args...] + ipc.send 'ipc-message', [args...] sendSync: (args...) -> - @sendSync 'sync-message', args... + JSON.parse ipc.sendSync('ipc-message-sync', [args...]) - sendChannelSync: (args...) -> - JSON.parse ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', [args...]) + # Discarded + sendChannel: -> @send.apply this, arguments + sendChannelSync: -> @sendSync.apply this, arguments module.exports = new Ipc diff --git a/spec/api-ipc-spec.coffee b/spec/api-ipc-spec.coffee index 1116d1bce280..1529e178f503 100644 --- a/spec/api-ipc-spec.coffee +++ b/spec/api-ipc-spec.coffee @@ -48,13 +48,13 @@ describe 'ipc module', -> print_name = remote.require path.join(fixtures, 'module', 'print_name.js') assert.equal print_name.print(buf), 'Buffer' - describe 'ipc.send', -> + describe 'ipc.sender.send', -> it 'should work when sending an object containing id property', (done) -> obj = id: 1, name: 'ly' ipc.once 'message', (message) -> assert.deepEqual message, obj done() - ipc.send obj + ipc.send 'message', obj describe 'ipc.sendSync', -> it 'can be replied by setting event.returnValue', -> diff --git a/spec/static/main.js b/spec/static/main.js index 6ec1cf1b892b..5d11ed04ffa5 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -8,8 +8,8 @@ var window = null; app.commandLine.appendSwitch('js-flags', '--expose_gc'); -ipc.on('message', function() { - ipc.send.apply(this, arguments); +ipc.on('message', function(event, arg) { + event.sender.send('message', arg); }); ipc.on('console.log', function(pid, rid, args) { @@ -24,11 +24,11 @@ ipc.on('process.exit', function(pid, rid, code) { process.exit(code); }); -ipc.on('eval', function(ev, pid, rid, script) { +ipc.on('eval', function(ev, script) { ev.returnValue = eval(script); }); -ipc.on('echo', function(ev, pid, rid, msg) { +ipc.on('echo', function(ev, msg) { ev.returnValue = msg; }); From 23ccad49151883aae9285552112b4e4c568fa63f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 16:23:40 +0800 Subject: [PATCH 15/18] Separate the webContents code in a new file. --- atom.gyp | 1 + atom/browser/api/lib/browser-window.coffee | 23 +--------------------- atom/browser/api/lib/web-contents.coffee | 23 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 22 deletions(-) create mode 100644 atom/browser/api/lib/web-contents.coffee diff --git a/atom.gyp b/atom.gyp index 2e2bc0359327..016260065ba6 100644 --- a/atom.gyp +++ b/atom.gyp @@ -24,6 +24,7 @@ 'atom/browser/api/lib/menu-item.coffee', 'atom/browser/api/lib/power-monitor.coffee', 'atom/browser/api/lib/protocol.coffee', + 'atom/browser/api/lib/web-contents.coffee', 'atom/browser/lib/init.coffee', 'atom/browser/lib/objects-registry.coffee', 'atom/browser/lib/rpc-server.coffee', diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index f4e3a23ef69b..a09c3fe71a18 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,32 +1,11 @@ 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 -wrapWebContents = (webContents) -> - return null unless webContents.isAlive() - # webContents is an EventEmitter. - webContents.__proto__ = EventEmitter.prototype - - # Wrap around the send method. - webContents.send = (args...) -> - @_send 'ATOM_INTERNAL_MESSAGE', [args...] - - # Dispatch the ipc messages. - webContents.on 'ipc-message', (event, channel, args...) => - Object.defineProperty event, 'sender', value: webContents - ipc.emit channel, event, args... - webContents.on 'ipc-message-sync', (event, channel, args...) => - set = (value) -> event.sendReply JSON.stringify(value) - Object.defineProperty event, 'returnValue', {set} - Object.defineProperty event, 'sender', value: webContents - ipc.emit channel, event, args... - - webContents - # Store all created windows in the weak map. BrowserWindow.windows = new IDWeakMap diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee new file mode 100644 index 000000000000..f3795afe7d4f --- /dev/null +++ b/atom/browser/api/lib/web-contents.coffee @@ -0,0 +1,23 @@ +EventEmitter = require('events').EventEmitter +ipc = require 'ipc' + +module.exports.wrap = (webContents) -> + return null unless webContents.isAlive() + + # webContents is an EventEmitter. + webContents.__proto__ = EventEmitter.prototype + + # Add the send method. + webContents.send = (args...) -> + @_send 'ATOM_INTERNAL_MESSAGE', [args...] + + # Dispatch IPC messages to the ipc module. + webContents.on 'ipc-message', (event, channel, args...) => + Object.defineProperty event, 'sender', value: webContents + ipc.emit channel, event, args... + webContents.on 'ipc-message-sync', (event, channel, args...) => + Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) + Object.defineProperty event, 'sender', value: webContents + ipc.emit channel, event, args... + + webContents From 1bba15cb7f55cfcf5c11f0157dd0ef94befc947e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 16:45:14 +0800 Subject: [PATCH 16/18] Avoid using processId and routingId directly. --- atom/browser/api/lib/browser-window.coffee | 17 +++++------------ atom/browser/api/lib/web-contents.coffee | 6 +++++- atom/browser/lib/objects-registry.coffee | 20 +++++++++----------- atom/browser/lib/rpc-server.coffee | 22 +++++++--------------- 4 files changed, 26 insertions(+), 39 deletions(-) diff --git a/atom/browser/api/lib/browser-window.coffee b/atom/browser/api/lib/browser-window.coffee index a09c3fe71a18..9a1f26a58506 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -40,7 +40,7 @@ BrowserWindow::_init = -> # Tell the rpc server that a render view has been deleted and we need to # release all objects owned by it. @webContents.on 'render-view-deleted', (event, processId, routingId) -> - process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', processId, routingId + process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}" BrowserWindow::toggleDevTools = -> if @isDevToolsOpened() then @closeDevTools() else @openDevTools() @@ -71,17 +71,13 @@ BrowserWindow.getFocusedWindow = -> windows = BrowserWindow.getAllWindows() return window for window in windows when window.isFocused() -BrowserWindow.fromProcessIdAndRoutingId = (processId, routingId) -> +BrowserWindow.fromWebContents = (webContents) -> windows = BrowserWindow.getAllWindows() - return window for window in windows when window.getProcessId() == processId and - window.getRoutingId() == routingId + return window for window in windows when webContents.equal window.webContents -BrowserWindow.fromDevTools = (processId, routingId) -> +BrowserWindow.fromDevToolsWebContents = (webContents) -> windows = BrowserWindow.getAllWindows() - for window in windows when window.isDevToolsOpened() - devtools = window.getDevTools() - return window if devtools.processId == processId and - devtools.routingId == routingId + return window for window in windows when webContents.equal window.devToolsWebContents # Helpers. BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments @@ -98,9 +94,6 @@ BrowserWindow::stop = -> @webContents.stop() BrowserWindow::getRoutingId = -> @webContents.getRoutingId() BrowserWindow::getProcessId = -> @webContents.getProcessId() BrowserWindow::isCrashed = -> @webContents.isCrashed() -BrowserWindow::getDevTools = -> - processId: @devToolsWebContents.getProcessId() - routingId: @devToolsWebContents.getRoutingId() BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents.executeJavaScript code diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index f3795afe7d4f..5e7212334764 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -7,10 +7,14 @@ module.exports.wrap = (webContents) -> # webContents is an EventEmitter. webContents.__proto__ = EventEmitter.prototype - # Add the send method. + # WebContents::send(channel, args..) webContents.send = (args...) -> @_send 'ATOM_INTERNAL_MESSAGE', [args...] + # The processId and routingId and identify a webContents. + webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}" + webContents.equal = (other) -> @getId() is other.getId() + # Dispatch IPC messages to the ipc module. webContents.on 'ipc-message', (event, channel, args...) => Object.defineProperty event, 'sender', value: webContents diff --git a/atom/browser/lib/objects-registry.coffee b/atom/browser/lib/objects-registry.coffee index f6c4a50d338e..e159730330e2 100644 --- a/atom/browser/lib/objects-registry.coffee +++ b/atom/browser/lib/objects-registry.coffee @@ -29,13 +29,11 @@ class ObjectsStore throw new Error("Invalid key #{id} for ObjectsStore") unless @has id @objects[id] - @forRenderView: (processId, routingId) -> - key = "#{processId}_#{routingId}" + @forRenderView: (key) -> @stores[key] = new ObjectsStore unless @stores[key]? @stores[key] - @releaseForRenderView: (processId, routingId) -> - key = "#{processId}_#{routingId}" + @releaseForRenderView: (key) -> delete @stores[key] class ObjectsRegistry extends EventEmitter @@ -52,7 +50,7 @@ class ObjectsRegistry extends EventEmitter # Register a new object, the object would be kept referenced until you release # it explicitly. - add: (processId, routingId, obj) -> + add: (key, obj) -> # Some native objects may already been added to objectsWeakMap, be care not # to add it twice. @objectsWeakMap.add obj unless v8Util.getHiddenValue obj, 'atomId' @@ -63,7 +61,7 @@ class ObjectsRegistry extends EventEmitter # with the storeId. # We use a difference key because the same object can be referenced for # multiple times by the same renderer view. - store = ObjectsStore.forRenderView processId, routingId + store = ObjectsStore.forRenderView key storeId = store.add obj [id, storeId] @@ -73,12 +71,12 @@ class ObjectsRegistry extends EventEmitter @objectsWeakMap.get id # Remove an object according to its storeId. - remove: (processId, routingId, storeId) -> - ObjectsStore.forRenderView(processId, routingId).remove storeId + remove: (key, storeId) -> + ObjectsStore.forRenderView(key).remove storeId # Clear all references to objects from renderer view. - clear: (processId, routingId) -> - @emit "clear-#{processId}-#{routingId}" - ObjectsStore.releaseForRenderView processId, routingId + clear: (key) -> + @emit "clear-#{key}" + ObjectsStore.releaseForRenderView key module.exports = new ObjectsRegistry diff --git a/atom/browser/lib/rpc-server.coffee b/atom/browser/lib/rpc-server.coffee index 73dc54059fe8..a28c4b25af3f 100644 --- a/atom/browser/lib/rpc-server.coffee +++ b/atom/browser/lib/rpc-server.coffee @@ -22,9 +22,7 @@ valueToMeta = (sender, value) -> # Reference the original value if it's an object, because when it's # passed to renderer we would assume the renderer keeps a reference of # it. - processId = sender.getProcessId() - routingId = sender.getRoutingId() - [meta.id, meta.storeId] = objectsRegistry.add processId, routingId, value + [meta.id, meta.storeId] = objectsRegistry.add sender.getId(), value meta.members = [] meta.members.push {name: prop, type: typeof field} for prop, field of value @@ -40,8 +38,6 @@ errorToMeta = (error) -> # Convert array of meta data from renderer into array of real values. unwrapArgs = (sender, args) -> - processId = sender.getProcessId() - routingId = sender.getRoutingId() metaToValue = (meta) -> switch meta.type when 'value' then meta.value @@ -57,7 +53,7 @@ unwrapArgs = (sender, args) -> -> returnValue when 'function' rendererReleased = false - objectsRegistry.once "clear-#{processId}-#{routingId}", -> + objectsRegistry.once "clear-#{sender.getId()}", -> rendererReleased = true ret = -> @@ -83,8 +79,8 @@ callFunction = (event, func, caller, args) -> event.returnValue = valueToMeta event.sender, ret # Send by BrowserWindow when its render view is deleted. -process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (processId, routingId) -> - objectsRegistry.clear processId, routingId +process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> + objectsRegistry.clear id ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) -> try @@ -101,10 +97,8 @@ ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) -> ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) -> try BrowserWindow = require 'browser-window' - processId = event.sender.getProcessId() - routingId = event.sender.getRoutingId() - window = BrowserWindow.fromProcessIdAndRoutingId processId, routingId - window = BrowserWindow.fromDevTools processId, routingId unless window? + window = BrowserWindow.fromWebContents event.sender + window = BrowserWindow.fromDevToolsWebContents event.sender unless window? event.returnValue = valueToMeta event.sender, window catch e event.returnValue = errorToMeta e @@ -162,6 +156,4 @@ ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) -> event.returnValue = errorToMeta e ipc.on 'ATOM_BROWSER_DEREFERENCE', (event, storeId) -> - processId = event.sender.getProcessId() - routingId = event.sender.getRoutingId() - objectsRegistry.remove processId, routingId, storeId + objectsRegistry.remove event.sender.getId(), storeId From 1fd8deaca75906fd96117811d81c11f22e62c8e4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 17:15:26 +0800 Subject: [PATCH 17/18] :memo: Add docs on WebContents. --- docs/api/browser/browser-window.md | 145 +++++++++++++++++------------ 1 file changed, 83 insertions(+), 62 deletions(-) diff --git a/docs/api/browser/browser-window.md b/docs/api/browser/browser-window.md index ae25fd0389ce..19fcb2591aa5 100644 --- a/docs/api/browser/browser-window.md +++ b/docs/api/browser/browser-window.md @@ -7,7 +7,7 @@ example is: var BrowserWindow = require('browser-window'); var win = new BrowserWindow({ width: 800, height: 600, show: false }); -win.on('destroyed', function() { +win.on('closed', function() { win = null; }); @@ -86,13 +86,6 @@ you should explictly set `sandbox` to `none`: Emitted when the document changed its title, calling `event.preventDefault()` would prevent the native window's title to change. -### Event: 'loading-state-changed' - -* `event` Event -* `isLoading` Boolean - -Emitted when the window is starting or is done loading a page. - ### Event: 'close' * `event` Event @@ -137,10 +130,6 @@ Emiited when the web page becomes unresponsive. Emitted when the unresponsive web page becomes responsive again. -### Event: 'crashed' - -Emitted when the renderer process is crashed. - ### Event: 'blur' Emiited when window loses focus. @@ -153,12 +142,20 @@ Returns an array of all opened browser windows. Returns the window that is focused in this application. -### Class Method: BrowserWindow.fromProcessIdAndRoutingId(processId, routingId) +### Class Method: BrowserWindow.fromWebContents(webContents) -* `processId` Integer -* `routingId` Integer +* `webContents` WebContents -Find a window according to its `processId` and `routingId`. +Find a window according to the `webContents` it owns + +### BrowserWindow.webContents + +The `WebContents` object this window owns, all web page related events and +operations would be done via it. + +### BrowserWindow.devToolsWebContents + +Get the `WebContents` of devtools of this window. ### BrowserWindow.destroy() @@ -334,13 +331,6 @@ Closes the developer tools. Starts inspecting element at position (`x`, `y`). -### BrowserWindow.executeJavaScriptInDevTools(code) - -* `code` String - -Evaluate `code` in devtools to use -[InspectorFrontendAPI](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/devtools/front_end/InspectorFrontendAPI.js&q=InspectorFrontendAPI&sq=package:chromium&type=cs) - ### BrowserWindow.focusOnWebView() ### BrowserWindow.blurWebView() @@ -366,82 +356,113 @@ encode it and use data URL to embed the image in HTML. [remote](../renderer/remote.md) if you are going to use this API in renderer process. -### BrowserWindow.getPageTitle() - -Returns the title of web page. - -### BrowserWindow.isLoading() - -Returns whether web page is still loading resources. - -### BrowserWindow.isWaitingForResponse() - -Returns whether web page is waiting for a first-response for the main resource -of the page. - -### BrowserWindow.stop() - -Stops any pending navigation. - -### BrowserWindow.getProcessId() - -Returns window's process ID. The process ID and routing ID can be used -together to locate a window. - -### BrowserWindow.getRoutingId() - -Returns window's routing ID. The process ID and routing ID can be used -together to locate a window. - ### BrowserWindow.loadUrl(url) +Same with `webContents.loadUrl(url)`. + +## Class: WebContents + +A `WebContents` is responsible for rendering and controlling a web page. + +`WebContents` is an +[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter). + +### Event: 'crashed' + +Emitted when the renderer process is crashed. + +### Event: 'did-finish-load' + +Emitted when the navigation is done, i.e. the spinner of the tab will stop +spinning, and the onload event was dispatched. + +### Event: 'did-start-loading' + +### Event: 'did-stop-loading' + +### WebContents.loadUrl(url) + * `url` URL Loads the `url` in the window, the `url` must contains the protocol prefix, e.g. the `http://` or `file://`. -### BrowserWindow.getUrl() +### WebContents.getUrl() Returns URL of current web page. -### BrowserWindow.canGoBack() +### WebContents.getTitle() + +Returns the title of web page. + +### WebContents.isLoading() + +Returns whether web page is still loading resources. + +### WebContents.isWaitingForResponse() + +Returns whether web page is waiting for a first-response for the main resource +of the page. + +### WebContents.stop() + +Stops any pending navigation. + +### WebContents.reload() + +Reloads current page. + +### WebContents.reloadIgnoringCache() + +Reloads current page and ignores cache. + +### WebContents.canGoBack() Returns whether the web page can go back. -### BrowserWindow.canGoForward() +### WebContents.canGoForward() Returns whether the web page can go forward. -### BrowserWindow.canGoToOffset(offset) +### WebContents.canGoToOffset(offset) * `offset` Integer Returns whether the web page can go to `offset`. -### BrowserWindow.goBack() +### WebContents.goBack() Makes the web page go back. -### BrowserWindow.goForward() +### WebContents.goForward() Makes the web page go forward. -### BrowserWindow.goToIndex(index) +### WebContents.goToIndex(index) * `index` Integer Navigates to the specified absolute index. -### BrowserWindow.goToOffset(offset) +### WebContents.goToOffset(offset) * `offset` Integer Navigates to the specified offset from the "current entry". -### BrowserWindow.reload() +### WebContents.IsCrashed() -Reloads current window. +Whether the renderer process has crashed. -### BrowserWindow.reloadIgnoringCache() +### WebContents.executeJavaScript(code) -Reloads current window and ignores cache. +* `code` String + +Evaluate `code` in page. + +### WebContents.send(channel[, args...]) + +* `channel` String + +Send `args..` to the web page via `channel` in asynchronous message, the web +page can handle it by listening to the `channel` event of `ipc` module. From 85f6edb81575fb4d2cfefad63e53511bb0632b95 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Apr 2014 17:35:36 +0800 Subject: [PATCH 18/18] :memo: Update docs of ipc module. --- docs/api/browser/ipc-browser.md | 83 ++++++++++++++----------------- docs/api/renderer/ipc-renderer.md | 75 ++++------------------------ 2 files changed, 47 insertions(+), 111 deletions(-) diff --git a/docs/api/browser/ipc-browser.md b/docs/api/browser/ipc-browser.md index 2edaa29463ae..534a7a2a075c 100644 --- a/docs/api/browser/ipc-browser.md +++ b/docs/api/browser/ipc-browser.md @@ -1,52 +1,45 @@ # ipc (browser) -The `ipc` module allows developers to send asynchronous messages to renderers. -To avoid possible dead-locks, it's not allowed to send synchronous messages in -browser. +Handles asynchronous and synchronous message sent from web page. -## Event: 'message' +The messages sent from web page would be emitted to this module, the event name +is the `channel` when sending message. To reply a synchronous message, you need +to set `event.returnValue`, to send an asynchronous back to the sender, you can +use `event.sender.send(...)`. -* `processId` Integer -* `routingId` Integer - -Emitted when renderer sent a message to the browser. - -## Event: 'sync-message' - -* `event` Object -* `processId` Integer -* `routingId` Integer - -Emitted when renderer sent a synchronous message to the browser. The receiver -should store the result in `event.returnValue`. - -**Note:** Due to the limitation of `EventEmitter`, returning value in the -event handler has no effect, so we have to store the result by using the -`event` parameter. - -## ipc.send(processId, routingId, [args...]) - -* `processId` Integer -* `routingId` Integer - -Send `args...` to the renderer specified by `processId` and `routingId` and -return immediately, the renderer should handle the message by listening to the -`message` event. - -## ipc.sendChannel(processId, routingId, channel, [args...]) - -* `processId` Integer -* `routingId` Integer -* `channel` String - -This is the same with ipc.send, except that the renderer should listen to the -`channel` event. The ipc.send(processId, routingId, args...) can be seen as -ipc.sendChannel(processId, routingId, 'message', args...). - -**Note:** If the the first argument (e.g. `processId`) is a `BrowserWindow`, -`ipc.sendChannel` would automatically get the `processId` and `routingId` -from it, so you can send a message to window like this: +An example of sending and handling messages: ```javascript -ipc.sendChannel(browserWindow, 'message', ...); +// In browser. +var ipc = require('ipc'); +ipc.on('asynchronous-message', function(event, arg) { + console.log(arg); // prints "ping" + event.sender.send('asynchronous-reply', 'pong'); +}); + +ipc.on('synchronous-message', function(event, arg) { + console.log(arg); // prints "ping" + event.returnValue = 'pong'. +}); ``` + +```javascript +// In web page. +var ipc = require('ipc'); +console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong" + +ipc.on('asynchronous-reply', function(arg) { + console.log(arg); // prints "pong" +}); +ipc.send('asynchronous-message', 'ping'); +``` + +### Class: Event + +## Event.returnValue + +Assign to this to return an value to synchronous messages. + +## Event.sender + +The `WebContents` of the web page that has sent the message. diff --git a/docs/api/renderer/ipc-renderer.md b/docs/api/renderer/ipc-renderer.md index 4076b93b395e..5c101269d45e 100644 --- a/docs/api/renderer/ipc-renderer.md +++ b/docs/api/renderer/ipc-renderer.md @@ -5,75 +5,18 @@ asynchronous messages to the browser, and also receive messages sent from browser. If you want to make use of modules of browser from renderer, you might consider using the [remote](remote.md) module. -An example of echoing messages between browser and renderer: +See [ipc (browser)](../browser/ipc-browser.md) for examples. -```javascript -// In browser: -var ipc = require('ipc'); -ipc.on('message', function(processId, routingId, m) { - ipc.send(processId, routingId, m); -}); -``` +## ipc.send(channel[, args...]) -```javascript -// In renderer: -var ipc = require('ipc'); -ipc.on('message', function(m) { - console.log('Received message', m); -}); -ipc.send('Hello world'); -``` +Send `args..` to the web page via `channel` in asynchronous message, the browser +process can handle it by listening to the `channel` event of `ipc` module. -An example of sending synchronous message from renderer to browser: +## ipc.sendSync(channel[, args...]) -```javascript -// In browser: -var ipc = require('ipc'); -ipc.on('browser-data-request', function(event, processId, routingId, message) { - event.returnValue = 'THIS SOME DATA FROM THE BROWSER'; -}); -``` - -```javascript -// In renderer: -var ipc = require('ipc'); -console.log(ipc.sendChannelSync('browser-data-request', 'THIS IS FROM THE RENDERER')); -``` - -## Event: 'message' - -Emitted when browser sent a message to this window. - -## ipc.send([args...]) - -Send all arguments to the browser and return immediately, the browser should -handle the message by listening to the `message` event. - -## ipc.sendSync([args...]) - -Send all arguments to the browser synchronously, and returns the result sent -from browser. The browser should handle the message by listening to the -`sync-message` event. +Send `args..` to the web page via `channel` in synchronous message, and returns +the result sent from browser. The browser process can handle it by listening to +the `channel` event of `ipc` module, and returns by setting `event.returnValue`. **Note:** Usually developers should never use this API, since sending -synchronous message would block the browser. - -## ipc.sendChannel(channel, [args...]) - -* `channel` String - -This is the same with `ipc.send`, except that the browser should listen to the -`channel` event. The `ipc.send(args...)` can be seen as -`ipc.sendChannel('message', args...)`. - - -## ipc.sendChannelSync(channel, [args...]) - -* `channel` String - -This is the same with `ipc.sendSync`, except that the browser should listen to -the `channel` event. The `ipc.sendSync(args...)` can be seen as -`ipc.sendChannelSync('sync-message', args...)`. - -**Note:** Usually developers should never use this API, since sending -synchronous message would block the browser. +synchronous message would block the whole web page.