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/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/string16_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)
: content::WebContentsObserver(web_contents),
guest_instance_id_(-1) {
guest_instance_id_(-1),
auto_size_enabled_(false) {
}
WebContents::WebContents(const mate::Dictionary& options)
: guest_instance_id_(-1) {
: guest_instance_id_(-1),
auto_size_enabled_(false) {
options.Get("guestInstances", &guest_instance_id_);
content::WebContents::CreateParams params(AtomBrowserContext::Get());
@ -106,17 +109,19 @@ void WebContents::WebContentsDestroyed() {
void WebContents::WillAttach(content::WebContents* embedder_web_contents,
const base::DictionaryValue& extra_params) {
LOG(ERROR) << "WillAttach";
embedder_web_contents_ = embedder_web_contents;
extra_params_.reset(extra_params.DeepCopy());
}
content::WebContents* WebContents::CreateNewGuestWindow(
const content::WebContents::CreateParams& create_params) {
LOG(ERROR) << "CreateNewGuestWindow";
return nullptr;
}
void WebContents::DidAttach() {
LOG(ERROR) << "DidAttach";
base::ListValue args;
args.Append(extra_params_.release());
Emit("internal-did-attach", args);
}
int WebContents::GetGuestInstanceID() const {
@ -125,29 +130,30 @@ int WebContents::GetGuestInstanceID() const {
void WebContents::ElementSizeChanged(const gfx::Size& old_size,
const gfx::Size& new_size) {
LOG(ERROR) << "ElementSizeChanged";
element_size_ = new_size;
}
void WebContents::GuestSizeChanged(const gfx::Size& old_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(
bool user_gesture,
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) {
const base::Callback<void(bool enabled)>& callback) {
callback.Run(true);
}
void WebContents::RegisterDestructionCallback(
const DestructionCallback& callback) {
LOG(ERROR) << "RegisterDestructionCallback";
destruction_callback_ = callback;
}
void WebContents::Destroy() {
LOG(ERROR) << "Destroy";
if (storage_) {
if (!destruction_callback_.is_null())
destruction_callback_.Run();
@ -248,6 +254,33 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
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(
v8::Isolate* isolate) {
if (template_.IsEmpty())
@ -274,6 +307,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
.SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
.Build());
return mate::ObjectTemplateBuilder(
@ -283,7 +317,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
void WebContents::OnRendererMessage(const base::string16& channel,
const base::ListValue& 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,
@ -293,6 +327,16 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
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
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) {

View file

@ -56,6 +56,14 @@ class WebContents : public mate::EventEmitter,
bool SendIPCMessage(const base::string16& channel,
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 {
return content::WebContentsObserver::web_contents();
}
@ -96,7 +104,7 @@ class WebContents : public mate::EventEmitter,
virtual void RequestPointerLockPermission(
bool user_gesture,
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) override;
const base::Callback<void(bool enabled)>& callback) override;
virtual void RegisterDestructionCallback(
const DestructionCallback& callback) override;
@ -110,14 +118,42 @@ class WebContents : public mate::EventEmitter,
const base::ListValue& args,
IPC::Message* message);
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
// Unique ID for a guest WebContents.
int guest_instance_id_;
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.
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);
};

View file

@ -22,6 +22,14 @@ module.exports.wrap = (webContents) ->
else
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.
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
webContents.equal = (other) -> @getId() is other.getId()
@ -32,10 +40,10 @@ module.exports.wrap = (webContents) ->
process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}"
# 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
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, 'sender', value: webContents
ipc.emit channel, event, args...

View file

@ -56,7 +56,7 @@
</style>
</head>
<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>
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) ->
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
// 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 "ui/gfx/point.h"
#include "ui/gfx/rect.h"
@ -94,3 +97,5 @@ struct Converter<gfx::Display> {
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_

View file

@ -10,3 +10,6 @@ module.exports =
destroyGuest: (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'
# ID generator.
nextId = 1
getNextId = -> nextId++
nextId = 0
getNextId = -> ++nextId
# FIXME
# Discarded after Chrome 39
@ -45,7 +45,7 @@ class Partition
toAttribute: ->
return '' unless @validPartitionId
(@persistStorage ? 'persist:' : '') + @storagePartitionId
(if @persistStorage then 'persist:' else '') + @storagePartitionId
fromAttribute: (value, hasNavigated) ->
result = {}
@ -223,15 +223,14 @@ class WebView
return unless @guestInstanceId
# Convert autosize attribute to boolean.
autosize = @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_AUTOSIZE
# FIXME
# GuestViewInternal.setAutoSize @guestInstanceId,
# enableAutoSize: autosize,
# min:
# width: parseInt @minwidth ? 0
# height: parseInt @minheight ? 0
# max:
# width: parseInt @maxwidth ? 0
# height: parseInt @maxheight ? 0
guestViewInternal.setAutoSize @guestInstanceId,
enableAutoSize: autosize,
min:
width: parseInt @minwidth || 0
height: parseInt @minheight || 0
max:
width: parseInt @maxwidth || 0
height: parseInt @maxheight || 0
else if name is WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY
# We treat null attribute (attribute removed) and the empty string as
# one case.
@ -450,7 +449,7 @@ class WebView
minwidth: parseInt @minwidth || 0
name: @name
# 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
# set via this.onAttach().
storagePartitionId: @partition.toAttribute()