Merge pull request #2869 from atom/inherit-window-open

Inherit parent window's options in window.open
This commit is contained in:
Cheng Zhao 2015-09-22 23:15:01 +08:00
commit d0d71efb0b
9 changed files with 61 additions and 3 deletions

View file

@ -228,7 +228,7 @@ WebContents::WebContents(v8::Isolate* isolate,
AttachAsUserData(web_contents); AttachAsUserData(web_contents);
InitWithWebContents(web_contents); InitWithWebContents(web_contents);
// Save the preferences. // Save the preferences in C++.
base::DictionaryValue web_preferences; base::DictionaryValue web_preferences;
mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences); mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences);
new WebContentsPreferences(web_contents, &web_preferences); new WebContentsPreferences(web_contents, &web_preferences);
@ -887,6 +887,12 @@ bool WebContents::IsGuest() const {
return type_ == WEB_VIEW; return type_ == WEB_VIEW;
} }
v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
WebContentsPreferences* web_preferences =
WebContentsPreferences::FromWebContents(web_contents());
return mate::ConvertToV8(isolate, *web_preferences->web_preferences());
}
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
v8::Isolate* isolate) { v8::Isolate* isolate) {
if (template_.IsEmpty()) if (template_.IsEmpty())
@ -942,6 +948,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("setSize", &WebContents::SetSize) .SetMethod("setSize", &WebContents::SetSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::IsGuest) .SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
.SetMethod("unregisterServiceWorker", .SetMethod("unregisterServiceWorker",
&WebContents::UnregisterServiceWorker) &WebContents::UnregisterServiceWorker)

View file

@ -132,6 +132,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
void SetAllowTransparency(bool allow); void SetAllowTransparency(bool allow);
bool IsGuest() const; bool IsGuest() const;
// Returns the web preferences of current WebContents.
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
protected: protected:
explicit WebContents(content::WebContents* web_contents); explicit WebContents(content::WebContents* web_contents);
WebContents(v8::Isolate* isolate, const mate::Dictionary& options); WebContents(v8::Isolate* isolate, const mate::Dictionary& options);

View file

@ -82,6 +82,10 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
web_contents_.Reset(isolate, web_contents.ToV8()); web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get(); 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. // Creates BrowserWindow.
window_.reset(NativeWindow::Create(web_contents->managed_web_contents(), window_.reset(NativeWindow::Create(web_contents->managed_web_contents(),
options)); options));

View file

@ -4,6 +4,17 @@ BrowserWindow = require 'browser-window'
frameToGuest = {} 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|. # Create a new guest created by |embedder| with |options|.
createGuest = (embedder, url, frameName, options) -> createGuest = (embedder, url, frameName, options) ->
guest = frameToGuest[frameName] guest = frameToGuest[frameName]
@ -11,7 +22,7 @@ createGuest = (embedder, url, frameName, options) ->
guest.loadUrl url guest.loadUrl url
return guest.id return guest.id
guest = new BrowserWindow(options) guest = new BrowserWindow(mergeBrowserWindowOptions(embedder, options))
guest.loadUrl url guest.loadUrl url
# Remember the embedder, will be used by window.opener methods. # Remember the embedder, will be used by window.opener methods.

View file

@ -40,6 +40,9 @@ WebContentsPreferences::WebContentsPreferences(
base::DictionaryValue* web_preferences) { base::DictionaryValue* web_preferences) {
web_preferences_.Swap(web_preferences); web_preferences_.Swap(web_preferences);
web_contents->SetUserData(UserDataKey(), this); web_contents->SetUserData(UserDataKey(), this);
// The "isGuest" is not a preferences field.
web_preferences_.Remove("isGuest", nullptr);
} }
WebContentsPreferences::~WebContentsPreferences() { WebContentsPreferences::~WebContentsPreferences() {

View file

@ -37,6 +37,9 @@ class WebContentsPreferences
// $.extend(|web_preferences_|, |new_web_preferences|). // $.extend(|web_preferences_|, |new_web_preferences|).
void Merge(const base::DictionaryValue& new_web_preferences); void Merge(const base::DictionaryValue& new_web_preferences);
// Returns the web preferences.
base::DictionaryValue* web_preferences() { return &web_preferences_; }
private: private:
friend class content::WebContentsUserData<WebContentsPreferences>; friend class content::WebContentsUserData<WebContentsPreferences>;

View file

@ -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 compatible with traditional web pages. For full control of the new window
you should create a `BrowserWindow` directly. 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])` ### `window.open(url[, frameName][, features])`
* `url` String * `url` String
@ -16,6 +20,9 @@ you should create a `BrowserWindow` directly.
Creates a new window and returns an instance of `BrowserWindowProxy` class. 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)` ### `window.opener.postMessage(message, targetOrigin)`
* `message` String * `message` String

View file

@ -35,6 +35,8 @@ describe 'chromium feature', ->
assert.notEqual navigator.language, '' assert.notEqual navigator.language, ''
describe 'window.open', -> describe 'window.open', ->
@timeout 10000
it 'returns a BrowserWindowProxy object', -> it 'returns a BrowserWindowProxy object', ->
b = window.open 'about:blank', '', 'show=no' b = window.open 'about:blank', '', 'show=no'
assert.equal b.closed, false assert.equal b.closed, false
@ -50,6 +52,16 @@ describe 'chromium feature', ->
window.addEventListener 'message', listener window.addEventListener 'message', listener
b = window.open "file://#{fixtures}/pages/window-opener-node.html", '', 'node-integration=no,show=no' 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', -> describe 'window.opener', ->
@timeout 10000 @timeout 10000

View file

@ -0,0 +1,8 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
var size = require('remote').getCurrentWindow().getSize();
window.opener.postMessage('size: ' + size.width + ' ' + size.height, '*')
</script>
</body>
</html>