diff --git a/atom.gyp b/atom.gyp index a56ae6139a4c..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', @@ -48,7 +49,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', @@ -62,10 +62,10 @@ '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', - 'atom/browser/api/atom_browser_bindings.h', 'atom/browser/api/event.cc', 'atom/browser/api/event.h', 'atom/browser/api/event_emitter.cc', @@ -93,8 +93,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 new file mode 100644 index 000000000000..8195a336c260 --- /dev/null +++ b/atom/browser/api/atom_api_web_contents.cc @@ -0,0 +1,206 @@ +// 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 "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 "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" +#include "native_mate/object_template_builder.h" + +namespace atom { + +namespace api { + +WebContents::WebContents(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + web_contents_(web_contents) { +} + +void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) { + base::ListValue args; + args.AppendInteger(render_view_host->GetProcess()->GetID()); + args.AppendInteger(render_view_host->GetRoutingID()); + Emit("render-view-deleted", args); +} + +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"); +} + +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()); + Emit("destroyed"); +} + +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(); +} + +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(); +} + +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(); +} + +int WebContents::GetProcessID() const { + return web_contents()->GetRenderProcessHost()->GetID(); +} + +bool WebContents::IsCrashed() const { + return web_contents()->IsCrashed(); +} + +void WebContents::ExecuteJavaScript(const string16& code) { + 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) + .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) + .SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript) + .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 +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..fb4c6082e7ee --- /dev/null +++ b/atom/browser/api/atom_api_web_contents.h @@ -0,0 +1,84 @@ +// 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 "content/public/browser/web_contents_observer.h" +#include "native_mate/handle.h" + +namespace atom { + +namespace api { + +class WebContents : public mate::EventEmitter, + public content::WebContentsObserver { + public: + static mate::Handle Create(v8::Isolate* isolate, + 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; + void ExecuteJavaScript(const string16& code); + bool SendIPCMessage(const string16& channel, const base::ListValue& args); + + protected: + explicit WebContents(content::WebContents* web_contents); + + // mate::Wrappable implementations: + virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) OVERRIDE; + + // 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 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); +}; + +} // 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..dae2abb93ebf 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -4,15 +4,12 @@ #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" -#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" @@ -22,8 +19,6 @@ #include "atom/common/node_includes.h" -using content::NavigationController; - namespace mate { template<> @@ -86,12 +81,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"); } @@ -114,17 +103,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) { @@ -326,96 +304,13 @@ void Window::CapturePage(mate::Arguments* args) { window_->CapturePage(rect, base::Bind(&OnCapturePageDone, callback)); } -string16 Window::GetPageTitle() { - return window_->GetWebContents()->GetTitle(); +mate::Handle Window::GetWebContents(v8::Isolate* isolate) const { + return WebContents::Create(isolate, window_->GetWebContents()); } -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(); - 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(); - - content::NavigationController::LoadURLParams params(url); - params.transition_type = content::PAGE_TRANSITION_TYPED; - params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; - 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(); -} - -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); +mate::Handle Window::GetDevToolsWebContents( + v8::Isolate* isolate) const { + return WebContents::Create(isolate, window_->GetDevToolsWebContents()); } // static @@ -462,27 +357,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("blurWebView", &Window::BlurWebView) .SetMethod("isWebViewFocused", &Window::IsWebViewFocused) .SetMethod("capturePage", &Window::CapturePage) - .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) - .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("_getWebContents", &Window::GetWebContents) + .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 d9663231a9e0..4d762bee90b3 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: @@ -47,14 +50,11 @@ 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; 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. @@ -100,30 +100,8 @@ class Window : public mate::EventEmitter, void CapturePage(mate::Arguments* args); // APIs for WebContents. - string16 GetPageTitle(); - bool IsLoading(); - bool IsWaitingForResponse(); - void Stop(); - int GetRoutingID(); - int GetProcessID(); - bool IsCrashed(); - - // APIs for devtools. - mate::Dictionary GetDevTools(v8::Isolate* isolate); - void ExecuteJavaScriptInDevTools(const std::string& code); - - // APIs for NavigationController. - void LoadURL(const GURL& url); - GURL GetURL(); - bool CanGoBack(); - bool CanGoForward(); - bool CanGoToOffset(int offset); - void GoBack(); - void GoForward(); - void GoToIndex(int index); - void GoToOffset(int offset); - void Reload(); - void ReloadIgnoringCache(); + mate::Handle GetWebContents(v8::Isolate* isolate) const; + mate::Handle GetDevToolsWebContents(v8::Isolate* isolate) const; scoped_ptr window_; 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 18dacbf2e6e7..9a1f26a58506 100644 --- a/atom/browser/api/lib/browser-window.coffee +++ b/atom/browser/api/lib/browser-window.coffee @@ -1,6 +1,7 @@ EventEmitter = require('events').EventEmitter IDWeakMap = require 'id-weak-map' app = require 'app' +wrapWebContents = require('web-contents').wrap BrowserWindow = process.atomBinding('window').BrowserWindow BrowserWindow::__proto__ = EventEmitter.prototype @@ -14,6 +15,20 @@ BrowserWindow::_init = -> menu = app.getApplicationMenu() @setMenu menu if menu? + @webContents = @getWebContents() + @webContents.once 'destroyed', => @webContents = null + + # Define getter for devToolsWebContents. + devToolsWebContents = null + @__defineGetter__ 'devToolsWebContents', -> + if @isDevToolsOpened() + # 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() + else + devToolsWebContents = null + # Remember the window. id = BrowserWindow.windows.add this @@ -24,12 +39,18 @@ 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) -> - process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', 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 = -> + wrapWebContents @_getWebContents() + +BrowserWindow::getDevToolsWebContents = -> + wrapWebContents @_getDevToolsWebContents() + BrowserWindow::restart = -> @loadUrl(@getUrl()) @@ -50,16 +71,30 @@ 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 +BrowserWindow::send = -> @webContents.send.apply @webContents, arguments + +# Be compatible with old API. +BrowserWindow::getUrl = -> @webContents.getUrl() +BrowserWindow::reload = -> @webContents.reload() +BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache() +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() +BrowserWindow::executeJavaScriptInDevTools = (code) -> + @devToolsWebContents.executeJavaScript code module.exports = BrowserWindow 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/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee new file mode 100644 index 000000000000..5e7212334764 --- /dev/null +++ b/atom/browser/api/lib/web-contents.coffee @@ -0,0 +1,27 @@ +EventEmitter = require('events').EventEmitter +ipc = require 'ipc' + +module.exports.wrap = (webContents) -> + return null unless webContents.isAlive() + + # webContents is an EventEmitter. + webContents.__proto__ = EventEmitter.prototype + + # 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 + 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 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/objects-registry.coffee b/atom/browser/lib/objects-registry.coffee index 1bae8f6e4e50..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 "release-renderer-view-#{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 e10f875328e3..a28c4b25af3f 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,14 +15,14 @@ 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. - [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 @@ -37,12 +37,12 @@ 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) -> 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 @@ -53,15 +53,15 @@ unwrapArgs = (processId, routingId, args) -> -> returnValue when 'function' rendererReleased = false - objectsRegistry.once "release-renderer-view-#{processId}-#{routingId}", -> + objectsRegistry.once "clear-#{sender.getId()}", -> rendererReleased = true 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 +69,78 @@ 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 +process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> + objectsRegistry.clear id -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' - window = BrowserWindow.fromProcessIdAndRoutingId processId, routingId - window = BrowserWindow.fromDevTools processId, routingId unless window? - event.returnValue = valueToMeta processId, routingId, 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 -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 +148,12 @@ 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) -> - objectsRegistry.remove processId, routingId, storeId +ipc.on 'ATOM_BROWSER_DEREFERENCE', (event, storeId) -> + objectsRegistry.remove event.sender.getId(), storeId diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index e4627d2ec2eb..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. @@ -229,11 +222,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(); } @@ -305,14 +293,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(); } @@ -437,13 +417,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()); @@ -482,16 +455,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. @@ -500,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) @@ -628,28 +588,8 @@ void NativeWindow::CallDevToolsFunction(const std::string& function_name, } } } - ExecuteJavaScriptInDevTools(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); + GetDevToolsWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame( + string16(), base::UTF8ToUTF16(function_name + "(" + params + ");")); } } // namespace atom diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index f10e509e4e92..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, @@ -136,7 +135,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(); @@ -220,7 +218,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; @@ -230,8 +227,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; @@ -274,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_; @@ -305,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/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 5d697480050f..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) {} @@ -34,12 +31,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 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/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. 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. 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()', -> 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; });