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);
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<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(
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> WebContents::CreateFrom(
// static
mate::Handle<WebContents> 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;
}

View file

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

View file

@ -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.

View file

@ -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() {

View file

@ -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<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
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

View file

@ -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
@ -50,6 +52,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

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>