Commit 6d745d6d authored by lazyboy's avatar lazyboy Committed by Commit bot

<webview>: Implement fullscreen permission for html5 element.requestFullscreen()

We do it in two stages, first a DOM element requests fullscreen inside <webview>,
this fires a permissionrequest to the embedder of <webview> to decide
whether to allow/deny the request. The element goes fullscreen within
the <webview>'s bounds at this point.
The embedder can:
a) allow the request: in this case we perform the second stage, where the
<webview> element in the embedder enters fullscreen (provided that
the embedder has permission to enter fullscreen).
b) deny the request: in this case, <webview> exits fullscreen mode.

Note that b) will cause a flicker and blink interface is required to avoid that.
That is tracked on http://crbug.com/466854.

BUG=141198
Test=
Load a chrome app with a <webview> in it, make the <webview> point to
some site that has html5 fullscreen request, e.g. youtube.com.

Add an event listener in the chrome app so that it allows <webview> fullscreen, e.g.

<webview>.addEventListener('permissionrequest', function(e) {
  if (e.permission === 'fullscreen') e.request.allow();
});

Now perform necessary action to request fullscreen from the <webview>, for the
youtube case, this would be fullscreening the video player.

Check that the element enters fullscreen mode.

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

Cr-Commit-Position: refs/heads/master@{#321282}
parent df69a28d
...@@ -528,6 +528,24 @@ class WebViewInteractiveTest ...@@ -528,6 +528,24 @@ class WebViewInteractiveTest
last_drop_data_ = last_drop_data; last_drop_data_ = last_drop_data;
} }
void FullscreenTestHelper(const std::string& test_name,
const std::string& test_dir) {
TestHelper(test_name, test_dir, NO_TEST_SERVER);
content::WebContents* embedder_web_contents =
GetFirstAppWindowWebContents();
ASSERT_TRUE(embedder_web_contents);
ASSERT_TRUE(guest_web_contents());
// Click the guest to request fullscreen.
ExtensionTestMessageListener passed_listener(
"FULLSCREEN_STEP_PASSED", false);
passed_listener.set_failure_message("TEST_FAILED");
content::SimulateMouseClickAt(guest_web_contents(),
0,
blink::WebMouseEvent::ButtonLeft,
gfx::Point(20, 20));
ASSERT_TRUE(passed_listener.WaitUntilSatisfied());
}
protected: protected:
TestGuestViewManagerFactory factory_; TestGuestViewManagerFactory factory_;
content::WebContents* guest_web_contents_; content::WebContents* guest_web_contents_;
...@@ -998,6 +1016,44 @@ IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ...@@ -998,6 +1016,44 @@ IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
NO_TEST_SERVER); NO_TEST_SERVER);
} }
// Disable this on mac, throws an assertion failure on teardown which
// will result in flakiness:
//
// "not is fullscreen state"
// "*** Assertion failure in -[_NSWindowFullScreenTransition
// transitionedWindowFrame],"
// See similar bug: http://crbug.com/169820.
#if defined(OS_MACOSX)
#define MAYBE_FullscreenAllow_EmbedderHasPermission \
DISABLED_FullscreenAllow_EmbedderHasPermission
#else
#define MAYBE_FullscreenAllow_EmbedderHasPermission \
FullscreenAllow_EmbedderHasPermission
#endif
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
MAYBE_FullscreenAllow_EmbedderHasPermission) {
FullscreenTestHelper("testFullscreenAllow",
"web_view/fullscreen/embedder_has_permission");
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenDeny_EmbedderHasPermission) {
FullscreenTestHelper("testFullscreenDeny",
"web_view/fullscreen/embedder_has_permission");
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenAllow_EmbedderHasNoPermission) {
FullscreenTestHelper("testFullscreenAllow",
"web_view/fullscreen/embedder_has_no_permission");
}
IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest,
FullscreenDeny_EmbedderHasNoPermission) {
FullscreenTestHelper("testFullscreenDeny",
"web_view/fullscreen/embedder_has_no_permission");
}
// This test exercies the following scenario: // This test exercies the following scenario:
// 1. An <input> in guest has focus. // 1. An <input> in guest has focus.
// 2. User takes focus to embedder by clicking e.g. an <input> in embedder. // 2. User takes focus to embedder by clicking e.g. an <input> in embedder.
......
<!--
* 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.
-->
<html>
<body>
<div id="webview-tag-container"></div>
<script src="embedder.js"></script>
</body>
</html>
// 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.
var embedder = {};
embedder.test = {};
embedder.test.fail = function() {
chrome.test.sendMessage('TEST_FAILED');
};
// window.* exported functions begin.
window.runTest = function(testName) {
if (!embedder.test.testList[testName]) {
console.log('Incorrect testName: ' + testName);
embedder.test.fail();
return;
}
// Run the test.
embedder.test.testList[testName]();
};
// window.* exported functions end.
var LOG = function(msg) {
window.console.log(msg);
};
function TestState(opt_guestFullscreenChangeType,
opt_didEmbedderGoFullscreen) {
this.guestFullscreenChangeType = opt_guestFullscreenChangeType || "none";
this.didEmbedderGoFullscreen = opt_didEmbedderGoFullscreen || false;
};
TestState.prototype.equals = function(other) {
return this.guestFullscreenChangeType === other.guestFullscreenChangeType &&
this.didEmbedderGoFullscreen === other.didEmbedderGoFullscreen;
};
/**
* @constructor
* @param {boolean} allowFullscreen Whether to allow fullscreen permission.
* @param {string} expectedChangeType Expected type of fullscreen change,
* can be one of "enter" or "exit".
* @param {boolean} expectEmbedderToGoFullscreen Whether or not we expect
* to see fullscreen change event on the embedder/app.
*/
function Tester(allowFullscreen,
expectedChangeType,
expectedDidEmbedderGoFullscreen) {
this.registerEventHandlers_();
this.allowFullscreen_ = allowFullscreen;
this.currentState_ = new TestState();
this.expectedState_ = new TestState(expectedChangeType,
expectedDidEmbedderGoFullscreen);
}
Tester.prototype.registerEventHandlers_ = function() {
document.onwebkitfullscreenchange = this.onFullscreenchange_.bind(this);
document.onwebkitfullscreenerror = this.onFullscreenerror_.bind(this);
};
Tester.prototype.onFullscreenchange_ = function(e) {
LOG('embedder.onFullscreenchange_');
var didEnterFullscreen = document.webkitIsFullScreen;
if (didEnterFullscreen) {
this.currentState_.didEmbedderGoFullscreen = true;
}
this.checkIfTestPassed_();
};
Tester.prototype.onFullscreenerror_ = function(e) {
LOG('embedder.onFullscreenerror_');
embedder.test.fail();
};
Tester.prototype.checkIfTestPassed_ = function() {
LOG('checkIfTestPassed_');
if (this.currentState_.equals(this.expectedState_)) {
chrome.test.sendMessage('FULLSCREEN_STEP_PASSED');
}
};
Tester.prototype.runTest = function() {
var container = document.querySelector('#webview-tag-container');
var webview = new WebView();
webview.style.width = '100px';
webview.style.height = '100px';
container.appendChild(webview);
// Setup event handlers on webview.
webview.addEventListener('loadstop', function() {
LOG('webview.loadstop');
webview.executeScript(
{file: 'guest.js'},
function(results) {
if (!results || !results.length) {
LOG('Error injecting script to webview');
embedder.test.fail();
return;
}
LOG('webview executeScript succeeded');
chrome.test.sendMessage('TEST_PASSED');
});
});
webview.addEventListener('consolemessage',
this.onGuestConsoleMessage_.bind(this));
webview.addEventListener('permissionrequest', function(e) {
if (e.permission === 'fullscreen') {
window.console.log('permissionrequest.fullscreen');
if (this.allowFullscreen_) {
e.request.allow();
} else {
e.request.deny();
}
}
}.bind(this));
// Note that we cannot use "about:blank" since fullscreen events don't
// seem to fire on webview document in that case.
webview.src = 'data:text/html,<html><body></body></html>';
};
Tester.prototype.onGuestConsoleMessage_ = function(e) {
LOG('GUEST.consolemessage: ' + e.message);
var status = this.getFullscreenStatusFromConsoleMessage_(e.message);
if (status && status.isFullscreenChange) {
if (status.failed) {
embedder.test.fail();
return;
}
this.currentState_.guestFullscreenChangeType = status.changeType;
this.checkIfTestPassed_();
}
};
Tester.prototype.getFullscreenStatusFromConsoleMessage_ = function(m) {
// status is of the following form:
// 'STATUS{
// "isFullscreenChange": true,
// "changeType": "enter" or "exit",
// failed": true/undefined
// }'.
var matches = m.match(/^STATUS(.*)/);
if (!matches) {
return null;
}
return JSON.parse(matches[1]);
};
function testFullscreenAllow() {
LOG('testFullscreenAllow');
var tester = new Tester(true /* allow */,
"exit" /* expectedChangeType */,
false /* expectEmbedderToGoFullscreen */);
tester.runTest();
}
function testFullscreenDeny() {
LOG('testFullscreenDeny');
var tester = new Tester(false /* allow */,
"exit" /* expectedChangeType */,
false /* expectEmbedderToGoFullscreen */);
tester.runTest();
}
embedder.test.testList = {
'testFullscreenAllow': testFullscreenAllow,
'testFullscreenDeny': testFullscreenDeny
};
chrome.test.sendMessage('Launched');
// 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.
var LOG = function(var_args) {
window.console.log.apply(window.console, arguments);
};
var initialize = function() {
var fullscreenElement = document.createElement('div');
fullscreenElement.innerText = 'Test fullscreen element';
document.body.appendChild(fullscreenElement);
document.onclick = function(e) {
LOG('document.click, requesting fullscreen');
fullscreenElement.webkitRequestFullScreen();
};
document.onwebkitfullscreenchange = function() {
var hasFullscreenElement = !!document.webkitFullscreenElement;
var isFullscreen = document.webkitIsFullScreen;
if (hasFullscreenElement != isFullscreen) {
LOG('STATUS{"isFullscreenChange": 1, "failed": true}');
} else {
if (isFullscreen) {
LOG('STATUS{"isFullscreenChange": 1, "changeType": "enter"}');
} else {
LOG('STATUS{"isFullscreenChange": 1, "changeType": "exit"}');
}
}
};
document.onwebkitfullscreenerror = function() {
LOG('STATUS{"isFullscreenChange": 1, "changeType": "exit"}');
};
};
initialize();
{
"name": "Platform App Test: <webview> fullscreen",
"description": "Loads a guest which requests fullscreen, hosting embedder does not have fullscreen permission",
"version": "1",
"permissions": [
"webview"
],
"app": {
"background": {
"scripts": ["test.js"]
}
}
}
// Copyright 2013 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.
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('embedder.html', {}, function () {});
});
<!--
* 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.
-->
<html>
<body>
<div id="webview-tag-container"></div>
<script src="embedder.js"></script>
</body>
</html>
// 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.
var embedder = {};
embedder.test = {};
embedder.test.fail = function() {
chrome.test.sendMessage('TEST_FAILED');
};
// window.* exported functions begin.
window.runTest = function(testName) {
if (!embedder.test.testList[testName]) {
console.log('Incorrect testName: ' + testName);
embedder.test.fail();
return;
}
// Run the test.
embedder.test.testList[testName]();
};
// window.* exported functions end.
var LOG = function(msg) {
window.console.log(msg);
};
function TestState(opt_guestFullscreenChangeType,
opt_didEmbedderGoFullscreen) {
this.guestFullscreenChangeType = opt_guestFullscreenChangeType || "none";
this.didEmbedderGoFullscreen = opt_didEmbedderGoFullscreen || false;
};
TestState.prototype.equals = function(other) {
return this.guestFullscreenChangeType === other.guestFullscreenChangeType &&
this.didEmbedderGoFullscreen === other.didEmbedderGoFullscreen;
};
/**
* @constructor
* @param {boolean} allowFullscreen Whether to allow fullscreen permission.
* @param {string} expectedChangeType Expected type of fullscreen change,
* can be one of "enter" or "exit".
* @param {boolean} expectEmbedderToGoFullscreen Whether or not we expect
* to see fullscreen change event on the embedder/app.
*/
function Tester(allowFullscreen,
expectedChangeType,
expectedDidEmbedderGoFullscreen) {
this.registerEventHandlers_();
this.allowFullscreen_ = allowFullscreen;
this.currentState_ = new TestState();
this.expectedState_ = new TestState(expectedChangeType,
expectedDidEmbedderGoFullscreen);
}
Tester.prototype.registerEventHandlers_ = function() {
document.onwebkitfullscreenchange = this.onFullscreenchange_.bind(this);
document.onwebkitfullscreenerror = this.onFullscreenerror_.bind(this);
};
Tester.prototype.onFullscreenchange_ = function(e) {
LOG('embedder.onFullscreenchange_');
var didEnterFullscreen = document.webkitIsFullScreen;
if (didEnterFullscreen) {
this.currentState_.didEmbedderGoFullscreen = true;
}
this.checkIfTestPassed_();
};
Tester.prototype.onFullscreenerror_ = function(e) {
LOG('embedder.onFullscreenerror_');
embedder.test.fail();
};
Tester.prototype.checkIfTestPassed_ = function() {
LOG('checkIfTestPassed_');
if (this.currentState_.equals(this.expectedState_)) {
chrome.test.sendMessage('FULLSCREEN_STEP_PASSED');
}
};
Tester.prototype.runTest = function() {
var container = document.querySelector('#webview-tag-container');
var webview = new WebView();
webview.style.width = '100px';
webview.style.height = '100px';
container.appendChild(webview);
// Setup event handlers on webview.
webview.addEventListener('loadstop', function() {
LOG('webview.loadstop');
webview.executeScript(
{file: 'guest.js'},
function(results) {
if (!results || !results.length) {
LOG('Error injecting script to webview');
embedder.test.fail();
return;
}
LOG('webview executeScript succeeded');
chrome.test.sendMessage('TEST_PASSED');
});
});
webview.addEventListener('consolemessage',
this.onGuestConsoleMessage_.bind(this));
webview.addEventListener('permissionrequest', function(e) {
if (e.permission === 'fullscreen') {
window.console.log('permissionrequest.fullscreen');
if (this.allowFullscreen_) {
e.request.allow();
} else {
e.request.deny();
}
}
}.bind(this));
// Note that we cannot use "about:blank" since fullscreen events don't
// seem to fire on webview document in that case.
webview.src = 'data:text/html,<html><body></body></html>';
};
Tester.prototype.onGuestConsoleMessage_ = function(e) {
LOG('GUEST.consolemessage: ' + e.message);
var status = this.getFullscreenStatusFromConsoleMessage_(e.message);
if (status && status.isFullscreenChange) {
if (status.failed) {
embedder.test.fail();
return;
}
this.currentState_.guestFullscreenChangeType = status.changeType;
this.checkIfTestPassed_();
}
};
Tester.prototype.getFullscreenStatusFromConsoleMessage_ = function(m) {
// status is of the following form:
// 'STATUS{
// "isFullscreenChange": true,
// "changeType": "enter" or "exit",
// failed": true/undefined
// }'.
var matches = m.match(/^STATUS(.*)/);
if (!matches) {
return null;
}
return JSON.parse(matches[1]);
};
function testFullscreenAllow() {
LOG('testFullscreenAllow');
var tester = new Tester(true /* allow */,
"enter" /* expectedChangeType */,
true /* expectEmbedderToGoFullscreen */);
tester.runTest();
}
function testFullscreenDeny() {
LOG('testFullscreenDeny');
var tester = new Tester(false /* allow */,
"exit" /* expectedChangeType */,
false /* expectEmbedderToGoFullscreen */);
tester.runTest();
}
embedder.test.testList = {
'testFullscreenAllow': testFullscreenAllow,
'testFullscreenDeny': testFullscreenDeny
};
chrome.test.sendMessage('Launched');
// 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.
var LOG = function(var_args) {
window.console.log.apply(window.console, arguments);
};
var initialize = function() {
var fullscreenElement = document.createElement('div');
fullscreenElement.innerText = 'Test fullscreen element';
document.body.appendChild(fullscreenElement);
document.onclick = function(e) {
LOG('document.click, requesting fullscreen');
fullscreenElement.webkitRequestFullScreen();
};
document.onwebkitfullscreenchange = function() {
var hasFullscreenElement = !!document.webkitFullscreenElement;
var isFullscreen = document.webkitIsFullScreen;
if (hasFullscreenElement != isFullscreen) {
LOG('STATUS{"isFullscreenChange": 1, "failed": true}');
} else {
if (isFullscreen) {
LOG('STATUS{"isFullscreenChange": 1, "changeType": "enter"}');
} else {
LOG('STATUS{"isFullscreenChange": 1, "changeType": "exit"}');
}
}
};
document.onwebkitfullscreenerror = function() {
LOG('STATUS{"isFullscreenChange": 1, "changeType": "exit"}');
};
};
initialize();
{
"name": "Platform App Test: <webview> fullscreen",
"description": "Loads a guest which requests fullscreen, the embedder has fullscreen permission",
"version": "1",
"permissions": [
"fullscreen",
"webview"
],
"app": {
"background": {
"scripts": ["test.js"]
}
}
}
// Copyright 2013 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.
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('embedder.html', {}, function () {});
});
...@@ -72,16 +72,18 @@ scoped_ptr<base::DictionaryValue> GuestViewBase::Event::GetArguments() { ...@@ -72,16 +72,18 @@ scoped_ptr<base::DictionaryValue> GuestViewBase::Event::GetArguments() {
} }
// This observer ensures that the GuestViewBase destroys itself when its // This observer ensures that the GuestViewBase destroys itself when its
// embedder goes away. // embedder goes away. It also tracks when the embedder's fullscreen is
class GuestViewBase::OwnerLifetimeObserver : public WebContentsObserver { // toggled so the guest can change itself accordingly.
class GuestViewBase::OwnerContentsObserver : public WebContentsObserver {
public: public:
OwnerLifetimeObserver(GuestViewBase* guest, OwnerContentsObserver(GuestViewBase* guest,
content::WebContents* embedder_web_contents) content::WebContents* embedder_web_contents)
: WebContentsObserver(embedder_web_contents), : WebContentsObserver(embedder_web_contents),
is_fullscreen_(false),
destroyed_(false), destroyed_(false),
guest_(guest) {} guest_(guest) {}
~OwnerLifetimeObserver() override {} ~OwnerContentsObserver() override {}
// WebContentsObserver implementation. // WebContentsObserver implementation.
void WebContentsDestroyed() override { void WebContentsDestroyed() override {
...@@ -102,7 +104,32 @@ class GuestViewBase::OwnerLifetimeObserver : public WebContentsObserver { ...@@ -102,7 +104,32 @@ class GuestViewBase::OwnerLifetimeObserver : public WebContentsObserver {
Destroy(); Destroy();
} }
void DidToggleFullscreenModeForTab(bool entered_fullscreen) override {
if (destroyed_)
return;
is_fullscreen_ = entered_fullscreen;
guest_->EmbedderFullscreenToggled(is_fullscreen_);
}
void MainFrameWasResized(bool width_changed) override {
if (destroyed_)
return;
if (!web_contents()->GetDelegate())
return;
bool current_fullscreen =
web_contents()->GetDelegate()->IsFullscreenForTabOrPending(
web_contents());
if (is_fullscreen_ && !current_fullscreen) {
is_fullscreen_ = false;
guest_->EmbedderFullscreenToggled(is_fullscreen_);
}
}
private: private:
bool is_fullscreen_;
bool destroyed_; bool destroyed_;
GuestViewBase* guest_; GuestViewBase* guest_;
...@@ -115,7 +142,7 @@ class GuestViewBase::OwnerLifetimeObserver : public WebContentsObserver { ...@@ -115,7 +142,7 @@ class GuestViewBase::OwnerLifetimeObserver : public WebContentsObserver {
guest_->Destroy(); guest_->Destroy();
} }
DISALLOW_COPY_AND_ASSIGN(OwnerLifetimeObserver); DISALLOW_COPY_AND_ASSIGN(OwnerContentsObserver);
}; };
// This observer ensures that the GuestViewBase destroys itself when its // This observer ensures that the GuestViewBase destroys itself when its
...@@ -209,8 +236,8 @@ void GuestViewBase::InitWithWebContents( ...@@ -209,8 +236,8 @@ void GuestViewBase::InitWithWebContents(
// At this point, we have just created the guest WebContents, we need to add // At this point, we have just created the guest WebContents, we need to add
// an observer to the owner WebContents. This observer will be responsible // an observer to the owner WebContents. This observer will be responsible
// for destroying the guest WebContents if the owner goes away. // for destroying the guest WebContents if the owner goes away.
owner_lifetime_observer_.reset( owner_contents_observer_.reset(
new OwnerLifetimeObserver(this, owner_web_contents_)); new OwnerContentsObserver(this, owner_web_contents_));
WebContentsObserver::Observe(guest_web_contents); WebContentsObserver::Observe(guest_web_contents);
guest_web_contents->SetDelegate(this); guest_web_contents->SetDelegate(this);
...@@ -490,12 +517,12 @@ void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents, ...@@ -490,12 +517,12 @@ void GuestViewBase::WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id, int element_instance_id,
bool is_full_page_plugin) { bool is_full_page_plugin) {
if (owner_web_contents_ != embedder_web_contents) { if (owner_web_contents_ != embedder_web_contents) {
DCHECK_EQ(owner_lifetime_observer_->web_contents(), owner_web_contents_); DCHECK_EQ(owner_contents_observer_->web_contents(), owner_web_contents_);
// Stop tracking the old embedder's zoom level. // Stop tracking the old embedder's zoom level.
StopTrackingEmbedderZoomLevel(); StopTrackingEmbedderZoomLevel();
owner_web_contents_ = embedder_web_contents; owner_web_contents_ = embedder_web_contents;
owner_lifetime_observer_.reset( owner_contents_observer_.reset(
new OwnerLifetimeObserver(this, embedder_web_contents)); new OwnerContentsObserver(this, embedder_web_contents));
} }
// Start tracking the new embedder's zoom level. // Start tracking the new embedder's zoom level.
......
...@@ -124,6 +124,12 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, ...@@ -124,6 +124,12 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
// work. // work.
virtual void GuestReady() {} virtual void GuestReady() {}
// This method is called when embedder WebContents's fullscreen is toggled.
//
// If the guest asked the embedder to enter fullscreen, the guest uses this
// signal to exit fullscreen state.
virtual void EmbedderFullscreenToggled(bool entered_fullscreen) {}
// This method is invoked when the contents auto-resized to give the container // This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes. // an opportunity to match it if it wishes.
// //
...@@ -347,7 +353,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, ...@@ -347,7 +353,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
void UpdateTargetURL(content::WebContents* source, const GURL& url) override; void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
private: private:
class OwnerLifetimeObserver; class OwnerContentsObserver;
class OpenerLifetimeObserver; class OpenerLifetimeObserver;
...@@ -414,7 +420,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate, ...@@ -414,7 +420,7 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
// This observer ensures that this guest self-destructs if the embedder goes // This observer ensures that this guest self-destructs if the embedder goes
// away. // away.
scoped_ptr<OwnerLifetimeObserver> owner_lifetime_observer_; scoped_ptr<OwnerContentsObserver> owner_contents_observer_;
// This observer ensures that if the guest is unattached and its opener goes // This observer ensures that if the guest is unattached and its opener goes
// away then this guest also self-destructs. // away then this guest also self-destructs.
......
...@@ -28,6 +28,7 @@ const char kEventContextMenu[] = "chromeWebViewInternal.contextmenu"; ...@@ -28,6 +28,7 @@ const char kEventContextMenu[] = "chromeWebViewInternal.contextmenu";
const char kEventDialog[] = "webViewInternal.onDialog"; const char kEventDialog[] = "webViewInternal.onDialog";
const char kEventDropLink[] = "webViewInternal.onDropLink"; const char kEventDropLink[] = "webViewInternal.onDropLink";
const char kEventExit[] = "webViewInternal.onExit"; const char kEventExit[] = "webViewInternal.onExit";
const char kEventExitFullscreen[] = "webViewInternal.onExitFullscreen";
const char kEventFindReply[] = "webViewInternal.onFindReply"; const char kEventFindReply[] = "webViewInternal.onFindReply";
const char kEventFrameNameChanged[] = "webViewInternal.onFrameNameChanged"; const char kEventFrameNameChanged[] = "webViewInternal.onFrameNameChanged";
const char kEventLoadAbort[] = "webViewInternal.onLoadAbort"; const char kEventLoadAbort[] = "webViewInternal.onLoadAbort";
...@@ -66,10 +67,12 @@ const char kNewURL[] = "newUrl"; ...@@ -66,10 +67,12 @@ const char kNewURL[] = "newUrl";
const char kNewWidth[] = "newWidth"; const char kNewWidth[] = "newWidth";
const char kOldHeight[] = "oldHeight"; const char kOldHeight[] = "oldHeight";
const char kOldURL[] = "oldUrl"; const char kOldURL[] = "oldUrl";
const char kOrigin[] = "origin";
const char kPermission[] = "permission"; const char kPermission[] = "permission";
const char kPermissionTypeDialog[] = "dialog"; const char kPermissionTypeDialog[] = "dialog";
const char kPermissionTypeDownload[] = "download"; const char kPermissionTypeDownload[] = "download";
const char kPermissionTypeFileSystem[] = "filesystem"; const char kPermissionTypeFileSystem[] = "filesystem";
const char kPermissionTypeFullscreen[] = "fullscreen";
const char kPermissionTypeGeolocation[] = "geolocation"; const char kPermissionTypeGeolocation[] = "geolocation";
const char kPermissionTypeLoadPlugin[] = "loadplugin"; const char kPermissionTypeLoadPlugin[] = "loadplugin";
const char kPermissionTypeMedia[] = "media"; const char kPermissionTypeMedia[] = "media";
......
...@@ -32,6 +32,7 @@ extern const char kEventContextMenu[]; ...@@ -32,6 +32,7 @@ extern const char kEventContextMenu[];
extern const char kEventDialog[]; extern const char kEventDialog[];
extern const char kEventDropLink[]; extern const char kEventDropLink[];
extern const char kEventExit[]; extern const char kEventExit[];
extern const char kEventExitFullscreen[];
extern const char kEventFindReply[]; extern const char kEventFindReply[];
extern const char kEventFrameNameChanged[]; extern const char kEventFrameNameChanged[];
extern const char kEventLoadAbort[]; extern const char kEventLoadAbort[];
...@@ -70,10 +71,12 @@ extern const char kNewURL[]; ...@@ -70,10 +71,12 @@ extern const char kNewURL[];
extern const char kNewWidth[]; extern const char kNewWidth[];
extern const char kOldHeight[]; extern const char kOldHeight[];
extern const char kOldURL[]; extern const char kOldURL[];
extern const char kOrigin[];
extern const char kPermission[]; extern const char kPermission[];
extern const char kPermissionTypeDialog[]; extern const char kPermissionTypeDialog[];
extern const char kPermissionTypeDownload[]; extern const char kPermissionTypeDownload[];
extern const char kPermissionTypeFileSystem[]; extern const char kPermissionTypeFileSystem[];
extern const char kPermissionTypeFullscreen[];
extern const char kPermissionTypeGeolocation[]; extern const char kPermissionTypeGeolocation[];
extern const char kPermissionTypeLoadPlugin[]; extern const char kPermissionTypeLoadPlugin[];
extern const char kPermissionTypeMedia[]; extern const char kPermissionTypeMedia[];
......
...@@ -321,6 +321,14 @@ void WebViewGuest::DidStopLoading() { ...@@ -321,6 +321,14 @@ void WebViewGuest::DidStopLoading() {
new GuestViewBase::Event(webview::kEventLoadStop, args.Pass())); new GuestViewBase::Event(webview::kEventLoadStop, args.Pass()));
} }
void WebViewGuest::EmbedderFullscreenToggled(bool entered_fullscreen) {
is_embedder_fullscreen_ = entered_fullscreen;
// If the embedder has got out of fullscreen, we get out of fullscreen
// mode as well.
if (!entered_fullscreen)
SetFullscreenState(false);
}
void WebViewGuest::EmbedderWillBeDestroyed() { void WebViewGuest::EmbedderWillBeDestroyed() {
// Clean up rules registries for the webview. // Clean up rules registries for the webview.
RulesRegistryService::Get(browser_context()) RulesRegistryService::Get(browser_context())
...@@ -640,6 +648,9 @@ WebViewGuest::WebViewGuest(content::WebContents* owner_web_contents) ...@@ -640,6 +648,9 @@ WebViewGuest::WebViewGuest(content::WebContents* owner_web_contents)
javascript_dialog_helper_(this), javascript_dialog_helper_(this),
current_zoom_factor_(1.0), current_zoom_factor_(1.0),
allow_scaling_(false), allow_scaling_(false),
is_guest_fullscreen_(false),
is_embedder_fullscreen_(false),
last_fullscreen_permission_was_allowed_by_embedder_(false),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
web_view_guest_delegate_.reset( web_view_guest_delegate_.reset(
ExtensionsAPIClient::Get()->CreateWebViewGuestDelegate(this)); ExtensionsAPIClient::Get()->CreateWebViewGuestDelegate(this));
...@@ -1158,6 +1169,36 @@ void WebViewGuest::WebContentsCreated(WebContents* source_contents, ...@@ -1158,6 +1169,36 @@ void WebViewGuest::WebContentsCreated(WebContents* source_contents,
std::make_pair(guest, NewWindowInfo(target_url, guest_name))); std::make_pair(guest, NewWindowInfo(target_url, guest_name)));
} }
void WebViewGuest::EnterFullscreenModeForTab(content::WebContents* web_contents,
const GURL& origin) {
// Ask the embedder for permission.
base::DictionaryValue request_info;
request_info.SetString(webview::kOrigin, origin.spec());
web_view_permission_helper_->RequestPermission(
WEB_VIEW_PERMISSION_TYPE_FULLSCREEN, request_info,
base::Bind(&WebViewGuest::OnFullscreenPermissionDecided,
weak_ptr_factory_.GetWeakPtr()),
false /* allowed_by_default */);
// TODO(lazyboy): Right now the guest immediately goes fullscreen within its
// bounds. If the embedder denies the permission then we will see a flicker.
// Once we have the ability to "cancel" a renderer/ fullscreen request:
// http://crbug.com/466854 this won't be necessary and we should be
// Calling SetFullscreenState(true) once the embedder allowed the request.
// Otherwise we would cancel renderer/ fullscreen if the embedder denied.
SetFullscreenState(true);
}
void WebViewGuest::ExitFullscreenModeForTab(
content::WebContents* web_contents) {
SetFullscreenState(false);
}
bool WebViewGuest::IsFullscreenForTabOrPending(
const content::WebContents* web_contents) const {
return is_guest_fullscreen_;
}
void WebViewGuest::LoadURLWithParams(const GURL& url, void WebViewGuest::LoadURLWithParams(const GURL& url,
const content::Referrer& referrer, const content::Referrer& referrer,
ui::PageTransition transition_type, ui::PageTransition transition_type,
...@@ -1264,4 +1305,36 @@ void WebViewGuest::OnWebViewNewWindowResponse( ...@@ -1264,4 +1305,36 @@ void WebViewGuest::OnWebViewNewWindowResponse(
guest->Destroy(); guest->Destroy();
} }
void WebViewGuest::OnFullscreenPermissionDecided(
bool allowed,
const std::string& user_input) {
last_fullscreen_permission_was_allowed_by_embedder_ = allowed;
SetFullscreenState(allowed);
}
bool WebViewGuest::GuestMadeEmbedderFullscreen() const {
return last_fullscreen_permission_was_allowed_by_embedder_ &&
is_embedder_fullscreen_;
}
void WebViewGuest::SetFullscreenState(bool is_fullscreen) {
if (is_fullscreen == is_guest_fullscreen_)
return;
bool was_fullscreen = is_guest_fullscreen_;
is_guest_fullscreen_ = is_fullscreen;
// If the embedder entered fullscreen because of us, it should exit fullscreen
// when we exit fullscreen.
if (was_fullscreen && GuestMadeEmbedderFullscreen()) {
// Dispatch a message so we can call document.webkitCancelFullscreen()
// on the embedder.
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
DispatchEventToView(
new GuestViewBase::Event(webview::kEventExitFullscreen, args.Pass()));
}
// Since we changed fullscreen state, sending a Resize message ensures that
// renderer/ sees the change.
web_contents()->GetRenderViewHost()->WasResized();
}
} // namespace extensions } // namespace extensions
...@@ -98,6 +98,7 @@ class WebViewGuest : public GuestView<WebViewGuest>, ...@@ -98,6 +98,7 @@ class WebViewGuest : public GuestView<WebViewGuest>,
void DidDropLink(const GURL& url) override; void DidDropLink(const GURL& url) override;
void DidInitialize(const base::DictionaryValue& create_params) override; void DidInitialize(const base::DictionaryValue& create_params) override;
void DidStopLoading() override; void DidStopLoading() override;
void EmbedderFullscreenToggled(bool entered_fullscreen) override;
void EmbedderWillBeDestroyed() override; void EmbedderWillBeDestroyed() override;
const char* GetAPINamespace() const override; const char* GetAPINamespace() const override;
int GetTaskPrefix() const override; int GetTaskPrefix() const override;
...@@ -164,6 +165,11 @@ class WebViewGuest : public GuestView<WebViewGuest>, ...@@ -164,6 +165,11 @@ class WebViewGuest : public GuestView<WebViewGuest>,
const base::string16& frame_name, const base::string16& frame_name,
const GURL& target_url, const GURL& target_url,
content::WebContents* new_contents) override; content::WebContents* new_contents) override;
void EnterFullscreenModeForTab(content::WebContents* web_contents,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* web_contents) const override;
// NotificationObserver implementation. // NotificationObserver implementation.
void Observe(int type, void Observe(int type,
...@@ -250,6 +256,11 @@ class WebViewGuest : public GuestView<WebViewGuest>, ...@@ -250,6 +256,11 @@ class WebViewGuest : public GuestView<WebViewGuest>,
bool allow, bool allow,
const std::string& user_input); const std::string& user_input);
void OnFullscreenPermissionDecided(bool allowed,
const std::string& user_input);
bool GuestMadeEmbedderFullscreen() const;
void SetFullscreenState(bool is_fullscreen);
// WebContentsObserver implementation. // WebContentsObserver implementation.
void DidCommitProvisionalLoadForFrame( void DidCommitProvisionalLoadForFrame(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
...@@ -369,6 +380,9 @@ class WebViewGuest : public GuestView<WebViewGuest>, ...@@ -369,6 +380,9 @@ class WebViewGuest : public GuestView<WebViewGuest>,
// Determines if this guest accepts pinch-zoom gestures. // Determines if this guest accepts pinch-zoom gestures.
bool allow_scaling_; bool allow_scaling_;
bool is_guest_fullscreen_;
bool is_embedder_fullscreen_;
bool last_fullscreen_permission_was_allowed_by_embedder_;
// This is used to ensure pending tasks will not fire after this object is // This is used to ensure pending tasks will not fire after this object is
// destroyed. // destroyed.
......
...@@ -25,6 +25,8 @@ static std::string PermissionTypeToString(WebViewPermissionType type) { ...@@ -25,6 +25,8 @@ static std::string PermissionTypeToString(WebViewPermissionType type) {
return webview::kPermissionTypeDownload; return webview::kPermissionTypeDownload;
case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM: case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
return webview::kPermissionTypeFileSystem; return webview::kPermissionTypeFileSystem;
case WEB_VIEW_PERMISSION_TYPE_FULLSCREEN:
return webview::kPermissionTypeFullscreen;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION: case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
return webview::kPermissionTypeGeolocation; return webview::kPermissionTypeGeolocation;
case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG: case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
...@@ -61,6 +63,10 @@ void RecordUserInitiatedUMA( ...@@ -61,6 +63,10 @@ void RecordUserInitiatedUMA(
content::RecordAction( content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.FileSystem")); UserMetricsAction("WebView.PermissionAllow.FileSystem"));
break; break;
case WEB_VIEW_PERMISSION_TYPE_FULLSCREEN:
content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Fullscreen"));
break;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION: case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
content::RecordAction( content::RecordAction(
UserMetricsAction("WebView.PermissionAllow.Geolocation")); UserMetricsAction("WebView.PermissionAllow.Geolocation"));
...@@ -97,6 +103,10 @@ void RecordUserInitiatedUMA( ...@@ -97,6 +103,10 @@ void RecordUserInitiatedUMA(
content::RecordAction( content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.FileSystem")); UserMetricsAction("WebView.PermissionDeny.FileSystem"));
break; break;
case WEB_VIEW_PERMISSION_TYPE_FULLSCREEN:
content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Fullscreen"));
break;
case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION: case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
content::RecordAction( content::RecordAction(
UserMetricsAction("WebView.PermissionDeny.Geolocation")); UserMetricsAction("WebView.PermissionDeny.Geolocation"));
......
...@@ -13,6 +13,9 @@ enum WebViewPermissionType { ...@@ -13,6 +13,9 @@ enum WebViewPermissionType {
WEB_VIEW_PERMISSION_TYPE_FILESYSTEM, WEB_VIEW_PERMISSION_TYPE_FILESYSTEM,
// html5 fullscreen permission.
WEB_VIEW_PERMISSION_TYPE_FULLSCREEN,
WEB_VIEW_PERMISSION_TYPE_GEOLOCATION, WEB_VIEW_PERMISSION_TYPE_GEOLOCATION,
// JavaScript Dialogs: prompt, alert, confirm // JavaScript Dialogs: prompt, alert, confirm
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "extensions/renderer/guest_view/extensions_guest_view_container.h" #include "extensions/renderer/guest_view/extensions_guest_view_container.h"
#include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context.h"
#include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
...@@ -43,6 +44,10 @@ GuestViewInternalCustomBindings::GuestViewInternalCustomBindings( ...@@ -43,6 +44,10 @@ GuestViewInternalCustomBindings::GuestViewInternalCustomBindings(
base::Bind( base::Bind(
&GuestViewInternalCustomBindings::RegisterElementResizeCallback, &GuestViewInternalCustomBindings::RegisterElementResizeCallback,
base::Unretained(this))); base::Unretained(this)));
RouteFunction(
"RunWithGesture",
base::Bind(&GuestViewInternalCustomBindings::RunWithGesture,
base::Unretained(this)));
} }
void GuestViewInternalCustomBindings::AttachGuest( void GuestViewInternalCustomBindings::AttachGuest(
...@@ -198,4 +203,14 @@ void GuestViewInternalCustomBindings::RegisterElementResizeCallback( ...@@ -198,4 +203,14 @@ void GuestViewInternalCustomBindings::RegisterElementResizeCallback(
args.GetReturnValue().Set(v8::Boolean::New(context()->isolate(), true)); args.GetReturnValue().Set(v8::Boolean::New(context()->isolate(), true));
} }
void GuestViewInternalCustomBindings::RunWithGesture(
const v8::FunctionCallbackInfo<v8::Value>& args) {
// Gesture is required to request fullscreen.
blink::WebScopedUserGesture user_gesture;
CHECK_EQ(args.Length(), 1);
CHECK(args[0]->IsFunction());
v8::Handle<v8::Value> no_args;
context()->CallFunction(v8::Handle<v8::Function>::Cast(args[0]), 0, &no_args);
}
} // namespace extensions } // namespace extensions
...@@ -55,6 +55,16 @@ class GuestViewInternalCustomBindings : public ObjectBackedNativeHandler { ...@@ -55,6 +55,16 @@ class GuestViewInternalCustomBindings : public ObjectBackedNativeHandler {
// a single parameter, |callback|. // a single parameter, |callback|.
void RegisterElementResizeCallback( void RegisterElementResizeCallback(
const v8::FunctionCallbackInfo<v8::Value>& args); const v8::FunctionCallbackInfo<v8::Value>& args);
// Runs a JavaScript function with user gesture.
//
// This is used to request webview element to enter fullscreen (from the
// embedder).
// Note that the guest requesting fullscreen means it has already been
// triggered by a user gesture and we get to this point if embedder allows
// the fullscreen request to proceed.
void RunWithGesture(
const v8::FunctionCallbackInfo<v8::Value>& args);
}; };
} // namespace extensions } // namespace extensions
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
var DocumentNatives = requireNative('document_natives'); var DocumentNatives = requireNative('document_natives');
var GuestView = require('guestView').GuestView; var GuestView = require('guestView').GuestView;
var GuestViewContainer = require('guestViewContainer').GuestViewContainer; var GuestViewContainer = require('guestViewContainer').GuestViewContainer;
var GuestViewInternalNatives = requireNative('guest_view_internal');
var WebViewConstants = require('webViewConstants').WebViewConstants; var WebViewConstants = require('webViewConstants').WebViewConstants;
var WebViewEvents = require('webViewEvents').WebViewEvents; var WebViewEvents = require('webViewEvents').WebViewEvents;
var WebViewInternal = require('webViewInternal').WebViewInternal; var WebViewInternal = require('webViewInternal').WebViewInternal;
...@@ -216,6 +217,13 @@ WebViewImpl.prototype.executeCode = function(func, args) { ...@@ -216,6 +217,13 @@ WebViewImpl.prototype.executeCode = function(func, args) {
return true; return true;
} }
// Requests the <webview> element wihtin the embedder to enter fullscreen.
WebViewImpl.prototype.makeElementFullscreen = function() {
GuestViewInternalNatives.RunWithGesture(function() {
this.element.webkitRequestFullScreen();
}.bind(this));
};
// Implemented when the ChromeWebView API is available. // Implemented when the ChromeWebView API is available.
WebViewImpl.prototype.maybeSetupContextMenus = function() {}; WebViewImpl.prototype.maybeSetupContextMenus = function() {};
......
...@@ -14,7 +14,8 @@ var PERMISSION_TYPES = ['media', ...@@ -14,7 +14,8 @@ var PERMISSION_TYPES = ['media',
'pointerLock', 'pointerLock',
'download', 'download',
'loadplugin', 'loadplugin',
'filesystem']; 'filesystem',
'fullscreen'];
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// WebViewActionRequest object. // WebViewActionRequest object.
...@@ -250,11 +251,38 @@ PermissionRequest.prototype.WARNING_MSG_REQUEST_BLOCKED = ...@@ -250,11 +251,38 @@ PermissionRequest.prototype.WARNING_MSG_REQUEST_BLOCKED =
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// FullscreenPermissionRequest object.
// Represents a fullscreen permission request.
function FullscreenPermissionRequest(webViewImpl, event, webViewEvent) {
PermissionRequest.call(this, webViewImpl, event, webViewEvent);
}
FullscreenPermissionRequest.prototype.__proto__ = PermissionRequest.prototype;
FullscreenPermissionRequest.prototype.getInterfaceObject = function() {
return {
allow: function() {
this.validateCall();
WebViewInternal.setPermission(
this.guestInstanceId, this.requestId, 'allow');
// Now make the <webview> element go fullscreen.
this.webViewImpl.makeElementFullscreen();
}.bind(this),
deny: function() {
this.validateCall();
WebViewInternal.setPermission(
this.guestInstanceId, this.requestId, 'deny');
}.bind(this)
};
};
var WebViewActionRequests = { var WebViewActionRequests = {
WebViewActionRequest: WebViewActionRequest, WebViewActionRequest: WebViewActionRequest,
Dialog: Dialog, Dialog: Dialog,
NewWindow: NewWindow, NewWindow: NewWindow,
PermissionRequest: PermissionRequest PermissionRequest: PermissionRequest,
FullscreenPermissionRequest: FullscreenPermissionRequest
}; };
exports.WebViewActionRequests = WebViewActionRequests; exports.WebViewActionRequests = WebViewActionRequests;
...@@ -55,6 +55,12 @@ WebViewEvents.EVENTS = { ...@@ -55,6 +55,12 @@ WebViewEvents.EVENTS = {
evt: CreateEvent('webViewInternal.onExit'), evt: CreateEvent('webViewInternal.onExit'),
fields: ['processId', 'reason'] fields: ['processId', 'reason']
}, },
'exitfullscreen': {
evt: CreateEvent('webViewInternal.onExitFullscreen'),
fields: ['url'],
handler: 'handleFullscreenExitEvent',
internal: true
},
'findupdate': { 'findupdate': {
evt: CreateEvent('webViewInternal.onFindReply'), evt: CreateEvent('webViewInternal.onFindReply'),
fields: [ fields: [
...@@ -219,6 +225,10 @@ WebViewEvents.prototype.handleFrameNameChangedEvent = function(event) { ...@@ -219,6 +225,10 @@ WebViewEvents.prototype.handleFrameNameChangedEvent = function(event) {
this.view.onFrameNameChanged(event.name); this.view.onFrameNameChanged(event.name);
}; };
WebViewEvents.prototype.handleFullscreenExitEvent = function(event, eventName) {
document.webkitCancelFullScreen();
};
WebViewEvents.prototype.handleLoadAbortEvent = function(event, eventName) { WebViewEvents.prototype.handleLoadAbortEvent = function(event, eventName) {
var showWarningMessage = function(reason) { var showWarningMessage = function(reason) {
var WARNING_MSG_LOAD_ABORTED = '<webview>: ' + var WARNING_MSG_LOAD_ABORTED = '<webview>: ' +
...@@ -249,7 +259,12 @@ WebViewEvents.prototype.handleNewWindowEvent = function(event, eventName) { ...@@ -249,7 +259,12 @@ WebViewEvents.prototype.handleNewWindowEvent = function(event, eventName) {
WebViewEvents.prototype.handlePermissionEvent = function(event, eventName) { WebViewEvents.prototype.handlePermissionEvent = function(event, eventName) {
var webViewEvent = this.makeDomEvent(event, eventName); var webViewEvent = this.makeDomEvent(event, eventName);
new WebViewActionRequests.PermissionRequest(this.view, event, webViewEvent); if (event.permission === 'fullscreen') {
new WebViewActionRequests.FullscreenPermissionRequest(
this.view, event, webViewEvent);
} else {
new WebViewActionRequests.PermissionRequest(this.view, event, webViewEvent);
}
}; };
WebViewEvents.prototype.handleSizeChangedEvent = function(event, eventName) { WebViewEvents.prototype.handleSizeChangedEvent = function(event, eventName) {
......
...@@ -11729,6 +11729,14 @@ should be able to be added at any place in this file. ...@@ -11729,6 +11729,14 @@ should be able to be added at any place in this file.
</description> </description>
</action> </action>
<action name="WebView.PermissionAllow.Fullscreen">
<owner>fsamuel@chromium.org</owner>
<owner>lazyboy@chromium.org</owner>
<description>
Tracks when the fullscreen permission is explicitly allowed on a webview.
</description>
</action>
<action name="WebView.PermissionAllow.Geolocation"> <action name="WebView.PermissionAllow.Geolocation">
<owner>fsamuel@chromium.org</owner> <owner>fsamuel@chromium.org</owner>
<owner>lazyboy@chromium.org</owner> <owner>lazyboy@chromium.org</owner>
...@@ -11777,6 +11785,14 @@ should be able to be added at any place in this file. ...@@ -11777,6 +11785,14 @@ should be able to be added at any place in this file.
</description> </description>
</action> </action>
<action name="WebView.PermissionDeny.Fullscreen">
<owner>fsamuel@chromium.org</owner>
<owner>lazyboy@chromium.org</owner>
<description>
Tracks when the fullscreen permission is explicitly denied on a webview.
</description>
</action>
<action name="WebView.PermissionDeny.Geolocation"> <action name="WebView.PermissionDeny.Geolocation">
<owner>fsamuel@chromium.org</owner> <owner>fsamuel@chromium.org</owner>
<owner>lazyboy@chromium.org</owner> <owner>lazyboy@chromium.org</owner>
......
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