From de418901968667355a87c45dfef74d74e87ccdcc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 21:56:56 +0800 Subject: [PATCH 1/4] Inherit parent window's options in window.open --- atom/browser/api/atom_api_web_contents.cc | 11 +++++++++-- atom/browser/api/atom_api_web_contents.h | 3 +++ atom/browser/api/atom_api_window.cc | 4 ++++ atom/browser/lib/guest-window-manager.coffee | 13 ++++++++++++- atom/browser/web_contents_preferences.cc | 3 +++ atom/browser/web_contents_preferences.h | 3 +++ 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 79f359ae8d7..bdeb4ed4f87 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -228,7 +228,7 @@ WebContents::WebContents(v8::Isolate* isolate, AttachAsUserData(web_contents); InitWithWebContents(web_contents); - // Save the preferences. + // Save the preferences in C++. base::DictionaryValue web_preferences; mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences); new WebContentsPreferences(web_contents, &web_preferences); @@ -887,6 +887,12 @@ bool WebContents::IsGuest() const { return type_ == WEB_VIEW; } +v8::Local WebContents::GetWebPreferences(v8::Isolate* isolate) { + WebContentsPreferences* web_preferences = + WebContentsPreferences::FromWebContents(web_contents()); + return mate::ConvertToV8(isolate, *web_preferences->web_preferences()); +} + mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( v8::Isolate* isolate) { if (template_.IsEmpty()) @@ -942,6 +948,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("setSize", &WebContents::SetSize) .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("isGuest", &WebContents::IsGuest) + .SetMethod("getWebPreferences", &WebContents::GetWebPreferences) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) .SetMethod("unregisterServiceWorker", &WebContents::UnregisterServiceWorker) @@ -995,7 +1002,7 @@ mate::Handle WebContents::CreateFrom( // static mate::Handle WebContents::Create( v8::Isolate* isolate, const mate::Dictionary& options) { - auto handle = mate::CreateHandle(isolate, new WebContents(isolate, options)); + auto handle = mate::CreateHandle(isolate, new WebContents(isolate, options)); g_wrap_web_contents.Run(handle.ToV8()); return handle; } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index c8ea6908bc5..91750ac6136 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -132,6 +132,9 @@ class WebContents : public mate::TrackableObject, void SetAllowTransparency(bool allow); bool IsGuest() const; + // Returns the web preferences of current WebContents. + v8::Local GetWebPreferences(v8::Isolate* isolate); + protected: explicit WebContents(content::WebContents* web_contents); WebContents(v8::Isolate* isolate, const mate::Dictionary& options); diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 3a44115da26..4d866d18503 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -82,6 +82,10 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) { web_contents_.Reset(isolate, web_contents.ToV8()); api_web_contents_ = web_contents.get(); + // Keep a copy of the options for later use. + mate::Dictionary(isolate, web_contents->GetWrapper(isolate)).Set( + "browserWindowOptions", options); + // Creates BrowserWindow. window_.reset(NativeWindow::Create(web_contents->managed_web_contents(), options)); diff --git a/atom/browser/lib/guest-window-manager.coffee b/atom/browser/lib/guest-window-manager.coffee index add366eca81..2dc5056a57e 100644 --- a/atom/browser/lib/guest-window-manager.coffee +++ b/atom/browser/lib/guest-window-manager.coffee @@ -4,6 +4,17 @@ BrowserWindow = require 'browser-window' frameToGuest = {} +# Merge |options| with the |embedder|'s window's options. +mergeBrowserWindowOptions = (embedder, options) -> + if embedder.browserWindowOptions? + # Inherit the original options if it is a BrowserWindow. + options.__proto__ = embedder.browserWindowOptions + else + # Or only inherit web-preferences if it is a webview. + options['web-preferences'] ?= {} + options['web-preferences'].__proto__ = embedder.getWebPreferences() + options + # Create a new guest created by |embedder| with |options|. createGuest = (embedder, url, frameName, options) -> guest = frameToGuest[frameName] @@ -11,7 +22,7 @@ createGuest = (embedder, url, frameName, options) -> guest.loadUrl url return guest.id - guest = new BrowserWindow(options) + guest = new BrowserWindow(mergeBrowserWindowOptions(embedder, options)) guest.loadUrl url # Remember the embedder, will be used by window.opener methods. diff --git a/atom/browser/web_contents_preferences.cc b/atom/browser/web_contents_preferences.cc index d34b67d7850..2856598c0bc 100644 --- a/atom/browser/web_contents_preferences.cc +++ b/atom/browser/web_contents_preferences.cc @@ -40,6 +40,9 @@ WebContentsPreferences::WebContentsPreferences( base::DictionaryValue* web_preferences) { web_preferences_.Swap(web_preferences); web_contents->SetUserData(UserDataKey(), this); + + // The "isGuest" is not a preferences field. + web_preferences_.Remove("isGuest", nullptr); } WebContentsPreferences::~WebContentsPreferences() { diff --git a/atom/browser/web_contents_preferences.h b/atom/browser/web_contents_preferences.h index 83b485f449b..3e36df02147 100644 --- a/atom/browser/web_contents_preferences.h +++ b/atom/browser/web_contents_preferences.h @@ -37,6 +37,9 @@ class WebContentsPreferences // $.extend(|web_preferences_|, |new_web_preferences|). void Merge(const base::DictionaryValue& new_web_preferences); + // Returns the web preferences. + base::DictionaryValue* web_preferences() { return &web_preferences_; } + private: friend class content::WebContentsUserData; From 4521db459b7fa8bdb4ffe3d4728cb615b337d59e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 22:36:46 +0800 Subject: [PATCH 2/4] spec: window.open should inherit options of parent window --- spec/chromium-spec.coffee | 10 ++++++++++ spec/fixtures/pages/window-open-size.html | 8 ++++++++ 2 files changed, 18 insertions(+) create mode 100644 spec/fixtures/pages/window-open-size.html diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index bb5cc47d658..2c2695aa5e6 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -50,6 +50,16 @@ describe 'chromium feature', -> window.addEventListener 'message', listener b = window.open "file://#{fixtures}/pages/window-opener-node.html", '', 'node-integration=no,show=no' + it 'inherit options of parent window', (done) -> + listener = (event) -> + window.removeEventListener 'message', listener + b.close() + size = remote.getCurrentWindow().getSize() + assert.equal event.data, "size: #{size.width} #{size.height}" + done() + window.addEventListener 'message', listener + b = window.open "file://#{fixtures}/pages/window-open-size.html", '', 'show=no' + describe 'window.opener', -> @timeout 10000 diff --git a/spec/fixtures/pages/window-open-size.html b/spec/fixtures/pages/window-open-size.html new file mode 100644 index 00000000000..7b06cfddf55 --- /dev/null +++ b/spec/fixtures/pages/window-open-size.html @@ -0,0 +1,8 @@ + + + + + From e499bb14de05cf2de8c19c56a742da0096b6b36c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 22:46:44 +0800 Subject: [PATCH 3/4] docs: Mention window.open inherits options --- docs/api/window-open.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index c574d5d036e..5d298e61e75 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -8,6 +8,10 @@ The proxy has limited standard functionality implemented to be compatible with traditional web pages. For full control of the new window you should create a `BrowserWindow` directly. +The newly created `BrowserWindow` will inherit parent window's options by +default, to override inherited options you can set them in the `features` +string. + ### `window.open(url[, frameName][, features])` * `url` String @@ -16,6 +20,9 @@ you should create a `BrowserWindow` directly. Creates a new window and returns an instance of `BrowserWindowProxy` class. +The `features` string follows the format of standard browser, but each feature +has to be a field of `BrowserWindow`'s options. + ### `window.opener.postMessage(message, targetOrigin)` * `message` String From 486f16fffa0956b95135044524a822034440d17e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 22 Sep 2015 22:48:52 +0800 Subject: [PATCH 4/4] spec: Increase timeout for window.open specs --- spec/chromium-spec.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index 2c2695aa5e6..4dd39aff5fd 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -35,6 +35,8 @@ describe 'chromium feature', -> assert.notEqual navigator.language, '' describe 'window.open', -> + @timeout 10000 + it 'returns a BrowserWindowProxy object', -> b = window.open 'about:blank', '', 'show=no' assert.equal b.closed, false