From 66a0abe79934c0bfcc23d37e46c1c2047e513f8b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 22 Apr 2013 21:32:48 +0800 Subject: [PATCH] Renderer can now use process.send to send messages to browser. --- browser/api/atom_browser_bindings.cc | 7 +++ browser/api/atom_browser_bindings.h | 7 +++ browser/atom_browser_context.cc | 12 +--- browser/atom_browser_context.h | 3 - browser/atom_browser_main_parts.cc | 12 ++++ browser/atom_browser_main_parts.h | 6 ++ browser/native_window.cc | 24 +++++-- browser/native_window.h | 3 + common/api/api_messages.h | 21 ++----- common/api/atom_bindings.h | 4 -- renderer/api/atom_renderer_bindings.cc | 86 ++++++++++++++++++++++++-- renderer/api/atom_renderer_bindings.h | 17 ++++- renderer/atom_render_view_observer.cc | 4 +- renderer/atom_render_view_observer.h | 6 ++ renderer/atom_renderer_client.cc | 4 +- renderer/atom_renderer_client.h | 3 - vendor/brightray | 2 +- 17 files changed, 167 insertions(+), 54 deletions(-) diff --git a/browser/api/atom_browser_bindings.cc b/browser/api/atom_browser_bindings.cc index bc4d3b337345..c23a1f92f1f1 100644 --- a/browser/api/atom_browser_bindings.cc +++ b/browser/api/atom_browser_bindings.cc @@ -5,6 +5,7 @@ #include "browser/api/atom_browser_bindings.h" #include "base/logging.h" +#include "base/values.h" #include "content/public/browser/browser_thread.h" #include "vendor/node/src/node.h" #include "vendor/node/src/node_internals.h" @@ -35,4 +36,10 @@ void AtomBrowserBindings::AfterLoad() { DCHECK(!browser_main_parts_.IsEmpty()); } +void AtomBrowserBindings::OnRendererMessage( + int routing_id, const base::ListValue& args) { + LOG(ERROR) << "OnRendererMessage routing_id:" << routing_id + << " args:" << args; +} + } // namespace atom diff --git a/browser/api/atom_browser_bindings.h b/browser/api/atom_browser_bindings.h index f67fcf0b5020..aa2831ee9937 100644 --- a/browser/api/atom_browser_bindings.h +++ b/browser/api/atom_browser_bindings.h @@ -7,6 +7,10 @@ #include "common/api/atom_bindings.h" +namespace base { +class ListValue; +} + namespace atom { class AtomBrowserBindings : public AtomBindings { @@ -17,6 +21,9 @@ class AtomBrowserBindings : public AtomBindings { // Called when the node.js main script has been loaded. virtual void AfterLoad(); + // Called when received a message from renderer. + void OnRendererMessage(int routing_id, const base::ListValue& args); + // The require('atom').browserMainParts object. v8::Handle browser_main_parts() { return browser_main_parts_; diff --git a/browser/atom_browser_context.cc b/browser/atom_browser_context.cc index 0d43f9ba930a..78cada008866 100644 --- a/browser/atom_browser_context.cc +++ b/browser/atom_browser_context.cc @@ -5,17 +5,12 @@ #include "browser/atom_browser_context.h" #include "browser/api/atom_api_objects_registry.h" +#include "browser/atom_browser_main_parts.h" namespace atom { -// static -AtomBrowserContext* AtomBrowserContext::self_; - AtomBrowserContext::AtomBrowserContext() : objects_registry_(new api::ObjectsRegistry) { - DCHECK(!self_); - - self_ = this; } AtomBrowserContext::~AtomBrowserContext() { @@ -23,9 +18,8 @@ AtomBrowserContext::~AtomBrowserContext() { // static AtomBrowserContext* AtomBrowserContext::Get() { - DCHECK(self_); - - return self_; + return static_cast( + AtomBrowserMainParts::Get()->browser_context()); } } // namespace atom diff --git a/browser/atom_browser_context.h b/browser/atom_browser_context.h index da60cfa39a14..397bd92c6986 100644 --- a/browser/atom_browser_context.h +++ b/browser/atom_browser_context.h @@ -19,7 +19,6 @@ class AtomBrowserContext : public brightray::BrowserContext { AtomBrowserContext(); virtual ~AtomBrowserContext(); - // We assume there is only one BrowserContext per browser process. static AtomBrowserContext* Get(); api::ObjectsRegistry* objects_registry() const { @@ -27,8 +26,6 @@ class AtomBrowserContext : public brightray::BrowserContext { } private: - static AtomBrowserContext* self_; - scoped_ptr objects_registry_; DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); diff --git a/browser/atom_browser_main_parts.cc b/browser/atom_browser_main_parts.cc index c5ac02a5784b..fadf32aaa5c4 100644 --- a/browser/atom_browser_main_parts.cc +++ b/browser/atom_browser_main_parts.cc @@ -5,6 +5,7 @@ #include "browser/atom_browser_main_parts.h" #include "browser/api/atom_browser_bindings.h" +#include "browser/atom_browser_client.h" #include "browser/atom_browser_context.h" #include "browser/native_window.h" #include "common/node_bindings.h" @@ -13,14 +14,25 @@ namespace atom { +// static +AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL; + AtomBrowserMainParts::AtomBrowserMainParts() : atom_bindings_(new AtomBrowserBindings), node_bindings_(NodeBindings::Create(true)) { + DCHECK(!self_) << "Cannot have two AtomBrowserMainParts"; + self_ = this; } AtomBrowserMainParts::~AtomBrowserMainParts() { } +// static +AtomBrowserMainParts* AtomBrowserMainParts::Get() { + DCHECK(self_); + return self_; +} + brightray::BrowserContext* AtomBrowserMainParts::CreateBrowserContext() { return new AtomBrowserContext(); } diff --git a/browser/atom_browser_main_parts.h b/browser/atom_browser_main_parts.h index c1dd0c8e43bc..eaecd096f6b0 100644 --- a/browser/atom_browser_main_parts.h +++ b/browser/atom_browser_main_parts.h @@ -17,6 +17,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { AtomBrowserMainParts(); virtual ~AtomBrowserMainParts(); + static AtomBrowserMainParts* Get(); + + AtomBrowserBindings* atom_bindings() { return atom_bindings_.get(); } + protected: // Implementations of brightray::BrowserMainParts. virtual brightray::BrowserContext* CreateBrowserContext() OVERRIDE; @@ -30,6 +34,8 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { scoped_ptr atom_bindings_; scoped_ptr node_bindings_; + static AtomBrowserMainParts* self_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserMainParts); }; diff --git a/browser/native_window.cc b/browser/native_window.cc index 3e301eee9b0b..be29cdbe6a89 100644 --- a/browser/native_window.cc +++ b/browser/native_window.cc @@ -8,15 +8,18 @@ #include "base/utf_string_conversions.h" #include "base/values.h" -#include "brightray/browser/browser_context.h" #include "brightray/browser/inspectable_web_contents.h" #include "brightray/browser/inspectable_web_contents_view.h" +#include "browser/api/atom_browser_bindings.h" #include "browser/atom_browser_context.h" +#include "browser/atom_browser_main_parts.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" +#include "common/api/api_messages.h" #include "common/options_switches.h" +#include "ipc/ipc_message_macros.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" @@ -27,13 +30,11 @@ namespace atom { NativeWindow::NativeWindow(content::WebContents* web_contents, base::DictionaryValue* options) - : inspectable_web_contents_( + : content::WebContentsObserver(web_contents), + inspectable_web_contents_( brightray::InspectableWebContents::Create(web_contents)) { web_contents->SetDelegate(this); - // Add window as an observer of the web contents. - content::WebContentsObserver::Observe(web_contents); - // Get notified of title updated message. registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, content::Source(web_contents)); @@ -129,7 +130,13 @@ void NativeWindow::WebContentsCreated( } bool NativeWindow::OnMessageReceived(const IPC::Message& message) { - return false; + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(NativeWindow, message) + IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; } void NativeWindow::Observe(int type, @@ -152,4 +159,9 @@ void NativeWindow::Observe(int type, } } +void NativeWindow::OnRendererMessage(const base::ListValue& args) { + AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage( + GetWebContents()->GetRoutingID(), args); +} + } // namespace atom diff --git a/browser/native_window.h b/browser/native_window.h index ad46d142f59c..b65ff17f6d75 100644 --- a/browser/native_window.h +++ b/browser/native_window.h @@ -19,6 +19,7 @@ namespace base { class DictionaryValue; +class ListValue; } namespace brightray { @@ -119,6 +120,8 @@ class NativeWindow : public content::WebContentsDelegate, const content::NotificationDetails& details) OVERRIDE; private: + void OnRendererMessage(const base::ListValue& args); + // Notification manager. content::NotificationRegistrar registrar_; diff --git a/common/api/api_messages.h b/common/api/api_messages.h index f10ff54f81df..8a3083a862f2 100644 --- a/common/api/api_messages.h +++ b/common/api/api_messages.h @@ -15,21 +15,8 @@ #define IPC_MESSAGE_START ShellMsgStart -IPC_SYNC_MESSAGE_CONTROL2_1(AtomViewHostMsg_Allocate_Object, - std::string /* module */, - DictionaryValue /* options */, - int /* object id */) +IPC_MESSAGE_ROUTED1(AtomViewHostMsg_Message, + ListValue /* arguments */) -IPC_SYNC_MESSAGE_CONTROL1_0(AtomViewHostMsg_Deallocate_Object, - int /* object id */) - -IPC_SYNC_MESSAGE_CONTROL3_1(AtomViewHostMsg_Call_Object_Method, - int /* object id */, - std::string /* method name */, - ListValue /* arguments */, - DictionaryValue /* return value */) - -IPC_SYNC_MESSAGE_CONTROL2_1(AtomViewMsg_Callback, - int /* callback id */, - ListValue /* arguments */, - DictionaryValue /* return value */) +IPC_MESSAGE_ROUTED1(AtomViewMsg_Message, + ListValue /* arguments */) diff --git a/common/api/atom_bindings.h b/common/api/atom_bindings.h index fac8c2f79524..88eb8e08c340 100644 --- a/common/api/atom_bindings.h +++ b/common/api/atom_bindings.h @@ -8,10 +8,6 @@ #include "base/basictypes.h" #include "v8/include/v8.h" -namespace WebKit { -class WebFrame; -} - namespace atom { class AtomBindings { diff --git a/renderer/api/atom_renderer_bindings.cc b/renderer/api/atom_renderer_bindings.cc index 3b2a600c204b..15276dd3aaf4 100644 --- a/renderer/api/atom_renderer_bindings.cc +++ b/renderer/api/atom_renderer_bindings.cc @@ -5,17 +5,56 @@ #include "renderer/api/atom_renderer_bindings.h" #include "base/logging.h" +#include "base/values.h" +#include "common/api/api_messages.h" +#include "content/public/renderer/render_view.h" +#include "content/public/renderer/v8_value_converter.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "vendor/node/src/node.h" + +using content::RenderView; +using content::V8ValueConverter; +using WebKit::WebFrame; +using WebKit::WebView; namespace atom { -AtomRendererBindings::AtomRendererBindings() { +namespace { + +v8::Handle GetProcessObject(v8::Handle context) { + v8::Handle process = + context->Global()->Get(v8::String::New("process"))->ToObject(); + DCHECK(!process.IsEmpty()); + + return process; +} + +RenderView* GetCurrentRenderView() { + WebFrame* frame = WebFrame::frameForCurrentContext(); + DCHECK(frame); + if (!frame) + return NULL; + + WebView* view = frame->view(); + if (!view) + return NULL; // can happen during closing. + + RenderView* render_view = RenderView::FromWebView(view); + DCHECK(render_view); + return render_view; +} + +} // namespace + +AtomRendererBindings::AtomRendererBindings(RenderView* render_view) + : render_view_(render_view) { } AtomRendererBindings::~AtomRendererBindings() { } -void AtomRendererBindings::BindToFrame(WebKit::WebFrame* frame) { +void AtomRendererBindings::BindToFrame(WebFrame* frame) { v8::HandleScope handle_scope; v8::Handle context = frame->mainWorldScriptContext(); @@ -24,11 +63,46 @@ void AtomRendererBindings::BindToFrame(WebKit::WebFrame* frame) { v8::Context::Scope scope(context); - v8::Handle process = - context->Global()->Get(v8::String::New("process"))->ToObject(); - DCHECK(!process.IsEmpty()); + AtomBindings::BindTo(GetProcessObject(context)); +} - AtomBindings::BindTo(process); +void AtomRendererBindings::AddIPCBindings(WebFrame* frame) { + v8::HandleScope handle_scope; + + v8::Handle context = frame->mainWorldScriptContext(); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + + v8::Handle process = GetProcessObject(context); + + node::SetMethod(process, "send", Send); +} + +// static +v8::Handle AtomRendererBindings::Send(const v8::Arguments &args) { + v8::HandleScope scope; + + RenderView* render_view = GetCurrentRenderView(); + + // Convert Arguments to Array, so we can use V8ValueConverter to convert it + // to ListValue. + v8::Local v8_args = v8::Array::New(args.Length()); + for (int i = 0; i < args.Length(); ++i) + v8_args->Set(i, args[i]); + + scoped_ptr converter(V8ValueConverter::create()); + scoped_ptr arguments( + converter->FromV8Value(v8_args, v8::Context::GetCurrent())); + + DCHECK(arguments && arguments->IsType(base::Value::TYPE_LIST)); + + render_view->Send(new AtomViewHostMsg_Message( + render_view->GetRoutingID(), + *static_cast(arguments.get()))); + + return v8::Undefined(); } } // namespace atom diff --git a/renderer/api/atom_renderer_bindings.h b/renderer/api/atom_renderer_bindings.h index 1c18d039132c..4be2a642029b 100644 --- a/renderer/api/atom_renderer_bindings.h +++ b/renderer/api/atom_renderer_bindings.h @@ -7,17 +7,32 @@ #include "common/api/atom_bindings.h" +namespace content { +class RenderView; +} + +namespace WebKit { +class WebFrame; +} + namespace atom { class AtomRendererBindings : public AtomBindings { public: - AtomRendererBindings(); + explicit AtomRendererBindings(content::RenderView* render_view); virtual ~AtomRendererBindings(); // Call BindTo for process object of the frame. void BindToFrame(WebKit::WebFrame* frame); + // Add process.send and make process.on accept IPC message. + void AddIPCBindings(WebKit::WebFrame* frame); + private: + static v8::Handle Send(const v8::Arguments &args); + + content::RenderView* render_view_; + DISALLOW_COPY_AND_ASSIGN(AtomRendererBindings); }; diff --git a/renderer/atom_render_view_observer.cc b/renderer/atom_render_view_observer.cc index e9e5fbe1cc17..cd025050aa98 100644 --- a/renderer/atom_render_view_observer.cc +++ b/renderer/atom_render_view_observer.cc @@ -54,6 +54,7 @@ AtomRenderViewObserver::AtomRenderViewObserver( content::RenderView* render_view, AtomRendererClient* renderer_client) : content::RenderViewObserver(render_view), + atom_bindings_(new AtomRendererBindings(render_view)), renderer_client_(renderer_client) { // Interact with dirty workarounds of extra node context in WebKit. webkit_atom::SetEnterFirstWindowContext(EnterFirstWindowContext); @@ -68,7 +69,8 @@ void AtomRenderViewObserver::DidClearWindowObject(WebFrame* frame) { web_frames().push_back(frame); renderer_client_->node_bindings()->BindTo(frame); - renderer_client_->atom_bindings()->BindToFrame(frame); + atom_bindings()->BindToFrame(frame); + atom_bindings()->AddIPCBindings(frame); } void AtomRenderViewObserver::FrameWillClose(WebFrame* frame) { diff --git a/renderer/atom_render_view_observer.h b/renderer/atom_render_view_observer.h index 650254fb6811..23c23eb9641c 100644 --- a/renderer/atom_render_view_observer.h +++ b/renderer/atom_render_view_observer.h @@ -5,10 +5,12 @@ #ifndef ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_ #define ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_ +#include "base/memory/scoped_ptr.h" #include "content/public/renderer/render_view_observer.h" namespace atom { +class AtomRendererBindings; class AtomRendererClient; class AtomRenderViewObserver : content::RenderViewObserver { @@ -16,6 +18,8 @@ class AtomRenderViewObserver : content::RenderViewObserver { explicit AtomRenderViewObserver(content::RenderView* render_view, AtomRendererClient* renderer_client); + AtomRendererBindings* atom_bindings() const { return atom_bindings_.get(); } + protected: virtual ~AtomRenderViewObserver(); @@ -23,6 +27,8 @@ class AtomRenderViewObserver : content::RenderViewObserver { virtual void FrameWillClose(WebKit::WebFrame*) OVERRIDE; private: + scoped_ptr atom_bindings_; + // Weak reference to renderer client. AtomRendererClient* renderer_client_; diff --git a/renderer/atom_renderer_client.cc b/renderer/atom_renderer_client.cc index 8e27865b79b0..142e6ff470bc 100644 --- a/renderer/atom_renderer_client.cc +++ b/renderer/atom_renderer_client.cc @@ -5,7 +5,6 @@ #include "renderer/atom_renderer_client.h" #include "common/node_bindings.h" -#include "renderer/api/atom_renderer_bindings.h" #include "renderer/atom_render_view_observer.h" #include "vendor/node/src/node_internals.h" @@ -16,8 +15,7 @@ extern void SetNodeContext(v8::Persistent context); namespace atom { AtomRendererClient::AtomRendererClient() - : atom_bindings_(new AtomRendererBindings), - node_bindings_(NodeBindings::Create(false)) { + : node_bindings_(NodeBindings::Create(false)) { } AtomRendererClient::~AtomRendererClient() { diff --git a/renderer/atom_renderer_client.h b/renderer/atom_renderer_client.h index 9ebd3753bbdd..46c79e75d645 100644 --- a/renderer/atom_renderer_client.h +++ b/renderer/atom_renderer_client.h @@ -9,7 +9,6 @@ namespace atom { -class AtomRendererBindings; class NodeBindings; class AtomRendererClient : public content::ContentRendererClient { @@ -17,14 +16,12 @@ class AtomRendererClient : public content::ContentRendererClient { AtomRendererClient(); virtual ~AtomRendererClient(); - AtomRendererBindings* atom_bindings() const { return atom_bindings_.get(); } NodeBindings* node_bindings() const { return node_bindings_.get(); } private: virtual void RenderThreadStarted() OVERRIDE; virtual void RenderViewCreated(content::RenderView*) OVERRIDE; - scoped_ptr atom_bindings_; scoped_ptr node_bindings_; DISALLOW_COPY_AND_ASSIGN(AtomRendererClient); diff --git a/vendor/brightray b/vendor/brightray index 5e5ac169db77..19be3702f2cd 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 5e5ac169db77ab49507ff474e54d73ab3e74ce38 +Subproject commit 19be3702f2cde6c677cae5352156b043842ecb01