From d34cff2eef8119b83c07a0899c1cf3a478e310da Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 23 Oct 2014 14:04:13 +0800 Subject: [PATCH] api: Add webContent.create() to create detached WebContents --- atom/browser/api/atom_api_web_contents.cc | 52 +++++++++++++++++++++-- atom/browser/api/atom_api_web_contents.h | 21 +++++++-- atom/browser/api/atom_api_window.cc | 4 +- atom/browser/api/lib/web-contents.coffee | 9 ++++ atom/common/node_bindings.cc | 1 + 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index c9db546fc09e..9978e92d6cf3 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -4,6 +4,7 @@ #include "atom/browser/api/atom_api_web_contents.h" +#include "atom/browser/atom_browser_context.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" @@ -13,8 +14,11 @@ #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/dictionary.h" #include "native_mate/object_template_builder.h" +#include "atom/common/node_includes.h" + namespace atom { namespace api { @@ -26,8 +30,20 @@ v8::Persistent template_; } // namespace WebContents::WebContents(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), - web_contents_(web_contents) { + : content::WebContentsObserver(web_contents) { +} + +WebContents::WebContents(const mate::Dictionary& options) { + content::WebContents::CreateParams params(AtomBrowserContext::Get()); + bool is_guest; + if (options.Get("isGuest", &is_guest) && is_guest) + params.guest_delegate = this; + + storage_.reset(content::WebContents::Create(params)); + Observe(storage_.get()); +} + +WebContents::~WebContents() { } void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) { @@ -75,10 +91,17 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) { void WebContents::WebContentsDestroyed() { // The RenderViewDeleted was not called when the WebContents is destroyed. - RenderViewDeleted(web_contents_->GetRenderViewHost()); + RenderViewDeleted(web_contents()->GetRenderViewHost()); Emit("destroyed"); } +void WebContents::Destroy() { + if (storage_) { + Observe(nullptr); + storage_.reset(); + } +} + bool WebContents::IsAlive() const { return web_contents() != NULL; } @@ -174,6 +197,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { if (template_.IsEmpty()) template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) + .SetMethod("destroy", &WebContents::Destroy) .SetMethod("isAlive", &WebContents::IsAlive) .SetMethod("loadUrl", &WebContents::LoadURL) .SetMethod("getUrl", &WebContents::GetURL) @@ -215,11 +239,31 @@ void WebContents::OnRendererMessageSync(const base::string16& channel, } // static -mate::Handle WebContents::Create( +mate::Handle WebContents::CreateFrom( v8::Isolate* isolate, content::WebContents* web_contents) { return mate::CreateHandle(isolate, new WebContents(web_contents)); } +// static +mate::Handle WebContents::Create( + v8::Isolate* isolate, const mate::Dictionary& options) { + return mate::CreateHandle(isolate, new WebContents(options)); +} + } // namespace api } // namespace atom + + +namespace { + +void Initialize(v8::Handle exports, v8::Handle unused, + v8::Handle context, void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + mate::Dictionary dict(isolate, exports); + dict.SetMethod("create", &atom::api::WebContents::Create); +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_contents, Initialize) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 145cd5aba9a8..4e119768960c 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -6,19 +6,31 @@ #define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_ #include "atom/browser/api/event_emitter.h" +#include "content/public/browser/browser_plugin_guest_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "native_mate/handle.h" +namespace mate { +class Dictionary; +} + namespace atom { namespace api { class WebContents : public mate::EventEmitter, + public content::BrowserPluginGuestDelegate, public content::WebContentsObserver { public: - static mate::Handle Create(v8::Isolate* isolate, - content::WebContents* web_contents); + // Create from an existing WebContents. + static mate::Handle CreateFrom( + v8::Isolate* isolate, content::WebContents* web_contents); + // Create a new WebContents. + static mate::Handle Create( + v8::Isolate* isolate, const mate::Dictionary& options); + + void Destroy(); bool IsAlive() const; void LoadURL(const GURL& url); GURL GetURL() const; @@ -44,6 +56,8 @@ class WebContents : public mate::EventEmitter, protected: explicit WebContents(content::WebContents* web_contents); + explicit WebContents(const mate::Dictionary& options); + ~WebContents(); // mate::Wrappable implementations: virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( @@ -71,7 +85,8 @@ class WebContents : public mate::EventEmitter, const base::ListValue& args, IPC::Message* message); - content::WebContents* web_contents_; // Weak. + // Stores the WebContents that managed by this class. + scoped_ptr storage_; DISALLOW_COPY_AND_ASSIGN(WebContents); }; diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 7bfffff1a5b4..55c4c584d33b 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -375,12 +375,12 @@ void Window::SetProgressBar(double progress) { } mate::Handle Window::GetWebContents(v8::Isolate* isolate) const { - return WebContents::Create(isolate, window_->GetWebContents()); + return WebContents::CreateFrom(isolate, window_->GetWebContents()); } mate::Handle Window::GetDevToolsWebContents( v8::Isolate* isolate) const { - return WebContents::Create(isolate, window_->GetDevToolsWebContents()); + return WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents()); } // static diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index 92e41cdbde1e..744cf51ab8c2 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -1,4 +1,5 @@ EventEmitter = require('events').EventEmitter +binding = process.atomBinding 'web_contents' ipc = require 'ipc' module.exports.wrap = (webContents) -> @@ -40,3 +41,11 @@ module.exports.wrap = (webContents) -> ipc.emit channel, event, args... webContents + +module.exports.create = (options={}) -> + webContents = @wrap binding.create(options) + + # Ensure the webContents is destroyed on exit. + process.on 'exit', -> webContents.destroy() + + webContents diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index a6f3659a2276..9dcba553bdef 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -68,6 +68,7 @@ REFERENCE_MODULE(atom_browser_power_monitor); REFERENCE_MODULE(atom_browser_protocol); REFERENCE_MODULE(atom_browser_global_shortcut); REFERENCE_MODULE(atom_browser_tray); +REFERENCE_MODULE(atom_browser_web_contents); REFERENCE_MODULE(atom_browser_window); REFERENCE_MODULE(atom_common_asar); REFERENCE_MODULE(atom_common_clipboard);