Commit df345d7a authored by lazyboy's avatar lazyboy Committed by Commit bot

Extract the element implementation logic to function mods in <webview>.

  function mods end with "$".

"element" inside <webview> is currently the plugin <object> element, i.e.
  the browser plugin. This CL makes it possible to provide a different
  implementation for the element. This CL also provides a stub
  using <iframe>. This will be used by the <webview> using OOPIF
  architecture CL: https://chromiumcodereview.appspot.com/972313002/

BUG=330264
Test=None, no visible changes.

Review URL: https://codereview.chromium.org/1165773004

Cr-Commit-Position: refs/heads/master@{#333592}
parent bf3a8708
......@@ -953,6 +953,7 @@
'renderer/resources/guest_view/surface_view/surface_view.js',
'renderer/resources/guest_view/web_view/web_view.js',
'renderer/resources/guest_view/web_view/web_view_events.js',
'renderer/resources/guest_view/web_view/web_view_iframe.js',
'renderer/resources/web_request_custom_bindings.js',
'renderer/resources/web_request_internal_custom_bindings.js',
'renderer/runtime_custom_bindings.cc',
......
......@@ -472,6 +472,15 @@ std::vector<std::pair<std::string, int> > Dispatcher::GetJsResources() {
resources.push_back(std::make_pair("guestViewDeny", IDR_GUEST_VIEW_DENY_JS));
resources.push_back(std::make_pair("guestViewEvents",
IDR_GUEST_VIEW_EVENTS_JS));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kSitePerProcess)) {
resources.push_back(std::make_pair("guestViewIframe",
IDR_GUEST_VIEW_IFRAME_JS));
resources.push_back(std::make_pair("guestViewIframeContainer",
IDR_GUEST_VIEW_IFRAME_CONTAINER_JS));
}
resources.push_back(std::make_pair("imageUtil", IDR_IMAGE_UTIL_JS));
resources.push_back(std::make_pair("json_schema", IDR_JSON_SCHEMA_JS));
resources.push_back(std::make_pair("lastError", IDR_LAST_ERROR_JS));
......@@ -509,6 +518,11 @@ std::vector<std::pair<std::string, int> > Dispatcher::GetJsResources() {
resources.push_back(std::make_pair("webViewEvents", IDR_WEB_VIEW_EVENTS_JS));
resources.push_back(std::make_pair("webViewInternal",
IDR_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kSitePerProcess)) {
resources.push_back(std::make_pair("webViewIframe",
IDR_WEB_VIEW_IFRAME_JS));
}
resources.push_back(
std::make_pair(mojo::kBindingsModuleName, IDR_MOJO_BINDINGS_JS));
resources.push_back(
......@@ -1417,6 +1431,11 @@ void Dispatcher::RequireGuestViewModules(ScriptContext* context) {
module_system->Require("webView");
module_system->Require("webViewApiMethods");
module_system->Require("webViewAttributes");
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kSitePerProcess)) {
module_system->Require("webViewIframe");
}
}
// The "guestViewDeny" module must always be loaded last. It registers
......
......@@ -28,11 +28,13 @@
<include name="IDR_EXTENSION_VIEW_CONSTANTS_JS" file="guest_view/extension_view/extension_view_constants.js" type="BINDATA" />
<include name="IDR_EXTENSION_VIEW_EVENTS_JS" file="guest_view/extension_view/extension_view_events.js" type="BINDATA" />
<include name="IDR_EXTENSION_VIEW_INTERNAL_CUSTOM_BINDINGS_JS" file="guest_view/extension_view/extension_view_internal.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_JS" file="guest_view/guest_view.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_ATTRIBUTES_JS" file="guest_view/guest_view_attributes.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_CONTAINER_JS" file="guest_view/guest_view_container.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_DENY_JS" file="guest_view/guest_view_deny.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_EVENTS_JS" file="guest_view/guest_view_events.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_IFRAME_CONTAINER_JS" file="guest_view/guest_view_iframe_container.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_IFRAME_JS" file="guest_view/guest_view_iframe.js" type="BINDATA" />
<include name="IDR_GUEST_VIEW_JS" file="guest_view/guest_view.js" type="BINDATA" />
<include name="IDR_IMAGE_UTIL_JS" file="image_util.js" type="BINDATA" />
<include name="IDR_JSON_SCHEMA_JS" file="json_schema.js" type="BINDATA" />
<include name="IDR_KEEP_ALIVE_JS" file="keep_alive.js" type="BINDATA" />
......@@ -61,6 +63,7 @@
<include name="IDR_WEB_VIEW_ATTRIBUTES_JS" file="guest_view/web_view/web_view_attributes.js" type="BINDATA" />
<include name="IDR_WEB_VIEW_CONSTANTS_JS" file="guest_view/web_view/web_view_constants.js" type="BINDATA" />
<include name="IDR_WEB_VIEW_EVENTS_JS" file="guest_view/web_view/web_view_events.js" type="BINDATA" />
<include name="IDR_WEB_VIEW_IFRAME_JS" file="guest_view/web_view/web_view_iframe.js" type="BINDATA" />
<include name="IDR_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS" file="guest_view/web_view/web_view_internal.js" type="BINDATA" />
<include name="IDR_WEB_VIEW_JS" file="guest_view/web_view/web_view.js" type="BINDATA" />
......
......@@ -70,7 +70,7 @@ AppViewImpl.prototype.connect = function(app, data, callback) {
}
return;
}
this.attachWindow();
this.attachWindow$();
if (callback) {
callback(true);
}
......
......@@ -41,7 +41,7 @@ ExtensionOptionsImpl.prototype.createGuest = function() {
var createFailedEvent = new Event('createfailed', { bubbles: true });
this.dispatchEvent(createFailedEvent);
} else {
this.attachWindow();
this.attachWindow$();
}
}.bind(this));
};
......
......@@ -29,7 +29,7 @@ ExtensionViewImpl.setupElement = function(proto) {
ExtensionViewImpl.prototype.createGuest = function() {
this.guest.create(this.buildParams(), function() {
this.attachWindow();
this.attachWindow$();
}.bind(this));
};
......
......@@ -14,11 +14,6 @@ var GuestViewInternalNatives = requireNative('guest_view_internal');
// Events.
var ResizeEvent = CreateEvent('guestViewInternal.onResize');
// Possible states.
var GUEST_STATE_ATTACHED = 2;
var GUEST_STATE_CREATED = 1;
var GUEST_STATE_START = 0;
// Error messages.
var ERROR_MSG_ALREADY_ATTACHED = 'The guest has already been attached.';
var ERROR_MSG_ALREADY_CREATED = 'The guest has already been created.';
......@@ -35,10 +30,10 @@ var PROPERTY_ON_RESIZE = 'onresize';
function GuestViewImpl(guestView, viewType, guestInstanceId) {
if (guestInstanceId) {
this.id = guestInstanceId;
this.state = GUEST_STATE_CREATED;
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
} else {
this.id = 0;
this.state = GUEST_STATE_START;
this.state = GuestViewImpl.GuestState.GUEST_STATE_START;
}
this.actionQueue = [];
this.contentWindow = null;
......@@ -50,6 +45,13 @@ function GuestViewImpl(guestView, viewType, guestInstanceId) {
this.setupOnResize();
}
// Possible states.
GuestViewImpl.GuestState = {
GUEST_STATE_START: 0,
GUEST_STATE_CREATED: 1,
GUEST_STATE_ATTACHED: 2
};
// Sets up the onResize property on the GuestView.
GuestViewImpl.prototype.setupOnResize = function() {
$Object.defineProperty(this.guestView, PROPERTY_ON_RESIZE, {
......@@ -145,7 +147,7 @@ GuestViewImpl.prototype.weakWrapper = function(func, viewInstanceId) {
};
// Internal implementation of attach().
GuestViewImpl.prototype.attachImpl = function(
GuestViewImpl.prototype.attachImpl$ = function(
internalInstanceId, viewInstanceId, attachParams, callback) {
// Check the current state.
if (!this.checkState('attach')) {
......@@ -159,7 +161,7 @@ GuestViewImpl.prototype.attachImpl = function(
var callbackWrapper = function(callback, contentWindow) {
// Check if attaching failed.
if (!contentWindow) {
this.state = GUEST_STATE_CREATED;
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
this.internalInstanceId = 0;
} else {
// Only update the contentWindow if attaching is successful.
......@@ -176,23 +178,23 @@ GuestViewImpl.prototype.attachImpl = function(
callbackWrapper.bind(this, callback));
this.internalInstanceId = internalInstanceId;
this.state = GUEST_STATE_ATTACHED;
this.state = GuestViewImpl.GuestState.GUEST_STATE_ATTACHED;
// Detach automatically when the container is destroyed.
GuestViewInternalNatives.RegisterDestructionCallback(
internalInstanceId, this.weakWrapper(function() {
if (this.state != GUEST_STATE_ATTACHED ||
if (this.state != GuestViewImpl.GuestState.GUEST_STATE_ATTACHED ||
this.internalInstanceId != internalInstanceId) {
return;
}
this.internalInstanceId = 0;
this.state = GUEST_STATE_CREATED;
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
}, viewInstanceId));
};
// Internal implementation of create().
GuestViewImpl.prototype.createImpl = function(createParams, callback) {
GuestViewImpl.prototype.createImpl$ = function(createParams, callback) {
// Check the current state.
if (!this.checkState('create')) {
this.handleCallback(callback);
......@@ -209,7 +211,7 @@ GuestViewImpl.prototype.createImpl = function(createParams, callback) {
// Check if creation failed.
if (this.id === 0) {
this.state = GUEST_STATE_START;
this.state = GuestViewImpl.GuestState.GUEST_STATE_START;
this.contentWindow = null;
}
......@@ -217,11 +219,14 @@ GuestViewImpl.prototype.createImpl = function(createParams, callback) {
this.handleCallback(callback);
};
GuestViewInternal.createGuest(this.viewType,
createParams,
callbackWrapper.bind(this, callback));
this.sendCreateRequest(createParams, callbackWrapper.bind(this, callback));
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
};
this.state = GUEST_STATE_CREATED;
GuestViewImpl.prototype.sendCreateRequest = function(
createParams, boundCallback) {
GuestViewInternal.createGuest(this.viewType, createParams, boundCallback);
};
// Internal implementation of destroy().
......@@ -232,7 +237,7 @@ GuestViewImpl.prototype.destroyImpl = function(callback) {
return;
}
if (this.state == GUEST_STATE_START) {
if (this.state == GuestViewImpl.GuestState.GUEST_STATE_START) {
// destroy() does nothing in this case.
this.handleCallback(callback);
return;
......@@ -250,7 +255,7 @@ GuestViewImpl.prototype.destroyImpl = function(callback) {
this.contentWindow = null;
this.id = 0;
this.internalInstanceId = 0;
this.state = GUEST_STATE_START;
this.state = GuestViewImpl.GuestState.GUEST_STATE_START;
if (ResizeEvent.hasListener(this.callOnResize)) {
ResizeEvent.removeListener(this.callOnResize);
}
......@@ -269,7 +274,7 @@ GuestViewImpl.prototype.detachImpl = function(callback) {
this.handleCallback.bind(this, callback));
this.internalInstanceId = 0;
this.state = GUEST_STATE_CREATED;
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
};
// Internal implementation of setSize().
......@@ -295,7 +300,7 @@ function GuestView(viewType, guestInstanceId) {
GuestView.prototype.attach = function(
internalInstanceId, viewInstanceId, attachParams, callback) {
var internal = privates(this).internal;
internal.actionQueue.push(internal.attachImpl.bind(
internal.actionQueue.push(internal.attachImpl$.bind(
internal, internalInstanceId, viewInstanceId, attachParams, callback));
internal.performNextAction();
};
......@@ -303,7 +308,7 @@ GuestView.prototype.attach = function(
// Creates the guestview.
GuestView.prototype.create = function(createParams, callback) {
var internal = privates(this).internal;
internal.actionQueue.push(internal.createImpl.bind(
internal.actionQueue.push(internal.createImpl$.bind(
internal, createParams, callback));
internal.performNextAction();
};
......@@ -346,3 +351,5 @@ GuestView.prototype.getId = function() {
// Exports
exports.GuestView = GuestView;
exports.GuestViewImpl = GuestViewImpl;
exports.ResizeEvent = ResizeEvent;
......@@ -23,10 +23,10 @@ function GuestViewContainer(element, viewType) {
this.guest = new GuestView(viewType);
this.setupAttributes();
privates(this).browserPluginElement = this.createBrowserPluginElement();
privates(this).internalElement = this.createInternalElement$();
this.setupFocusPropagation();
var shadowRoot = this.element.createShadowRoot();
shadowRoot.appendChild(privates(this).browserPluginElement);
shadowRoot.appendChild(privates(this).internalElement);
GuestViewInternalNatives.RegisterView(this.viewInstanceId, this);
}
......@@ -52,8 +52,7 @@ GuestViewContainer.registerElement = function(guestViewContainerType) {
if (document.readyState == 'loading')
return;
registerBrowserPluginElement(
guestViewContainerType.VIEW_TYPE.toLowerCase());
registerInternalElement(guestViewContainerType.VIEW_TYPE.toLowerCase());
registerGuestViewElement(guestViewContainerType);
window.removeEventListener(event.type, listener, useCapture);
}, useCapture);
......@@ -85,7 +84,7 @@ GuestViewContainer.prototype.setupGuestProperty = function() {
});
};
GuestViewContainer.prototype.createBrowserPluginElement = function() {
GuestViewContainer.prototype.createInternalElement$ = function() {
// We create BrowserPlugin as a custom element in order to observe changes
// to attributes synchronously.
var browserPluginElement =
......@@ -104,15 +103,15 @@ GuestViewContainer.prototype.setupFocusPropagation = function() {
}
this.element.addEventListener('focus', this.weakWrapper(function(e) {
// Focus the BrowserPlugin when the GuestViewContainer takes focus.
privates(this).browserPluginElement.focus();
privates(this).internalElement.focus();
}));
this.element.addEventListener('blur', this.weakWrapper(function(e) {
// Blur the BrowserPlugin when the GuestViewContainer loses focus.
privates(this).browserPluginElement.blur();
privates(this).internalElement.blur();
}));
};
GuestViewContainer.prototype.attachWindow = function() {
GuestViewContainer.prototype.attachWindow$ = function() {
if (!this.internalInstanceId) {
return true;
}
......@@ -129,24 +128,28 @@ GuestViewContainer.prototype.makeGCOwnContainer = function(internalInstanceId) {
}, -1);
};
GuestViewContainer.prototype.handleBrowserPluginAttributeMutation =
function(name, oldValue, newValue) {
if (name == 'internalinstanceid' && !oldValue && !!newValue) {
privates(this).browserPluginElement.removeAttribute('internalinstanceid');
this.internalInstanceId = parseInt(newValue);
GuestViewContainer.prototype.onInternalInstanceId = function(
internalInstanceId) {
this.internalInstanceId = internalInstanceId;
this.makeGCOwnContainer(this.internalInstanceId);
this.makeGCOwnContainer(this.internalInstanceId);
// Track when the element resizes using the element resize callback.
GuestViewInternalNatives.RegisterElementResizeCallback(
this.internalInstanceId, this.weakWrapper(this.onElementResize));
// Track when the element resizes using the element resize callback.
GuestViewInternalNatives.RegisterElementResizeCallback(
this.internalInstanceId, this.weakWrapper(this.onElementResize));
if (!this.guest.getId()) {
return;
}
this.guest.attach(this.internalInstanceId,
this.viewInstanceId,
this.buildParams());
};
if (!this.guest.getId()) {
return;
}
this.guest.attach(this.internalInstanceId,
this.viewInstanceId,
this.buildParams());
GuestViewContainer.prototype.handleInternalElementAttributeMutation =
function(name, oldValue, newValue) {
if (name == 'internalinstanceid' && !oldValue && !!newValue) {
privates(this).internalElement.removeAttribute('internalinstanceid');
this.onInternalInstanceId(parseInt(newValue));
}
};
......@@ -196,7 +199,7 @@ GuestViewContainer.prototype.setupAttributes = function() {};
// Registers the browser plugin <object> custom element. |viewType| is the
// name of the specific guestview container (e.g. 'webview').
function registerBrowserPluginElement(viewType) {
function registerInternalElement(viewType) {
var proto = $Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
......@@ -216,7 +219,7 @@ function registerBrowserPluginElement(viewType) {
if (!internal) {
return;
}
internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue);
internal.handleInternalElementAttributeMutation(name, oldValue, newValue);
};
GuestViewContainer[viewType + 'BrowserPlugin'] =
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// --site-per-process overrides for guest_view.js.
var GuestView = require('guestView').GuestView;
var GuestViewImpl = require('guestView').GuestViewImpl;
var GuestViewInternalNatives = requireNative('guest_view_internal');
var ResizeEvent = require('guestView').ResizeEvent;
var getIframeContentWindow = function(viewInstanceId) {
var view = GuestViewInternalNatives.GetViewFromID(viewInstanceId);
if (!view)
return null;
var internalIframeElement = privates(view).internalElement;
if (internalIframeElement)
return internalIframeElement.contentWindow;
return null;
};
// Internal implementation of attach().
GuestViewImpl.prototype.attachImpl$ = function(
internalInstanceId, viewInstanceId, attachParams, callback) {
// Check the current state.
if (!this.checkState('attach')) {
this.handleCallback(callback);
return;
}
// Callback wrapper function to store the contentWindow from the attachGuest()
// callback, handle potential attaching failure, register an automatic detach,
// and advance the queue.
var callbackWrapper = function(callback, contentWindow) {
// Check if attaching failed.
contentWindow = getIframeContentWindow(viewInstanceId);
if (!contentWindow) {
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
this.internalInstanceId = 0;
} else {
// Only update the contentWindow if attaching is successful.
this.contentWindow = contentWindow;
}
this.handleCallback(callback);
};
attachParams['instanceId'] = viewInstanceId;
var contentWindow = getIframeContentWindow(viewInstanceId);
// TODO(lazyboy): Call binding function to attach this guest.
// |contentWindow| should be used to retrieve the RenderFrame in cpp.
this.internalInstanceId = internalInstanceId;
this.state = GuestViewImpl.GuestState.GUEST_STATE_ATTACHED;
// Detach automatically when the container is destroyed.
GuestViewInternalNatives.RegisterDestructionCallback(
internalInstanceId, this.weakWrapper(function() {
if (this.state != GuestViewImpl.GuestState.GUEST_STATE_ATTACHED ||
this.internalInstanceId != internalInstanceId) {
return;
}
this.internalInstanceId = 0;
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
}, viewInstanceId));
};
// Internal implementation of create().
GuestViewImpl.prototype.createImpl$ = function(createParams, callback) {
// Check the current state.
if (!this.checkState('create')) {
this.handleCallback(callback);
return;
}
// Callback wrapper function to store the guestInstanceId from the
// createGuest() callback, handle potential creation failure, and advance the
// queue.
var callbackWrapper = function(callback, guestInfo) {
this.id = guestInfo.id;
// Check if creation failed.
if (this.id === 0) {
this.state = GuestViewImpl.GuestState.GUEST_STATE_START;
this.contentWindow = null;
}
ResizeEvent.addListener(this.callOnResize, {instanceId: this.id});
this.handleCallback(callback);
};
this.sendCreateRequest(createParams, callbackWrapper.bind(this, callback));
this.state = GuestViewImpl.GuestState.GUEST_STATE_CREATED;
};
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// --site-per-process overrides for guest_view_container.js
var GuestViewContainer = require('guestViewContainer').GuestViewContainer;
GuestViewContainer.prototype.createInternalElement$ = function() {
var iframeElement = document.createElement('iframe');
iframeElement.style.width = '100%';
iframeElement.style.height = '100%';
privates(iframeElement).internal = this;
return iframeElement;
};
......@@ -42,7 +42,7 @@ SurfaceViewImpl.prototype.connect = function(url, callback) {
this.guest.destroy();
this.guest.create(this.buildParams(), function() {
this.attachWindow();
this.attachWindow$();
if (callback) {
callback(true);
}
......
......@@ -137,7 +137,7 @@ WebViewImpl.prototype.onSizeChanged = function(webViewEvent) {
WebViewImpl.prototype.createGuest = function() {
this.guest.create(this.buildParams(), function() {
this.attachWindow();
this.attachWindow$();
}.bind(this));
};
......@@ -178,7 +178,7 @@ WebViewImpl.prototype.buildContainerParams = function() {
return params;
};
WebViewImpl.prototype.attachWindow = function(opt_guestInstanceId) {
WebViewImpl.prototype.attachWindow$ = function(opt_guestInstanceId) {
// If |opt_guestInstanceId| was provided, then a different existing guest is
// being attached to this webview, and the current one will get destroyed.
if (opt_guestInstanceId) {
......@@ -189,7 +189,7 @@ WebViewImpl.prototype.attachWindow = function(opt_guestInstanceId) {
this.guest = new GuestView('webview', opt_guestInstanceId);
}
return GuestViewContainer.prototype.attachWindow.call(this);
return GuestViewContainer.prototype.attachWindow$.call(this);
};
// Shared implementation of executeScript() and insertCSS().
......
......@@ -163,7 +163,7 @@ NewWindow.prototype.getInterfaceObject = function() {
webViewImpl.onAttach(this.event.partition);
}
var attached = webViewImpl.attachWindow(this.event.windowId);
var attached = webViewImpl.attachWindow$(this.event.windowId);
if (!attached) {
window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH);
}
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This module provides --site-per-process overrides for WebView (<webview>).
// See web_view.js for details.
var IdGenerator = requireNative('id_generator');
var WebViewImpl = require('webView').WebViewImpl;
// NOTE: Do not remove these, we implicitly depend on these in
// --site-per-process.
var GuestViewIframe = require('guestViewIframe');
var GuestViewIframeContainer = require('guestViewIframeContainer');
WebViewImpl.prototype.attachWindow$ = function(opt_guestInstanceId) {
// If |opt_guestInstanceId| was provided, then a different existing guest is
// being attached to this webview, and the current one will get destroyed.
if (opt_guestInstanceId) {
if (this.guest.getId() == opt_guestInstanceId) {
return true;
}
this.guest.destroy();
this.guest = new GuestView('webview', opt_guestInstanceId);
}
var generatedId = IdGenerator.GetNextId();
// Generate an instance id for the container.
this.onInternalInstanceId(generatedId);
return true;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment