Attach <webview> with guest WebContents

This commit is contained in:
Cheng Zhao 2014-10-24 14:37:14 +08:00
parent 2d8fe489a7
commit 39e75574f4
8 changed files with 126 additions and 28 deletions

View file

@ -6,6 +6,7 @@
#include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_context.h"
#include "atom/common/api/api_messages.h" #include "atom/common/api/api_messages.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/native_mate_converters/value_converter.h"
@ -31,11 +32,13 @@ v8::Persistent<v8::ObjectTemplate> template_;
WebContents::WebContents(content::WebContents* web_contents) WebContents::WebContents(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents), : content::WebContentsObserver(web_contents),
guest_instance_id_(-1) { guest_instance_id_(-1),
auto_size_enabled_(false) {
} }
WebContents::WebContents(const mate::Dictionary& options) WebContents::WebContents(const mate::Dictionary& options)
: guest_instance_id_(-1) { : guest_instance_id_(-1),
auto_size_enabled_(false) {
options.Get("guestInstances", &guest_instance_id_); options.Get("guestInstances", &guest_instance_id_);
content::WebContents::CreateParams params(AtomBrowserContext::Get()); content::WebContents::CreateParams params(AtomBrowserContext::Get());
@ -106,17 +109,19 @@ void WebContents::WebContentsDestroyed() {
void WebContents::WillAttach(content::WebContents* embedder_web_contents, void WebContents::WillAttach(content::WebContents* embedder_web_contents,
const base::DictionaryValue& extra_params) { const base::DictionaryValue& extra_params) {
LOG(ERROR) << "WillAttach"; embedder_web_contents_ = embedder_web_contents;
extra_params_.reset(extra_params.DeepCopy());
} }
content::WebContents* WebContents::CreateNewGuestWindow( content::WebContents* WebContents::CreateNewGuestWindow(
const content::WebContents::CreateParams& create_params) { const content::WebContents::CreateParams& create_params) {
LOG(ERROR) << "CreateNewGuestWindow";
return nullptr; return nullptr;
} }
void WebContents::DidAttach() { void WebContents::DidAttach() {
LOG(ERROR) << "DidAttach"; base::ListValue args;
args.Append(extra_params_.release());
Emit("internal-did-attach", args);
} }
int WebContents::GetGuestInstanceID() const { int WebContents::GetGuestInstanceID() const {
@ -125,29 +130,30 @@ int WebContents::GetGuestInstanceID() const {
void WebContents::ElementSizeChanged(const gfx::Size& old_size, void WebContents::ElementSizeChanged(const gfx::Size& old_size,
const gfx::Size& new_size) { const gfx::Size& new_size) {
LOG(ERROR) << "ElementSizeChanged"; element_size_ = new_size;
} }
void WebContents::GuestSizeChanged(const gfx::Size& old_size, void WebContents::GuestSizeChanged(const gfx::Size& old_size,
const gfx::Size& new_size) { const gfx::Size& new_size) {
LOG(ERROR) << "GuestSizeChanged"; if (!auto_size_enabled_)
return;
guest_size_ = new_size;
GuestSizeChangedDueToAutoSize(old_size, new_size);
} }
void WebContents::RequestPointerLockPermission( void WebContents::RequestPointerLockPermission(
bool user_gesture, bool user_gesture,
bool last_unlocked_by_target, bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) { const base::Callback<void(bool enabled)>& callback) {
callback.Run(true); callback.Run(true);
} }
void WebContents::RegisterDestructionCallback( void WebContents::RegisterDestructionCallback(
const DestructionCallback& callback) { const DestructionCallback& callback) {
LOG(ERROR) << "RegisterDestructionCallback";
destruction_callback_ = callback; destruction_callback_ = callback;
} }
void WebContents::Destroy() { void WebContents::Destroy() {
LOG(ERROR) << "Destroy";
if (storage_) { if (storage_) {
if (!destruction_callback_.is_null()) if (!destruction_callback_.is_null())
destruction_callback_.Run(); destruction_callback_.Run();
@ -248,6 +254,33 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
return Send(new AtomViewMsg_Message(routing_id(), channel, args)); return Send(new AtomViewMsg_Message(routing_id(), channel, args));
} }
void WebContents::SetAutoSize(bool enabled,
const gfx::Size& min_size,
const gfx::Size& max_size) {
min_auto_size_ = min_size;
min_auto_size_.SetToMin(max_size);
max_auto_size_ = max_size;
max_auto_size_.SetToMax(min_size);
enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
if (!enabled && !auto_size_enabled_)
return;
auto_size_enabled_ = enabled;
if (!attached())
return;
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
if (auto_size_enabled_) {
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
} else {
rvh->DisableAutoResize(element_size_);
guest_size_ = element_size_;
GuestSizeChangedDueToAutoSize(guest_size_, element_size_);
}
}
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
v8::Isolate* isolate) { v8::Isolate* isolate) {
if (template_.IsEmpty()) if (template_.IsEmpty())
@ -274,6 +307,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("isCrashed", &WebContents::IsCrashed) .SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript) .SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
.SetMethod("_send", &WebContents::SendIPCMessage) .SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
.Build()); .Build());
return mate::ObjectTemplateBuilder( return mate::ObjectTemplateBuilder(
@ -283,7 +317,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
void WebContents::OnRendererMessage(const base::string16& channel, void WebContents::OnRendererMessage(const base::string16& channel,
const base::ListValue& args) { const base::ListValue& args) {
// webContents.emit(channel, new Event(), args...); // webContents.emit(channel, new Event(), args...);
Emit(base::UTF16ToUTF8(channel), args, web_contents(), NULL); Emit(base::UTF16ToUTF8(channel), args);
} }
void WebContents::OnRendererMessageSync(const base::string16& channel, void WebContents::OnRendererMessageSync(const base::string16& channel,
@ -293,6 +327,16 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
Emit(base::UTF16ToUTF8(channel), args, web_contents(), message); Emit(base::UTF16ToUTF8(channel), args, web_contents(), message);
} }
void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size) {
base::ListValue args;
args.AppendInteger(old_size.width());
args.AppendInteger(old_size.height());
args.AppendInteger(new_size.width());
args.AppendInteger(new_size.height());
Emit("size-changed", args);
}
// static // static
mate::Handle<WebContents> WebContents::CreateFrom( mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) { v8::Isolate* isolate, content::WebContents* web_contents) {

View file

@ -56,6 +56,14 @@ class WebContents : public mate::EventEmitter,
bool SendIPCMessage(const base::string16& channel, bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args); const base::ListValue& args);
// Toggles autosize mode for corresponding <webview>.
void SetAutoSize(bool enabled,
const gfx::Size& min_size,
const gfx::Size& max_size);
// Returns whether this guest has an associated embedder.
bool attached() const { return !!embedder_web_contents_; }
content::WebContents* web_contents() const { content::WebContents* web_contents() const {
return content::WebContentsObserver::web_contents(); return content::WebContentsObserver::web_contents();
} }
@ -96,7 +104,7 @@ class WebContents : public mate::EventEmitter,
virtual void RequestPointerLockPermission( virtual void RequestPointerLockPermission(
bool user_gesture, bool user_gesture,
bool last_unlocked_by_target, bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) override; const base::Callback<void(bool enabled)>& callback) override;
virtual void RegisterDestructionCallback( virtual void RegisterDestructionCallback(
const DestructionCallback& callback) override; const DestructionCallback& callback) override;
@ -110,14 +118,42 @@ class WebContents : public mate::EventEmitter,
const base::ListValue& args, const base::ListValue& args,
IPC::Message* message); IPC::Message* message);
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
// Unique ID for a guest WebContents. // Unique ID for a guest WebContents.
int guest_instance_id_; int guest_instance_id_;
DestructionCallback destruction_callback_; DestructionCallback destruction_callback_;
// The extra parameters associated with this guest view passed
// in from JavaScript. This will typically be the view instance ID,
// the API to use, and view-specific parameters. These parameters
// are passed along to new guests that are created from this guest.
scoped_ptr<base::DictionaryValue> extra_params_;
// Stores the WebContents that managed by this class. // Stores the WebContents that managed by this class.
scoped_ptr<content::WebContents> storage_; scoped_ptr<content::WebContents> storage_;
// The WebContents that attaches this guest view.
content::WebContents* embedder_web_contents_;
// The size of the container element.
gfx::Size element_size_;
// The size of the guest content. Note: In autosize mode, the container
// element may not match the size of the guest.
gfx::Size guest_size_;
// Indicates whether autosize mode is enabled or not.
bool auto_size_enabled_;
// The maximum size constraints of the container element in autosize mode.
gfx::Size max_auto_size_;
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
DISALLOW_COPY_AND_ASSIGN(WebContents); DISALLOW_COPY_AND_ASSIGN(WebContents);
}; };

View file

@ -22,6 +22,14 @@ module.exports.wrap = (webContents) ->
else else
webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code) webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code)
# Init guest web view.
webContents.on 'internal-did-attach', (event, params) ->
min = width: params.minwidth, height: params.minheight
max = width: params.maxwidth, height: params.maxheight
@setAutoSize params.autosize, min, max
if params.src
@loadUrl params.src
# The processId and routingId and identify a webContents. # The processId and routingId and identify a webContents.
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}" webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
webContents.equal = (other) -> @getId() is other.getId() webContents.equal = (other) -> @getId() is other.getId()
@ -32,10 +40,10 @@ module.exports.wrap = (webContents) ->
process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}" process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}"
# Dispatch IPC messages to the ipc module. # Dispatch IPC messages to the ipc module.
webContents.on 'ipc-message', (event, channel, args...) => webContents.on 'ipc-message', (event, channel, args...) ->
Object.defineProperty event, 'sender', value: webContents Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args... ipc.emit channel, event, args...
webContents.on 'ipc-message-sync', (event, channel, args...) => webContents.on 'ipc-message-sync', (event, channel, args...) ->
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
Object.defineProperty event, 'sender', value: webContents Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args... ipc.emit channel, event, args...

