summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlazyboy@chromium.org <lazyboy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-09 01:32:49 +0000
committerlazyboy@chromium.org <lazyboy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-09 01:32:49 +0000
commite4a55a597c2d3ad0e7b1fad022c510452171a248 (patch)
treef6f68d9a59401c2cdcfa6fa51ed2f8a72502a4e7
parenteba66b0c2f522302638803d3c04827b901c95ba5 (diff)
downloadchromium_src-e4a55a597c2d3ad0e7b1fad022c510452171a248.zip
chromium_src-e4a55a597c2d3ad0e7b1fad022c510452171a248.tar.gz
chromium_src-e4a55a597c2d3ad0e7b1fad022c510452171a248.tar.bz2
<browser>: permissionRequest API for geolocation.
BUG=141195 TEST=Added browsertests: WebViewTest.GeolocationAPI* Review URL: https://chromiumcodereview.appspot.com/11142012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187099 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/web_view_browsertest.cc29
-rw-r--r--chrome/renderer/resources/extensions/web_view_experimental.js2
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.html11
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.js107
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/manifest.json13
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/test.js7
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.html11
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.js112
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/manifest.json14
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/test.js7
-rw-r--r--chrome/test/data/extensions/platform_apps/web_view/geolocation/geolocation_access_guest.html55
-rw-r--r--content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc95
-rw-r--r--content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h44
-rw-r--r--content/browser/browser_plugin/browser_plugin_guest.cc82
-rw-r--r--content/browser/browser_plugin/browser_plugin_guest.h18
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc10
-rw-r--r--content/common/browser_plugin/browser_plugin_constants.cc1
-rw-r--r--content/common/browser_plugin/browser_plugin_constants.h1
-rw-r--r--content/common/browser_plugin/browser_plugin_message_enums.h3
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/renderer/browser_plugin/browser_plugin.cc10
21 files changed, 624 insertions, 10 deletions
diff --git a/chrome/browser/extensions/web_view_browsertest.cc b/chrome/browser/extensions/web_view_browsertest.cc
index fb4e900..93fe133 100644
--- a/chrome/browser/extensions/web_view_browsertest.cc
+++ b/chrome/browser/extensions/web_view_browsertest.cc
@@ -97,6 +97,16 @@ class WebViewTest : public extensions::PlatformAppBrowserTest {
extensions::PlatformAppBrowserTest::TearDown();
}
+ virtual void SetUpOnMainThread() OVERRIDE {
+ const testing::TestInfo* const test_info =
+ testing::UnitTest::GetInstance()->current_test_info();
+ // Mock out geolocation for geolocation specific tests.
+ if (!strncmp(test_info->name(), "GeolocationAPI",
+ strlen("GeolocationAPI"))) {
+ ui_test_utils::OverrideGeolocation(10, 20);
+ }
+ }
+
// This method is responsible for initializing a packaged app, which contains
// multiple webview tags. The tags have different partition identifiers and
// their WebContent objects are returned as output. The method also verifies
@@ -817,3 +827,22 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, TearDownTest) {
LoadAndLaunchPlatformApp("web_view/teardown");
ASSERT_TRUE(second_loaded_listener.WaitUntilSatisfied());
}
+
+// Embedder does not have geolocation permission for this test.
+// No matter what the API does, geolocation permission would be denied.
+// Note that the test name prefix must be "GeolocationAPI".
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasNoAccess) {
+ ASSERT_TRUE(StartTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTest(
+ "platform_apps/web_view/geolocation/embedder_has_no_permission"))
+ << message_;
+}
+
+// Embedder has geolocation permission for this test.
+// Note that the test name prefix must be "GeolocationAPI".
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasAccess) {
+ ASSERT_TRUE(StartTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTest(
+ "platform_apps/web_view/geolocation/embedder_has_permission"))
+ << message_;
+}
diff --git a/chrome/renderer/resources/extensions/web_view_experimental.js b/chrome/renderer/resources/extensions/web_view_experimental.js
index 4681e24..2b75e38 100644
--- a/chrome/renderer/resources/extensions/web_view_experimental.js
+++ b/chrome/renderer/resources/extensions/web_view_experimental.js
@@ -14,7 +14,7 @@
var WebView = require('webview').WebView;
/** @type {Array.<string>} */
-var PERMISSION_TYPES = ['media'];
+var PERMISSION_TYPES = ['media', 'geolocation'];
/** @type {string} */
var ERROR_MSG_PERMISSION_ALREADY_DECIDED = '<webview>: ' +
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.html b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.html
new file mode 100644
index 0000000..d350e46
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.html
@@ -0,0 +1,11 @@
+<!--
+ * 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.
+-->
+<html>
+<body>
+ <div id="webview-tag-container"></div>
+ <script src="embedder.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.js
new file mode 100644
index 0000000..9b24fd3
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/embedder.js
@@ -0,0 +1,107 @@
+// 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.
+
+var embedder = {};
+embedder.tests = {};
+embedder.baseGuestURL = '';
+embedder.guestURL = '';
+
+embedder.setUp = function(config) {
+ embedder.baseGuestURL = 'http://localhost:' + config.testServer.port;
+ embedder.guestURL = embedder.baseGuestURL +
+ '/files/extensions/platform_apps/web_view/geolocation' +
+ '/geolocation_access_guest.html';
+ chrome.test.log('Guest url is: ' + embedder.guestURL);
+};
+
+/** @private */
+embedder.setUpGuest_ = function() {
+ document.querySelector('#webview-tag-container').innerHTML =
+ '<webview style="width: 100px; height: 100px;"' +
+ ' src="' + embedder.guestURL + '"' +
+ '></webview>';
+ var webview = document.querySelector('webview');
+ if (!webview) {
+ chrome.test.fail('No <webview> element created');
+ }
+ return webview;
+};
+
+/** @private */
+embedder.setUpLoadStop_ = function(webview, testName) {
+ var onWebViewLoadStop = function(e) {
+ // Send post message to <webview> when it's ready to receive them.
+ webview.contentWindow.postMessage(
+ JSON.stringify(['check-geolocation-permission', '' + testName]), '*');
+ };
+ webview.addEventListener('loadstop', onWebViewLoadStop);
+};
+
+/** @private */
+embedder.registerAndWaitForPostMessage_ = function(
+ webview, expectedData) {
+ var testName = expectedData[0];
+ var onPostMessageReceived = function(e) {
+ var data = JSON.parse(e.data);
+ if (data[0] == '' + testName) {
+ chrome.test.assertEq(expectedData, data);
+ chrome.test.succeed();
+ }
+ };
+ window.addEventListener('message', onPostMessageReceived);
+};
+
+/** @private */
+embedder.assertCorrectEvent_ = function(e) {
+ chrome.test.assertEq('geolocation', e.permission);
+ chrome.test.assertTrue(!!e.url);
+ chrome.test.assertTrue(e.url.indexOf(embedder.baseGuestURL) == 0);
+};
+
+// Tests begin.
+
+// Embedder does not have geolocation permission, so geolocation access is
+// always denied for these tests.
+
+// Calling deny() results in deny.
+embedder.tests.testDenyDenies = function testDenyDenies() {
+ var webview = embedder.setUpGuest_();
+
+ var onPermissionRequest = function(e) {
+ chrome.test.log('Embedder notified on permissionRequest');
+ embedder.assertCorrectEvent_(e);
+ e.request.deny();
+ };
+ webview.addEventListener('permissionrequest', onPermissionRequest);
+
+ embedder.setUpLoadStop_(webview, 'test1');
+ embedder.registerAndWaitForPostMessage_(
+ webview, ['test1', 'access-denied']);
+};
+
+// Calling allow() results in deny too.
+embedder.tests.testAllowDenies = function testAllowDenies() {
+ var webview = embedder.setUpGuest_();
+
+ var onPermissionRequest = function(e) {
+ chrome.test.log('Embedder notified on permissionRequest');
+ embedder.assertCorrectEvent_(e);
+ e.request.allow();
+ };
+ webview.addEventListener('permissionrequest', onPermissionRequest);
+
+ embedder.setUpLoadStop_(webview, 'test2');
+ embedder.registerAndWaitForPostMessage_(
+ webview, ['test2', 'access-denied']);
+};
+
+onload = function() {
+ chrome.test.getConfig(function(config) {
+ embedder.setUp(config);
+ chrome.test.runTests([
+ embedder.tests.testDenyDenies,
+ embedder.tests.testAllowDenies
+ ]);
+ });
+};
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/manifest.json
new file mode 100644
index 0000000..c30ec57
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "Platform App Test: <webview> geolocation",
+ "description": "Loads a guest which requests geolocation",
+ "version": "1",
+ "permissions": [
+ "webview"
+ ],
+ "app": {
+ "background": {
+ "scripts": ["test.js"]
+ }
+ }
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/test.js b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/test.js
new file mode 100644
index 0000000..1886432
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_no_permission/test.js
@@ -0,0 +1,7 @@
+// 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 () {});
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.html b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.html
new file mode 100644
index 0000000..d350e46
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.html
@@ -0,0 +1,11 @@
+<!--
+ * 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.
+-->
+<html>
+<body>
+ <div id="webview-tag-container"></div>
+ <script src="embedder.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.js
new file mode 100644
index 0000000..5fa91c4
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/embedder.js
@@ -0,0 +1,112 @@
+// 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.
+
+var embedder = {};
+embedder.tests = {};
+embedder.baseGuestURL = '';
+embedder.guestURL = '';
+
+embedder.setUp = function(config) {
+ embedder.baseGuestURL = 'http://localhost:' + config.testServer.port;
+ embedder.guestURL = embedder.baseGuestURL +
+ '/files/extensions/platform_apps/web_view/geolocation' +
+ '/geolocation_access_guest.html';
+ chrome.test.log('Guest url is: ' + embedder.guestURL);
+};
+
+/** @private */
+embedder.setUpGuest_ = function() {
+ document.querySelector('#webview-tag-container').innerHTML =
+ '<webview style="width: 100px; height: 100px;"' +
+ ' src="' + embedder.guestURL + '"' +
+ '></webview>';
+ var webview = document.querySelector('webview');
+ if (!webview) {
+ chrome.test.fail('No <webview> element created');
+ }
+ return webview;
+};
+
+/** @private */
+embedder.setUpLoadStop_ = function(webview, testName) {
+ var onWebViewLoadStop = function(e) {
+ // Send post message to <webview> when it's ready to receive them.
+ webview.contentWindow.postMessage(
+ JSON.stringify(['check-geolocation-permission', '' + testName]), '*');
+ };
+ webview.addEventListener('loadstop', onWebViewLoadStop);
+};
+
+/** @private */
+embedder.registerAndWaitForPostMessage_ = function(
+ webview, expectedData) {
+ var testName = expectedData[0];
+ var onPostMessageReceived = function(e) {
+ var data = JSON.parse(e.data);
+ if (data[0] == '' + testName) {
+ chrome.test.assertEq(expectedData, data);
+ chrome.test.succeed();
+ }
+ };
+ window.addEventListener('message', onPostMessageReceived);
+};
+
+/** @private */
+embedder.assertCorrectEvent_ = function(e) {
+ chrome.test.assertEq('geolocation', e.permission);
+ chrome.test.assertTrue(!!e.url);
+ chrome.test.assertTrue(e.url.indexOf(embedder.baseGuestURL) == 0);
+};
+
+// Tests begin.
+
+// Once the guest is allowed or denied geolocation, the guest notifies the
+// embedder about the fact via post message.
+// The embedder has to initiate a post message so that the guest can get a
+// reference to embedder to send the reply back.
+
+// Loads a guest which requests geolocation. The embedder (platform app) has
+// acccess to geolocation and allows geolocation for the guest.
+embedder.tests.testAllow = function testAllow() {
+ var webview = embedder.setUpGuest_();
+
+ var onPermissionRequest = function(e) {
+ chrome.test.log('Embedder notified on permissionRequest');
+ embedder.assertCorrectEvent_(e);
+ e.request.allow();
+ };
+ webview.addEventListener('permissionrequest', onPermissionRequest);
+
+ embedder.setUpLoadStop_(webview, 'test1');
+ // WebViewTest sets (mock) lat, lng to 10, 20.
+ embedder.registerAndWaitForPostMessage_(
+ webview, ['test1', 'access-granted', 10, 20]);
+};
+
+// Loads a guest which requests geolocation. The embedder (platform app) has
+// acccess to geolocation, but denies geolocation for the guest.
+embedder.tests.testDeny = function testDeny() {
+ var webview = embedder.setUpGuest_();
+
+ var onPermissionRequest = function(e) {
+ chrome.test.log('Embedder notified on permissionRequest');
+ embedder.assertCorrectEvent_(e);
+ e.request.deny();
+ };
+ webview.addEventListener('permissionrequest', onPermissionRequest);
+
+ embedder.setUpLoadStop_(webview, 'test2');
+ embedder.registerAndWaitForPostMessage_(
+ webview, ['test2', 'access-denied']);
+};
+
+onload = function() {
+ chrome.test.getConfig(function(config) {
+ embedder.setUp(config);
+ chrome.test.runTests([
+ embedder.tests.testAllow,
+ embedder.tests.testDeny
+ ]);
+ });
+};
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/manifest.json
new file mode 100644
index 0000000..74ad74a
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/manifest.json
@@ -0,0 +1,14 @@
+{
+ "name": "Platform App Test: <webview> geolocation",
+ "description": "Loads a guest which requests geolocation",
+ "version": "1",
+ "permissions": [
+ "geolocation",
+ "webview"
+ ],
+ "app": {
+ "background": {
+ "scripts": ["test.js"]
+ }
+ }
+}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/test.js b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/test.js
new file mode 100644
index 0000000..1886432
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/embedder_has_permission/test.js
@@ -0,0 +1,7 @@
+// 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 () {});
+});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/geolocation/geolocation_access_guest.html b/chrome/test/data/extensions/platform_apps/web_view/geolocation/geolocation_access_guest.html
new file mode 100644
index 0000000..05c42bd
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/geolocation/geolocation_access_guest.html
@@ -0,0 +1,55 @@
+<!--
+ * 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.
+-->
+<html>
+ <head>
+ <script type="text/javascript">
+ // A guest that requests geolocation.
+ // Notifies the embedder about the result of the request (success/fail)
+ // via post message. Note that the embedder has to initiate a postMessage
+ // first so that guest has a reference to the embedder's window.
+
+ // The window reference of the embedder to send post message reply.
+ var embedderWindowChannel = null;
+
+ var notifyEmbedder = function(msg_array) {
+ embedderWindowChannel.postMessage(JSON.stringify(msg_array), '*');
+ };
+
+ var onGeolocationSuccess = function(testName, position) {
+ window.console.log('onGeolocationSuccess callback.');
+ var latitude = position.coords.latitude;
+ var longitude = position.coords.longitude;
+ notifyEmbedder([testName, 'access-granted', latitude, longitude]);
+ };
+
+ var onGeolocationFailure = function(testName, err) {
+ window.console.log('onGeolocationFailure callback.');
+ notifyEmbedder([testName, 'access-denied']);
+ };
+
+ var startTest = function(testName) {
+ navigator.geolocation.getCurrentPosition(
+ onGeolocationSuccess.bind(this, testName),
+ onGeolocationFailure.bind(this, testName));
+ };
+
+ var onPostMessageReceived = function(e) {
+ var data = JSON.parse(e.data);
+ if (data[0] == 'check-geolocation-permission') {
+ var testName = data[1];
+ embedderWindowChannel = e.source;
+ // Start the test once we have |embedderWindowChannel|.
+ startTest(testName);
+ }
+ };
+
+ window.addEventListener('message', onPostMessageReceived, false);
+ </script>
+ </head>
+ <body>
+ <div>This is a guest that requests geolocation.</div>
+ </body>
+</html>
diff --git a/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc b/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc
new file mode 100644
index 0000000..59a23b5
--- /dev/null
+++ b/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc
@@ -0,0 +1,95 @@
+// 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.
+
+#include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
+
+#include "base/bind.h"
+#include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+
+namespace content {
+
+BrowserPluginGeolocationPermissionContext::
+ BrowserPluginGeolocationPermissionContext() {
+}
+
+BrowserPluginGeolocationPermissionContext::
+ ~BrowserPluginGeolocationPermissionContext() {
+}
+
+void BrowserPluginGeolocationPermissionContext::RequestGeolocationPermission(
+ int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame,
+ base::Callback<void(bool)> callback) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &BrowserPluginGeolocationPermissionContext::
+ RequestGeolocationPermission,
+ this,
+ render_process_id,
+ render_view_id,
+ bridge_id,
+ requesting_frame,
+ callback));
+ return;
+ }
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Note that callback.Run(true) allows geolocation access, callback.Run(false)
+ // denies geolocation access.
+ // We need to go to the renderer to ask embedder's js if we are allowed to
+ // have geolocation access.
+ RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
+ render_view_id);
+ DCHECK(rvh);
+ if (rvh) {
+ DCHECK(rvh->GetProcess()->IsGuest());
+ WebContentsImpl* guest_web_contents =
+ static_cast<WebContentsImpl*>(rvh->GetDelegate()->GetAsWebContents());
+ BrowserPluginGuest* guest = guest_web_contents->GetBrowserPluginGuest();
+ guest->AskEmbedderForGeolocationPermission(bridge_id,
+ requesting_frame,
+ callback);
+ }
+}
+
+void BrowserPluginGeolocationPermissionContext::
+ CancelGeolocationPermissionRequest(int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &BrowserPluginGeolocationPermissionContext::
+ CancelGeolocationPermissionRequest,
+ this,
+ render_process_id,
+ render_view_id,
+ bridge_id,
+ requesting_frame));
+ return;
+ }
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
+ render_view_id);
+ if (rvh) {
+ DCHECK(rvh->GetProcess()->IsGuest());
+ WebContentsImpl* guest_web_contents =
+ static_cast<WebContentsImpl*>(rvh->GetDelegate()->GetAsWebContents());
+ BrowserPluginGuest* guest = guest_web_contents->GetBrowserPluginGuest();
+ if (guest)
+ guest->CancelGeolocationRequest(bridge_id);
+ }
+}
+
+} // namespace content
diff --git a/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h b/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h
new file mode 100644
index 0000000..27cc9e3
--- /dev/null
+++ b/content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GEOLOCATION_PERMISSION_CONTEXT_H_
+#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GEOLOCATION_PERMISSION_CONTEXT_H_
+
+#include "content/public/browser/geolocation_permission_context.h"
+
+namespace content {
+
+// Browser plugin specific implementation of GeolocationPermissionContext.
+// It manages Geolocation permissions flow for BrowserPluginGuest. When a guest
+// requests gelocation permission, it delegates the request to embedder though
+// embedder's javascript api.
+// This runs on the I/O thread. We have to return to UI thread to talk to a
+// BrowserPluginGuest.
+class BrowserPluginGeolocationPermissionContext :
+ public GeolocationPermissionContext {
+ public:
+ BrowserPluginGeolocationPermissionContext();
+
+ // GeolocationPermissionContext implementation:
+ virtual void RequestGeolocationPermission(
+ int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame,
+ base::Callback<void(bool)> callback) OVERRIDE;
+ virtual void CancelGeolocationPermissionRequest(
+ int render_process_id,
+ int render_view_id,
+ int bridge_id,
+ const GURL& requesting_frame) OVERRIDE;
+
+ private:
+ virtual ~BrowserPluginGeolocationPermissionContext();
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserPluginGeolocationPermissionContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GEOLOCATION_PERMISSION_CONTEXT_H_
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 962a931..8a9b3e1 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -25,6 +25,7 @@
#include "content/port/browser/render_view_host_delegate_view.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/geolocation_permission_context.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
@@ -50,7 +51,7 @@ namespace content {
BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL;
namespace {
-const size_t kNumMaxOutstandingMediaRequests = 1024;
+const size_t kNumMaxOutstandingPermissionRequests = 1024;
}
BrowserPluginGuest::BrowserPluginGuest(
@@ -58,6 +59,7 @@ BrowserPluginGuest::BrowserPluginGuest(
WebContentsImpl* web_contents,
const BrowserPluginHostMsg_CreateGuest_Params& params)
: WebContentsObserver(web_contents),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
embedder_web_contents_(NULL),
instance_id_(instance_id),
damage_buffer_sequence_id_(0),
@@ -376,6 +378,45 @@ void BrowserPluginGuest::LoadRedirect(
is_top_level));
}
+void BrowserPluginGuest::AskEmbedderForGeolocationPermission(
+ int bridge_id,
+ const GURL& requesting_frame,
+ GeolocationCallback callback) {
+ if (geolocation_request_callback_map_.size() >=
+ kNumMaxOutstandingPermissionRequests) {
+ // Deny the geolocation request.
+ callback.Run(false);
+ return;
+ }
+ int request_id = next_permission_request_id_++;
+ geolocation_request_callback_map_[request_id] = callback;
+
+ base::DictionaryValue request_info;
+ request_info.Set(browser_plugin::kURL,
+ base::Value::CreateStringValue(requesting_frame.spec()));
+
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_RequestPermission(instance_id(),
+ BrowserPluginPermissionTypeGeolocation, request_id, request_info));
+}
+
+void BrowserPluginGuest::CancelGeolocationRequest(int bridge_id) {
+ GeolocationRequestsMap::iterator callback_iter =
+ geolocation_request_callback_map_.find(bridge_id);
+ if (callback_iter != geolocation_request_callback_map_.end())
+ geolocation_request_callback_map_.erase(callback_iter);
+}
+
+void BrowserPluginGuest::SetGeolocationPermission(int request_id,
+ bool allowed) {
+ GeolocationRequestsMap::iterator callback_iter =
+ geolocation_request_callback_map_.find(request_id);
+ if (callback_iter != geolocation_request_callback_map_.end()) {
+ callback_iter->second.Run(allowed);
+ geolocation_request_callback_map_.erase(callback_iter);
+ }
+}
+
void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
int64 frame_id,
bool is_main_frame,
@@ -697,11 +738,14 @@ void BrowserPluginGuest::OnStop(int instance_id) {
}
void BrowserPluginGuest::OnRespondPermission(
- int /*instance_id*/,
+ int instance_id,
BrowserPluginPermissionType permission_type,
int request_id,
bool should_allow) {
switch (permission_type) {
+ case BrowserPluginPermissionTypeGeolocation:
+ OnRespondPermissionGeolocation(request_id, should_allow);
+ break;
case BrowserPluginPermissionTypeMedia:
OnRespondPermissionMedia(request_id, should_allow);
break;
@@ -842,7 +886,7 @@ void BrowserPluginGuest::RequestMediaAccessPermission(
WebContents* web_contents,
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback) {
- if (media_requests_map_.size() >= kNumMaxOutstandingMediaRequests) {
+ if (media_requests_map_.size() >= kNumMaxOutstandingPermissionRequests) {
// Deny the media request.
callback.Run(content::MediaStreamDevices());
return;
@@ -917,6 +961,38 @@ void BrowserPluginGuest::OnUpdateRect(
new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
}
+void BrowserPluginGuest::OnRespondPermissionGeolocation(
+ int request_id, bool should_allow) {
+ if (should_allow && embedder_web_contents_) {
+ // If renderer side embedder decides to allow gelocation, we need to check
+ // if the app/embedder itself has geolocation access.
+ BrowserContext* browser_context =
+ embedder_web_contents_->GetBrowserContext();
+ if (browser_context) {
+ GeolocationPermissionContext* geolocation_context =
+ browser_context->GetGeolocationPermissionContext();
+ if (geolocation_context) {
+ base::Callback<void(bool)> geolocation_callback = base::Bind(
+ &BrowserPluginGuest::SetGeolocationPermission,
+ weak_ptr_factory_.GetWeakPtr(),
+ request_id);
+ geolocation_context->RequestGeolocationPermission(
+ embedder_web_contents_->GetRenderProcessHost()->GetID(),
+ embedder_routing_id(),
+ // The geolocation permission request here is not initiated through
+ // WebGeolocationPermissionRequest. We are only interested in the
+ // fact whether the embedder/app has geolocation permission.
+ // Therefore we use an invalid |bridge_id|.
+ -1 /* bridge_id */,
+ embedder_web_contents_->GetURL(),
+ geolocation_callback);
+ return;
+ }
+ }
+ }
+ SetGeolocationPermission(request_id, false);
+}
+
void BrowserPluginGuest::OnRespondPermissionMedia(
int request_id, bool should_allow) {
MediaStreamRequestsMap::iterator media_request_iter =
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index e91dc6a..7d03a68 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -25,6 +25,7 @@
#include "base/compiler_specific.h"
#include "base/id_map.h"
+#include "base/memory/weak_ptr.h"
#include "base/shared_memory.h"
#include "base/time.h"
#include "content/common/browser_plugin/browser_plugin_message_enums.h"
@@ -72,6 +73,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver,
public WebContentsDelegate,
public WebContentsObserver {
public:
+ typedef base::Callback<void(bool)> GeolocationCallback;
virtual ~BrowserPluginGuest();
static BrowserPluginGuest* Create(
@@ -173,6 +175,15 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver,
// messages for testing.
virtual void SendMessageToEmbedder(IPC::Message* msg);
+ // Requests geolocation permission through embedder js api.
+ void AskEmbedderForGeolocationPermission(int bridge_id,
+ const GURL& requesting_frame,
+ GeolocationCallback callback);
+ // Cancels pending geolocation request.
+ void CancelGeolocationRequest(int bridge_id);
+ // Embedder sets permission to allow or deny geolocation request.
+ void SetGeolocationPermission(int request_id, bool allowed);
+
// Returns the identifier that uniquely identifies a browser plugin guest
// within an embedder.
int instance_id() const { return instance_id_; }
@@ -330,13 +341,20 @@ class CONTENT_EXPORT BrowserPluginGuest : public NotificationObserver,
void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
// Helpers for |OnRespondPermission|.
+ void OnRespondPermissionGeolocation(int request_id, bool should_allow);
void OnRespondPermissionMedia(int request_id, bool should_allow);
+ // Weak pointer used to ask GeolocationPermissionContext about geolocation
+ // permission.
+ base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
+
// Static factory instance (always NULL for non-test).
static content::BrowserPluginHostFactory* factory_;
NotificationRegistrar notification_registrar_;
WebContentsImpl* embedder_web_contents_;
+ typedef std::map<int, GeolocationCallback> GeolocationRequestsMap;
+ GeolocationRequestsMap geolocation_request_callback_map_;
// An identifier that uniquely identifies a browser plugin guest within an
// embedder.
int instance_id_;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index b598f4e..fa7fb67 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -41,6 +41,7 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/browser_main.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/browser_plugin/browser_plugin_geolocation_permission_context.h"
#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/device_orientation/orientation_message_filter.h"
@@ -537,8 +538,13 @@ void RenderProcessHostImpl::CreateMessageFilters() {
new IndexedDBDispatcherHost(
GetID(),
storage_partition_impl_->GetIndexedDBContext()));
- channel_->AddFilter(GeolocationDispatcherHost::New(
- GetID(), browser_context->GetGeolocationPermissionContext()));
+ if (IsGuest()) {
+ channel_->AddFilter(GeolocationDispatcherHost::New(
+ GetID(), new BrowserPluginGeolocationPermissionContext()));
+ } else {
+ channel_->AddFilter(GeolocationDispatcherHost::New(
+ GetID(), browser_context->GetGeolocationPermissionContext()));
+ }
gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
channel_->AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
diff --git a/content/common/browser_plugin/browser_plugin_constants.cc b/content/common/browser_plugin/browser_plugin_constants.cc
index 6d8405b..d0b3e10 100644
--- a/content/common/browser_plugin/browser_plugin_constants.cc
+++ b/content/common/browser_plugin/browser_plugin_constants.cc
@@ -56,6 +56,7 @@ const char kOldURL[] = "oldUrl";
const char kOldHeight[] = "oldHeight";
const char kOldWidth[] = "oldWidth";
const char kPermission[] = "permission";
+const char kPermissionTypeGeolocation[] = "geolocation";
const char kPermissionTypeMedia[] = "media";
const char kPersistPrefix[] = "persist:";
const char kProcessId[] = "processId";
diff --git a/content/common/browser_plugin/browser_plugin_constants.h b/content/common/browser_plugin/browser_plugin_constants.h
index d49837d..831467d1 100644
--- a/content/common/browser_plugin/browser_plugin_constants.h
+++ b/content/common/browser_plugin/browser_plugin_constants.h
@@ -57,6 +57,7 @@ extern const char kOldURL[];
extern const char kOldHeight[];
extern const char kOldWidth[];
extern const char kPermission[];
+extern const char kPermissionTypeGeolocation[];
extern const char kPermissionTypeMedia[];
extern const char kPersistPrefix[];
extern const char kProcessId[];
diff --git a/content/common/browser_plugin/browser_plugin_message_enums.h b/content/common/browser_plugin/browser_plugin_message_enums.h
index 56f8ea6..9d344ca 100644
--- a/content/common/browser_plugin/browser_plugin_message_enums.h
+++ b/content/common/browser_plugin/browser_plugin_message_enums.h
@@ -11,6 +11,9 @@ enum BrowserPluginPermissionType {
// Media access (audio/video) permission request type.
BrowserPluginPermissionTypeMedia,
+
+ // Geolocation.
+ BrowserPluginPermissionTypeGeolocation,
};
#endif // CONTENT_COMMON_BROWSER_PLUGIN_BROWSER_PLUGIN_MESSAGE_ENUMS_H_
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 846f972..fe33697 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -264,6 +264,8 @@
'browser/browser_main_runner.cc',
'browser/browser_plugin/browser_plugin_embedder.cc',
'browser/browser_plugin/browser_plugin_embedder.h',
+ 'browser/browser_plugin/browser_plugin_geolocation_permission_context.cc',
+ 'browser/browser_plugin/browser_plugin_geolocation_permission_context.h',
'browser/browser_plugin/browser_plugin_guest.cc',
'browser/browser_plugin/browser_plugin_guest.h',
'browser/browser_plugin/browser_plugin_guest_helper.cc',
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 37fe6eb..ee6a713 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -75,8 +75,11 @@ static std::string GetInternalEventName(const char* event_name) {
static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
switch (type) {
+ case BrowserPluginPermissionTypeGeolocation:
+ return browser_plugin::kPermissionTypeGeolocation;
case BrowserPluginPermissionTypeMedia:
return browser_plugin::kPermissionTypeMedia;
+ case BrowserPluginPermissionTypeUnknown:
default:
NOTREACHED();
break;
@@ -419,7 +422,7 @@ void BrowserPlugin::OnBuffersSwapped(int instance_id,
}
void BrowserPlugin::OnGuestContentWindowReady(int instance_id,
- int content_window_routing_id) {
+ int content_window_routing_id) {
DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
content_window_routing_id_ = content_window_routing_id;
}
@@ -538,15 +541,14 @@ void BrowserPlugin::OnLockMouse(int instance_id,
}
void BrowserPlugin::OnRequestPermission(
- int /*instance_id*/,
+ int instance_id,
BrowserPluginPermissionType permission_type,
int request_id,
const base::DictionaryValue& request_info) {
if (!HasEventListeners(browser_plugin::kEventRequestPermission)) {
// Automatically deny the request if there are no event listeners for
// permissionrequest.
- RespondPermission(
- permission_type, request_id, false /* allow */);
+ RespondPermission(permission_type, request_id, false /* allow */);
return;
}
DCHECK(!pending_permission_requests_.count(request_id));