diff options
author | michaelbai@chromium.org <michaelbai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-28 18:25:34 +0000 |
---|---|---|
committer | michaelbai@chromium.org <michaelbai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-28 18:25:34 +0000 |
commit | 9710193224e6f1106eaff11fcbeea19b2e5e146d (patch) | |
tree | 7a8589e922e121ecbace5aa66464cb48ca96d4dc | |
parent | 7367bd4dd13bdde4fe9ab71bb227646d74d1427a (diff) | |
download | chromium_src-9710193224e6f1106eaff11fcbeea19b2e5e146d.zip chromium_src-9710193224e6f1106eaff11fcbeea19b2e5e146d.tar.gz chromium_src-9710193224e6f1106eaff11fcbeea19b2e5e146d.tar.bz2 |
Merge 271650 "Cancel the permission request when webview navigat..."
> Cancel the permission request when webview navigates to different page or reload.
>
> BUG=373352
>
> Review URL: https://codereview.chromium.org/288463003
TBR=michaelbai@chromium.org
Review URL: https://codereview.chromium.org/300323002
git-svn-id: svn://svn.chromium.org/chrome/branches/1985/src@273296 0039d316-1c4b-4281-b951-d872f2087c98
5 files changed, 211 insertions, 8 deletions
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java new file mode 100644 index 0000000..b4a132b --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/MediaAccessPermissionRequestTest.java @@ -0,0 +1,157 @@ +// Copyright 2014 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. + +package org.chromium.android_webview.test; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.permission.AwPermissionRequest; +import org.chromium.android_webview.test.util.CommonResources; +import org.chromium.base.test.util.Feature; +import org.chromium.content.browser.test.util.CallbackHelper; +import org.chromium.net.test.util.TestWebServer; + +import java.util.concurrent.Callable; + +/** + * Test MediaAccessPermissionRequest. + */ +public class MediaAccessPermissionRequestTest extends AwTestBase { + private static class OnPermissionRequestHelper extends CallbackHelper { + private boolean mCanceled; + + public void notifyCanceled() { + mCanceled = true; + notifyCalled(); + } + + public boolean canceled() { + return mCanceled; + } + } + + private final String mData = "<html> <script> " + + "var constraints = {audio: true, video: true};" + + "var video = document.querySelector('video');" + + "function successCallback(stream) {" + + "window.document.title = 'grant';" + + "if (window.URL) {" + + "video.src = window.URL.createObjectURL(stream);" + + "} else {" + + "video.src = stream;" + + "}" + + "}" + + "function errorCallback(error){" + + "window.document.title = 'deny';" + + "console.log('navigator.getUserMedia error: ', error);" + + "}" + + "navigator.webkitGetUserMedia(constraints, successCallback, errorCallback)" + + " </script><body>" + + "<video autoplay></video>" + + "</body></html>"; + + private TestWebServer mTestWebServer; + private String mWebRTCPage; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTestWebServer = new TestWebServer(false); + mWebRTCPage = mTestWebServer.setResponse("/WebRTC", mData, + CommonResources.getTextHtmlHeaders(true)); + } + + @Override + protected void tearDown() throws Exception { + mTestWebServer.shutdown(); + mTestWebServer = null; + super.tearDown(); + } + + @Feature({"AndroidWebView"}) + @SmallTest + public void testGrantAccess() throws Throwable { + final OnPermissionRequestHelper helper = new OnPermissionRequestHelper(); + TestAwContentsClient contentsClient = + new TestAwContentsClient() { + @Override + public void onPermissionRequest(AwPermissionRequest awPermissionRequest) { + awPermissionRequest.grant(); + helper.notifyCalled(); + } + }; + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(contentsClient); + final AwContents awContents = testContainerView.getAwContents(); + enableJavaScriptOnUiThread(awContents); + int callCount = helper.getCallCount(); + loadUrlAsync(awContents, mWebRTCPage, null); + helper.waitForCallback(callCount); + pollTitleAs("grant", awContents); + } + + @Feature({"AndroidWebView"}) + @SmallTest + public void testDenyAccess() throws Throwable { + final OnPermissionRequestHelper helper = new OnPermissionRequestHelper(); + TestAwContentsClient contentsClient = + new TestAwContentsClient() { + @Override + public void onPermissionRequest(AwPermissionRequest awPermissionRequest) { + awPermissionRequest.deny(); + helper.notifyCalled(); + } + }; + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(contentsClient); + final AwContents awContents = testContainerView.getAwContents(); + enableJavaScriptOnUiThread(awContents); + int callCount = helper.getCallCount(); + loadUrlAsync(awContents, mWebRTCPage, null); + helper.waitForCallback(callCount); + pollTitleAs("deny", awContents); + } + + private void pollTitleAs(final String title, final AwContents awContents) + throws Exception { + poll(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return title.equals(getTitleOnUiThread(awContents)); + } + }); + } + + @Feature({"AndroidWebView"}) + @SmallTest + public void testCancelPermission() throws Throwable { + final OnPermissionRequestHelper helper = new OnPermissionRequestHelper(); + TestAwContentsClient contentsClient = + new TestAwContentsClient() { + @Override + public void onPermissionRequest(AwPermissionRequest awPermissionRequest) { + // Don't respond and wait for the request canceled. + helper.notifyCalled(); + } + @Override + public void onPermissionRequestCanceled( + AwPermissionRequest awPermissionRequest) { + helper.notifyCanceled(); + } + }; + final AwTestContainerView testContainerView = + createAwTestContainerViewOnMainSync(contentsClient); + final AwContents awContents = testContainerView.getAwContents(); + enableJavaScriptOnUiThread(awContents); + int callCount = helper.getCallCount(); + loadUrlAsync(awContents, mWebRTCPage, null); + helper.waitForCallback(callCount); + callCount = helper.getCallCount(); + // Load the same page again, the previous request should be canceled. + loadUrlAsync(awContents, mWebRTCPage, null); + helper.waitForCallback(callCount); + assert (helper.canceled()); + } +} diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index d4b4e09..594f508 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -169,7 +169,8 @@ AwContents::AwContents(scoped_ptr<WebContents> web_contents) render_view_host_ext_.reset( new AwRenderViewHostExt(this, web_contents_.get())); - permission_request_handler_.reset(new PermissionRequestHandler(this)); + permission_request_handler_.reset( + new PermissionRequestHandler(this, web_contents_.get())); AwAutofillManagerDelegate* autofill_manager_delegate = AwAutofillManagerDelegate::FromWebContents(web_contents_.get()); diff --git a/android_webview/native/permission/permission_request_handler.cc b/android_webview/native/permission/permission_request_handler.cc index 20cc748..bb6cce3 100644 --- a/android_webview/native/permission/permission_request_handler.cc +++ b/android_webview/native/permission/permission_request_handler.cc @@ -9,19 +9,35 @@ #include "android_webview/native/permission/permission_request_handler_client.h" #include "base/android/scoped_java_ref.h" #include "base/bind.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/web_contents.h" using base::android::ScopedJavaLocalRef; namespace android_webview { +namespace { + +int GetActiveEntryID(content::WebContents* web_contents) { + if (!web_contents) return 0; + + content::NavigationEntry* active_entry = + web_contents->GetController().GetActiveEntry(); + return active_entry ? active_entry->GetUniqueID() : 0; +} + +} // namespace + PermissionRequestHandler::PermissionRequestHandler( - PermissionRequestHandlerClient* client) - : client_(client) { + PermissionRequestHandlerClient* client, content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + client_(client), + contents_unique_id_(GetActiveEntryID(web_contents)) { } PermissionRequestHandler::~PermissionRequestHandler() { - for (RequestIterator i = requests_.begin(); i != requests_.end(); ++i) - CancelRequest(i); + CancelAllRequests(); } void PermissionRequestHandler::SendRequest( @@ -64,6 +80,18 @@ void PermissionRequestHandler::PreauthorizePermission(const GURL& origin, preauthorized_permission_[key] |= resources; } +void PermissionRequestHandler::NavigationEntryCommitted( + const content::LoadCommittedDetails& details) { + const content::PageTransition transition = details.entry->GetTransitionType(); + if (details.is_navigation_to_different_page() || + content::PageTransitionStripQualifier(transition) == + content::PAGE_TRANSITION_RELOAD || + contents_unique_id_ != details.entry->GetUniqueID()) { + CancelAllRequests(); + contents_unique_id_ = details.entry->GetUniqueID(); + } +} + PermissionRequestHandler::RequestIterator PermissionRequestHandler::FindRequest(const GURL& origin, int64 resources) { @@ -87,6 +115,11 @@ void PermissionRequestHandler::CancelRequest(RequestIterator i) { delete i->get(); } +void PermissionRequestHandler::CancelAllRequests() { + for (RequestIterator i = requests_.begin(); i != requests_.end(); ++i) + CancelRequest(i); +} + void PermissionRequestHandler::PruneRequests() { for (RequestIterator i = requests_.begin(); i != requests_.end();) { if (!i->get()) diff --git a/android_webview/native/permission/permission_request_handler.h b/android_webview/native/permission/permission_request_handler.h index 3acb497..69a9171 100644 --- a/android_webview/native/permission/permission_request_handler.h +++ b/android_webview/native/permission/permission_request_handler.h @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "content/public/browser/web_contents_observer.h" #include "url/gurl.h" namespace android_webview { @@ -22,9 +23,10 @@ class PermissionRequestHandlerClient; // requests. // It is owned by AwContents and has 1x1 mapping to AwContents. All methods // are running on UI thread. -class PermissionRequestHandler { +class PermissionRequestHandler : public content::WebContentsObserver { public: - PermissionRequestHandler(PermissionRequestHandlerClient* aw_contents); + PermissionRequestHandler(PermissionRequestHandlerClient* client, + content::WebContents* aw_contents); virtual ~PermissionRequestHandler(); // Send the given |request| to PermissionRequestHandlerClient. @@ -36,6 +38,10 @@ class PermissionRequestHandler { // Allow |origin| to access the |resources|. void PreauthorizePermission(const GURL& origin, int64 resources); + // WebContentsObserver + virtual void NavigationEntryCommitted( + const content::LoadCommittedDetails& load_details) OVERRIDE; + private: friend class TestPermissionRequestHandler; @@ -48,6 +54,8 @@ class PermissionRequestHandler { // Cancel the given request. void CancelRequest(RequestIterator i); + void CancelAllRequests(); + // Remove the invalid requests from requests_. void PruneRequests(); @@ -61,6 +69,10 @@ class PermissionRequestHandler { std::map<std::string, int64> preauthorized_permission_; + // The unique id of the active NavigationEntry of the WebContents that we were + // opened for. Used to help expire on requests. + int contents_unique_id_; + DISALLOW_COPY_AND_ASSIGN(PermissionRequestHandler); }; diff --git a/android_webview/native/permission/permission_request_handler_unittest.cc b/android_webview/native/permission/permission_request_handler_unittest.cc index 981170c..c709f0b 100644 --- a/android_webview/native/permission/permission_request_handler_unittest.cc +++ b/android_webview/native/permission/permission_request_handler_unittest.cc @@ -106,7 +106,7 @@ class TestPermissionRequestHandlerClient : class TestPermissionRequestHandler : public PermissionRequestHandler { public: TestPermissionRequestHandler(PermissionRequestHandlerClient* client) - : PermissionRequestHandler(client) { + : PermissionRequestHandler(client, NULL) { } const std::vector<base::WeakPtr<AwPermissionRequest> > requests() { |