View file

@ -56,7 +56,7 @@
</style> </style>
</head> </head>
<body> <body>
<webview id="foo" src="http://www.baidu.com/" style="display:block; width:640px; height:100px"></webview> <webview id="foo" autosize src="http://www.baidu.com/" style="display:block; width:640px; height:100px"></webview>
<script> <script>
var execPath = require('remote').process.execPath; var execPath = require('remote').process.execPath;

View file

@ -32,3 +32,6 @@ ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, reque
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, guestInstanceId) -> ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, guestInstanceId) ->
destroyGuest guestInstanceId destroyGuest guestInstanceId
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, guestInstanceId, params) ->
guestInstances[id]?.setAutoSize params.enableAutoSize, params.min, params.max

View file

@ -2,6 +2,9 @@
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "ui/gfx/point.h" #include "ui/gfx/point.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
@ -94,3 +97,5 @@ struct Converter<gfx::Display> {
}; };
} // namespace mate } // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_

View file

@ -10,3 +10,6 @@ module.exports =
destroyGuest: (guestInstanceId) -> destroyGuest: (guestInstanceId) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId
setAutoSize: (guestInstanceId, params) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', guestInstanceId, params

View file

@ -3,8 +3,8 @@ guestViewInternal = require './guest-view-internal'
webView = require 'web-view' webView = require 'web-view'
# ID generator. # ID generator.
nextId = 1 nextId = 0
getNextId = -> nextId++ getNextId = -> ++nextId
# FIXME # FIXME
# Discarded after Chrome 39 # Discarded after Chrome 39
@ -45,7 +45,7 @@ class Partition
toAttribute: -> toAttribute: ->
return '' unless @validPartitionId return '' unless @validPartitionId
(@persistStorage ? 'persist:' : '') + @storagePartitionId (if @persistStorage then 'persist:' else '') + @storagePartitionId
fromAttribute: (value, hasNavigated) -> fromAttribute: (value, hasNavigated) ->
result = {} result = {}
@ -223,15 +223,14 @@ class WebView
return unless @guestInstanceId return unless @guestInstanceId
# Convert autosize attribute to boolean. # Convert autosize attribute to boolean.
autosize = @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_AUTOSIZE autosize = @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_AUTOSIZE
# FIXME guestViewInternal.setAutoSize @guestInstanceId,
# GuestViewInternal.setAutoSize @guestInstanceId, enableAutoSize: autosize,
# enableAutoSize: autosize, min:
# min: width: parseInt @minwidth || 0
# width: parseInt @minwidth ? 0 height: parseInt @minheight || 0
# height: parseInt @minheight ? 0 max:
# max: width: parseInt @maxwidth || 0
# width: parseInt @maxwidth ? 0 height: parseInt @maxheight || 0
# height: parseInt @maxheight ? 0
else if name is WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY else if name is WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY
# We treat null attribute (attribute removed) and the empty string as # We treat null attribute (attribute removed) and the empty string as
# one case. # one case.
@ -450,7 +449,7 @@ class WebView
minwidth: parseInt @minwidth || 0 minwidth: parseInt @minwidth || 0
name: @name name: @name
# We don't need to navigate new window from here. # We don't need to navigate new window from here.
src: isNewWindow ? undefined : @src src: if isNewWindow then undefined else @src
# If we have a partition from the opener, that will also be already # If we have a partition from the opener, that will also be already
# set via this.onAttach(). # set via this.onAttach().
storagePartitionId: @partition.toAttribute() storagePartitionId: @partition.toAttribute()