diff options
author | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 01:35:22 +0000 |
---|---|---|
committer | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 01:35:22 +0000 |
commit | 54aa17b1e77346c84d068be5d6eaddf576c440b7 (patch) | |
tree | 2dae52bf7eb8209d0224b679b311ccb17d810eb7 | |
parent | 9e04fe63a65381f35b40902719e7d6c776c2de90 (diff) | |
download | chromium_src-54aa17b1e77346c84d068be5d6eaddf576c440b7.zip chromium_src-54aa17b1e77346c84d068be5d6eaddf576c440b7.tar.gz chromium_src-54aa17b1e77346c84d068be5d6eaddf576c440b7.tar.bz2 |
Revert of Fix the handling of user gestures for external protocol handler dialogs. (https://codereview.chromium.org/131783012/)
Reason for revert:
Looks like this caused a failure on the build bots.
http://build.chromium.org/p/chromium.linux/builders/Linux%20Clang%20%28dbg%29/builds/57837
FAILED: /b/build/goma/gomacc ../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF obj/apps/shell/browser/app_shell_lib.shell_extensions_browser_client.o.d -DV8_DEPRECATION_WARNINGS -DBLINK_SCALE_FILTERS_AT_RECORD_TIME -D_FILE_OFFSET_BITS=64 -DCHROMIUM_BUILD -DCOMPONENT_BUILD -DTOOLKIT_VIEWS=1 -DUI_COMPOSITOR_IMAGE_TRANSPORT -DUSE_AURA=1 -DUSE_CAIRO=1 -DUSE_GLIB=1 -DUSE_DEFAULT_RENDER_THEME=1 -DUSE_LIBJPEG_TURBO=1 -DUSE_MOJO=1 -DUSE_X11=1 -DUSE_CLIPBOARD_AURAX11=1 -DENABLE_ONE_CLICK_SIGNIN -DUSE_XI2_MT=2 -DENABLE_REMOTING=1 -DENABLE_WEBRTC=1 -DENABLE_PEPPER_CDMS -DENABLE_CONFIGURATION_POLICY -DENABLE_INPUT_SPEECH -DENABLE_NOTIFICATIONS -DUSE_UDEV -DENABLE_EGLIMAGE=1 -DENABLE_TASK_MANAGER=1 -DENABLE_EXTENSIONS=1 -DENABLE_PLUGIN_INSTALLATION=1 -DENABLE_PLUGINS=1 -DENABLE_SESSION_SERVICE=1 -DENABLE_THEMES=1 -DENABLE_AUTOFILL_DIALOG=1 -DENABLE_BACKGROUND=1 -DENABLE_AUTOMATION=1 -DENABLE_GOOGLE_NOW=1 -DCLD_VERSION=2 -DENABLE_FULL_PRINTING=1 -DENABLE_PRINTING=1 -DENABLE_SPELLCHECK=1 -DENABLE_CAPTIVE_PORTAL_DETECTION=1 -DENABLE_APP_LIST=1 -DENABLE_SETTINGS_APP=1 -DENABLE_MANAGED_USERS=1 -DENABLE_MDNS=1 -DENABLE_SERVICE_DISCOVERY=1 -DGL_GLEXT_PROTOTYPES -DGTEST_HAS_POSIX_RE=0 -DLIBPEERCONNECTION_LIB=1 -DU_USING_ICU_NAMESPACE=0 -DV8_SHARED -DUSING_V8_SHARED -DCHROME_PNG_WRITE_SUPPORT -DPNG_USER_CONFIG -DSKIA_DLL -DGR_GL_IGNORE_ES3_MSAA=0 -DSK_ENABLE_INST_COUNT=0 -DSK_SUPPORT_GPU=1 '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' -DSK_ENABLE_LEGACY_API_ALIASING=1 -DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1 -DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1 -DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT -DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1 -DSK_SUPPORT_LEGACY_GETCLIPTYPE -DSK_SUPPORT_LEGACY_GETTOTALCLIP -DSK_SUPPORT_LEGACY_GETTOPDEVICE -DSK_USE_POSIX_THREADS -DSK_DEFERRED_CANVAS_USES_FACTORIES=1 -DUSE_NSS=1 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DWTF_USE_DYNAMIC_ANNOTATIONS=1 -D_DEBUG -D_GLIBCXX_DEBUG=1 -I../.. -I../../third_party/khronos -I../../gpu -I../../skia/config -I../../third_party/WebKit/Source -Igen -I../../third_party/WebKit -I../../third_party/icu/source/common -I../../third_party/npapi -I../../third_party/npapi/bindings -I../../v8/include -I../../third_party/libpng -I../../third_party/zlib -I../../third_party/libwebp -I../../third_party/ots/include -I../../third_party/qcms/src -I../../third_party/iccjpeg -I../../third_party/libjpeg_turbo -Igen/policy -Igen/protoc_out -I../../third_party/WebKit -I../../third_party/skia/src/core -I../../third_party/skia/include/core -I../../third_party/skia/include/effects -I../../third_party/skia/include/pdf -I../../third_party/skia/include/gpu -I../../third_party/skia/include/lazy -I../../third_party/skia/include/pathops -I../../third_party/skia/include/pipe -I../../third_party/skia/include/ports -I../../third_party/skia/include/utils -I../../skia/ext -fstack-protector --param=ssp-buffer-size=4 -Werror -pthread -fno-exceptions -fno-strict-aliasing -Wall -Wno-unused-parameter -Wno-missing-field-initializers -fvisibility=hidden -pipe -fPIC -Wheader-hygiene -Wno-char-subscripts -Wno-unneeded-internal-declaration -Wno-covered-switch-default -Wstring-conversion -Wno-c++11-narrowing -Wno-reserved-user-defined-literal -Wno-deprecated-register -Wno-absolute-value -Xclang -load -Xclang /b/build/slave/Linux_Clang__dbg_/build/src/tools/clang/scripts/../../../third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so -Xclang -add-plugin -Xclang find-bad-constructs -fcolor-diagnostics -pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -m64 -march=x86-64 -O0 -g -funwind-tables -fno-rtti -fno-threadsafe-statics -fvisibility-inlines-hidden -Wsign-compare -std=gnu++11 -c ../../apps/shell/browser/shell_extensions_browser_client.cc -o obj/apps/shell/browser/app_shell_lib.shell_extensions_browser_client.o
In file included from ../../apps/shell/browser/shell_extensions_browser_client.cc:5:
../../apps/shell/browser/shell_extensions_browser_client.h:54:16:error: 'PermitExternalProtocolHandler' marked 'override' but does not override any member functions
virtual void PermitExternalProtocolHandler() OVERRIDE;
Original issue's description:
> Fix the handling of user gestures for external protocol handler dialogs.
>
> - Remove browser state from external protocol handler.
> - Use gesture with a timeout.
>
> BUG=173557
>
> Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=261014
TBR=jyasskin@chromium.org,kalman@chromium.org,mmenke@chromium.org,joi@chromium.org,pkasting@chromium.org,jochen@chromium.org,boliu@chromium.org,meacer@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=173557
Review URL: https://codereview.chromium.org/221283006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261022 0039d316-1c4b-4281-b951-d872f2087c98
23 files changed, 138 insertions, 73 deletions
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index 05eb520..00b6e60 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc @@ -298,11 +298,9 @@ content::ResourceDispatcherHostLoginDelegate* return new AwLoginDelegate(auth_info, request); } -bool AwResourceDispatcherHostDelegate::HandleExternalProtocol( - const GURL& url, - int child_id, - int route_id, - bool initiated_by_user_gesture) { +bool AwResourceDispatcherHostDelegate::HandleExternalProtocol(const GURL& url, + int child_id, + int route_id) { // The AwURLRequestJobFactory implementation should ensure this method never // gets called. NOTREACHED(); diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h index 8702b09..e584c40 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h @@ -51,8 +51,7 @@ class AwResourceDispatcherHostDelegate net::URLRequest* request) OVERRIDE; virtual bool HandleExternalProtocol(const GURL& url, int child_id, - int route_id, - bool initiated_by_user_gesture) OVERRIDE; + int route_id) OVERRIDE; virtual void OnResponseStarted( net::URLRequest* request, content::ResourceContext* resource_context, diff --git a/chrome/browser/autocomplete/autocomplete_input.cc b/chrome/browser/autocomplete/autocomplete_input.cc index 4672f0c..ea42851 100644 --- a/chrome/browser/autocomplete/autocomplete_input.cc +++ b/chrome/browser/autocomplete/autocomplete_input.cc @@ -198,12 +198,9 @@ AutocompleteInput::Type AutocompleteInput::Parse( // handlable schemes (e.g. "javascript") may be treated as "blocked" by the // external protocol handler because we don't want pages to open them, but // users still can. - // Note that the protocol handler needs to be informed that omnibox input - // should always be considered "user gesture-triggered", lest it always - // return BLOCK. ExternalProtocolHandler::BlockState block_state = ExternalProtocolHandler::GetBlockState( - base::UTF16ToUTF8(parsed_scheme), true); + base::UTF16ToUTF8(parsed_scheme)); switch (block_state) { case ExternalProtocolHandler::DONT_BLOCK: return return_value_for_non_http_url; diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc index 756007e..ecedd34 100644 --- a/chrome/browser/extensions/active_tab_permission_granter.cc +++ b/chrome/browser/extensions/active_tab_permission_granter.cc @@ -37,9 +37,6 @@ ActiveTabPermissionGranter::ActiveTabPermissionGranter( ActiveTabPermissionGranter::~ActiveTabPermissionGranter() {} void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) { - // Active tab grant request implies there was a user gesture. - web_contents()->UserGestureDone(); - if (granted_extensions_.Contains(extension->id())) return; diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index a8582a2..67d76bd 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc @@ -183,6 +183,10 @@ bool ChromeExtensionsBrowserClient::DidVersionUpdate( return last_version.IsOlderThan(current_version); } +void ChromeExtensionsBrowserClient::PermitExternalProtocolHandler() { + ExternalProtocolHandler::PermitLaunchUrl(); +} + scoped_ptr<AppSorting> ChromeExtensionsBrowserClient::CreateAppSorting() { return scoped_ptr<AppSorting>(new ChromeAppSorting()); } diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.h b/chrome/browser/extensions/chrome_extensions_browser_client.h index f7c7752..dd2d469 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.h +++ b/chrome/browser/extensions/chrome_extensions_browser_client.h @@ -64,6 +64,7 @@ class ChromeExtensionsBrowserClient : public ExtensionsBrowserClient { virtual scoped_ptr<ExtensionHostDelegate> CreateExtensionHostDelegate() OVERRIDE; virtual bool DidVersionUpdate(content::BrowserContext* context) OVERRIDE; + virtual void PermitExternalProtocolHandler() OVERRIDE; virtual scoped_ptr<AppSorting> CreateAppSorting() OVERRIDE; virtual bool IsRunningInForcedAppMode() OVERRIDE; virtual ApiActivityMonitor* GetApiActivityMonitor( diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc index 78334d9..b414261 100644 --- a/chrome/browser/external_protocol/external_protocol_handler.cc +++ b/chrome/browser/external_protocol/external_protocol_handler.cc @@ -27,6 +27,11 @@ using content::BrowserThread; +// Whether we accept requests for launching external protocols. This is set to +// false every time an external protocol is requested, and set back to true on +// each user gesture. This variable should only be accessed from the UI thread. +static bool g_accept_requests = true; + namespace { // Functions enabling unit testing. Using a NULL delegate will use the default @@ -44,13 +49,11 @@ ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker( ExternalProtocolHandler::BlockState GetBlockStateWithDelegate( const std::string& scheme, - ExternalProtocolHandler::Delegate* delegate, - bool initiated_by_user_gesture) { + ExternalProtocolHandler::Delegate* delegate) { if (!delegate) - return ExternalProtocolHandler::GetBlockState(scheme, - initiated_by_user_gesture); + return ExternalProtocolHandler::GetBlockState(scheme); - return delegate->GetBlockState(scheme, initiated_by_user_gesture); + return delegate->GetBlockState(scheme); } void RunExternalProtocolDialogWithDelegate( @@ -200,9 +203,9 @@ void ExternalProtocolHandler::PrepopulateDictionary( // static ExternalProtocolHandler::BlockState ExternalProtocolHandler::GetBlockState( - const std::string& scheme, - bool initiated_by_user_gesture) { - if (!initiated_by_user_gesture) + const std::string& scheme) { + // If we are being carpet bombed, block the request. + if (!g_accept_requests) return BLOCK; if (scheme.length() == 1) { @@ -249,12 +252,10 @@ void ExternalProtocolHandler::SetBlockState(const std::string& scheme, } // static -void ExternalProtocolHandler::LaunchUrlWithDelegate( - const GURL& url, - int render_process_host_id, - int tab_contents_id, - Delegate* delegate, - bool initiated_by_user_gesture) { +void ExternalProtocolHandler::LaunchUrlWithDelegate(const GURL& url, + int render_process_host_id, + int tab_contents_id, + Delegate* delegate) { DCHECK(base::MessageLoopForUI::IsCurrent()); // Escape the input scheme to be sure that the command does not @@ -262,14 +263,15 @@ void ExternalProtocolHandler::LaunchUrlWithDelegate( std::string escaped_url_string = net::EscapeExternalHandlerValue(url.spec()); GURL escaped_url(escaped_url_string); BlockState block_state = GetBlockStateWithDelegate(escaped_url.scheme(), - delegate, - initiated_by_user_gesture); + delegate); if (block_state == BLOCK) { if (delegate) delegate->BlockRequest(); return; } + g_accept_requests = false; + // The worker creates tasks with references to itself and puts them into // message loops. When no tasks are left it will delete the observer and // eventually be deleted itself. @@ -306,3 +308,9 @@ void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck( void ExternalProtocolHandler::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(prefs::kExcludedSchemes); } + +// static +void ExternalProtocolHandler::PermitLaunchUrl() { + DCHECK(base::MessageLoopForUI::IsCurrent()); + g_accept_requests = true; +} diff --git a/chrome/browser/external_protocol/external_protocol_handler.h b/chrome/browser/external_protocol/external_protocol_handler.h index 6780d10..7c934c5 100644 --- a/chrome/browser/external_protocol/external_protocol_handler.h +++ b/chrome/browser/external_protocol/external_protocol_handler.h @@ -30,8 +30,7 @@ class ExternalProtocolHandler { virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker( ShellIntegration::DefaultWebClientObserver* observer, const std::string& protocol) = 0; - virtual BlockState GetBlockState(const std::string& scheme, - bool initiated_by_user_gesture) = 0; + virtual BlockState GetBlockState(const std::string& scheme) = 0; virtual void BlockRequest() = 0; virtual void RunExternalProtocolDialog(const GURL& url, int render_process_host_id, @@ -42,17 +41,27 @@ class ExternalProtocolHandler { }; // Returns whether we should block a given scheme. - static BlockState GetBlockState(const std::string& scheme, - bool initiated_by_user_gesture); + static BlockState GetBlockState(const std::string& scheme); // Sets whether we should block a given scheme. static void SetBlockState(const std::string& scheme, BlockState state); + // Checks to see if the protocol is allowed, if it is whitelisted, + // the application associated with the protocol is launched on the io thread, + // if it is blacklisted, returns silently. Otherwise, an + // ExternalProtocolDialog is created asking the user. If the user accepts, + // LaunchUrlWithoutSecurityCheck is called on the io thread and the + // application is launched. + // Must run on the UI thread. + static void LaunchUrl(const GURL& url, int render_process_host_id, + int tab_contents_id) { + LaunchUrlWithDelegate(url, render_process_host_id, tab_contents_id, NULL); + } + // Version of LaunchUrl allowing use of a delegate to facilitate unit // testing. static void LaunchUrlWithDelegate(const GURL& url, int render_process_host_id, - int tab_contents_id, Delegate* delegate, - bool initiated_by_user_gesture); + int tab_contents_id, Delegate* delegate); // Creates and runs a External Protocol dialog box. // |url| - The url of the request. @@ -87,8 +96,11 @@ class ExternalProtocolHandler { // preferences for them do not already exist. static void PrepopulateDictionary(base::DictionaryValue* win_pref); - private: - DISALLOW_COPY_AND_ASSIGN(ExternalProtocolHandler); + // Allows LaunchUrl to proceed with launching an external protocol handler. + // This is typically triggered by a user gesture, but is also called for + // each extension API function. Note that each call to LaunchUrl resets + // the state to false (not allowed). + static void PermitLaunchUrl(); }; #endif // CHROME_BROWSER_EXTERNAL_PROTOCOL_EXTERNAL_PROTOCOL_HANDLER_H_ diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc index 0b27465..57a6db6 100644 --- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc +++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc @@ -51,8 +51,7 @@ class FakeExternalProtocolHandlerDelegate } virtual ExternalProtocolHandler::BlockState GetBlockState( - const std::string& scheme, - bool initiated_by_user_gesture) OVERRIDE { return block_state_; } + const std::string& scheme) OVERRIDE { return block_state_; } virtual void BlockRequest() OVERRIDE { ASSERT_TRUE(block_state_ == ExternalProtocolHandler::BLOCK || @@ -108,6 +107,11 @@ class ExternalProtocolHandlerTest : public testing::Test { file_thread_.Start(); } + virtual void TearDown() { + // Ensure that g_accept_requests gets set back to true after test execution. + ExternalProtocolHandler::PermitLaunchUrl(); + } + void DoTest(ExternalProtocolHandler::BlockState block_state, ShellIntegration::DefaultWebClientState os_state, bool should_prompt, bool should_launch, bool should_block) { @@ -118,7 +122,7 @@ class ExternalProtocolHandlerTest : public testing::Test { delegate_.set_block_state(block_state); delegate_.set_os_state(os_state); - ExternalProtocolHandler::LaunchUrlWithDelegate(url, 0, 0, &delegate_, true); + ExternalProtocolHandler::LaunchUrlWithDelegate(url, 0, 0, &delegate_); if (block_state != ExternalProtocolHandler::BLOCK) base::MessageLoop::current()->Run(); diff --git a/chrome/browser/external_protocol/external_protocol_observer.cc b/chrome/browser/external_protocol/external_protocol_observer.cc new file mode 100644 index 0000000..8f69517 --- /dev/null +++ b/chrome/browser/external_protocol/external_protocol_observer.cc @@ -0,0 +1,22 @@ +// 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. + +#include "chrome/browser/external_protocol/external_protocol_observer.h" + +#include "chrome/browser/external_protocol/external_protocol_handler.h" + +using content::WebContents; + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(ExternalProtocolObserver); + +ExternalProtocolObserver::ExternalProtocolObserver(WebContents* web_contents) + : content::WebContentsObserver(web_contents) { +} + +ExternalProtocolObserver::~ExternalProtocolObserver() { +} + +void ExternalProtocolObserver::DidGetUserGesture() { + ExternalProtocolHandler::PermitLaunchUrl(); +} diff --git a/chrome/browser/external_protocol/external_protocol_observer.h b/chrome/browser/external_protocol/external_protocol_observer.h new file mode 100644 index 0000000..8249c3d --- /dev/null +++ b/chrome/browser/external_protocol/external_protocol_observer.h @@ -0,0 +1,29 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTERNAL_PROTOCOL_EXTERNAL_PROTOCOL_OBSERVER_H_ +#define CHROME_BROWSER_EXTERNAL_PROTOCOL_EXTERNAL_PROTOCOL_OBSERVER_H_ + +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +// ExternalProtocolObserver is responsible for handling messages from +// WebContents relating to external protocols. +class ExternalProtocolObserver + : public content::WebContentsObserver, + public content::WebContentsUserData<ExternalProtocolObserver> { + public: + virtual ~ExternalProtocolObserver(); + + // content::WebContentsObserver overrides. + virtual void DidGetUserGesture() OVERRIDE; + + private: + explicit ExternalProtocolObserver(content::WebContents* web_contents); + friend class content::WebContentsUserData<ExternalProtocolObserver>; + + DISALLOW_COPY_AND_ASSIGN(ExternalProtocolObserver); +}; + +#endif // CHROME_BROWSER_EXTERNAL_PROTOCOL_EXTERNAL_PROTOCOL_OBSERVER_H_ diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 68841b8..af8e09e 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -972,8 +972,7 @@ class NeverRunsExternalProtocolHandlerDelegate return NULL; } virtual ExternalProtocolHandler::BlockState GetBlockState( - const std::string& scheme, - bool initiated_by_user_gesture) OVERRIDE { + const std::string& scheme) OVERRIDE { // Block everything and fail the test. ADD_FAILURE(); return ExternalProtocolHandler::BLOCK; diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc index 8fe2144..268e374 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc @@ -198,8 +198,7 @@ void SendExecuteMimeTypeHandlerEvent(scoped_ptr<content::StreamHandle> stream, extension_id, web_contents, stream.Pass(), expected_content_size); } -void LaunchURL(const GURL& url, int render_process_id, int render_view_id, - bool user_gesture) { +void LaunchURL(const GURL& url, int render_process_id, int render_view_id) { // If there is no longer a WebContents, the request may have raced with tab // closing. Don't fire the external request. (It may have been a prerender.) content::WebContents* web_contents = @@ -218,8 +217,7 @@ void LaunchURL(const GURL& url, int render_process_id, int render_view_id, ExternalProtocolHandler::LaunchUrlWithDelegate( url, render_process_id, render_view_id, - g_external_protocol_handler_delegate, - user_gesture); + g_external_protocol_handler_delegate); } #endif // !defined(OS_ANDROID) @@ -443,10 +441,7 @@ ResourceDispatcherHostLoginDelegate* } bool ChromeResourceDispatcherHostDelegate::HandleExternalProtocol( - const GURL& url, - int child_id, - int route_id, - bool initiated_by_user_gesture) { + const GURL& url, int child_id, int route_id) { #if defined(OS_ANDROID) // Android use a resource throttle to handle external as well as internal // protocols. @@ -462,8 +457,7 @@ bool ChromeResourceDispatcherHostDelegate::HandleExternalProtocol( BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&LaunchURL, url, child_id, route_id, - initiated_by_user_gesture)); + base::Bind(&LaunchURL, url, child_id, route_id)); return true; #endif } diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h index b154b5b..8bcf06a 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h @@ -65,8 +65,7 @@ class ChromeResourceDispatcherHostDelegate net::AuthChallengeInfo* auth_info, net::URLRequest* request) OVERRIDE; virtual bool HandleExternalProtocol(const GURL& url, int child_id, - int route_id, - bool initiated_by_user_gesture) OVERRIDE; + int route_id) OVERRIDE; virtual bool ShouldForceDownloadResource( const GURL& url, const std::string& mime_type) OVERRIDE; virtual bool ShouldInterceptResourceAsStream( diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 45853cd..5fd4fef 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc @@ -40,6 +40,7 @@ #else #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" +#include "chrome/browser/external_protocol/external_protocol_observer.h" #include "chrome/browser/net/predictor_tab_helper.h" #include "chrome/browser/network_time/navigation_time_helper.h" #include "chrome/browser/plugins/plugin_observer.h" @@ -151,6 +152,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( web_contents); extensions::WebNavigationTabObserver::CreateForWebContents(web_contents); + ExternalProtocolObserver::CreateForWebContents(web_contents); HungPluginTabHelper::CreateForWebContents(web_contents); ManagePasswordsBubbleUIController::CreateForWebContents(web_contents); NavigationTimeHelper::CreateForWebContents(web_contents); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 93f008a..0403a63 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -654,6 +654,8 @@ 'browser/extensions/token_cache/token_cache_service_factory.h', 'browser/external_protocol/external_protocol_handler.cc', 'browser/external_protocol/external_protocol_handler.h', + 'browser/external_protocol/external_protocol_observer.cc', + 'browser/external_protocol/external_protocol_observer.h', 'browser/favicon/favicon_changed_details.cc', 'browser/favicon/favicon_changed_details.h', 'browser/favicon/favicon_handler.cc', @@ -3334,6 +3336,7 @@ 'browser/download/download_shelf.cc', 'browser/download/download_shelf_context_menu.cc', 'browser/drive/drive_switches.cc', + 'browser/external_protocol/external_protocol_observer.cc', 'browser/feedback/proto/annotations.proto', 'browser/feedback/proto/chrome.proto', 'browser/feedback/proto/common.proto', diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index c5e067d..61fc35b 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc @@ -679,15 +679,8 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader, if (job_factory->IsHandledURL(url)) return false; - bool initiated_by_user_gesture = - (loader->request()->load_flags() & net::LOAD_MAYBE_USER_GESTURE) != 0; - bool handled = delegate_->HandleExternalProtocol(url, info->GetChildID(), - info->GetRouteID(), - initiated_by_user_gesture); - // Consume the user gesture if the external protocol dialog is shown. - if (handled) - last_user_gesture_time_ = base::TimeTicks(); - return handled; + return delegate_->HandleExternalProtocol(url, info->GetChildID(), + info->GetRouteID()); } void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { diff --git a/content/public/browser/resource_dispatcher_host_delegate.cc b/content/public/browser/resource_dispatcher_host_delegate.cc index ccd358f..bf92b25 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.cc +++ b/content/public/browser/resource_dispatcher_host_delegate.cc @@ -46,11 +46,9 @@ ResourceDispatcherHostLoginDelegate* return NULL; } -bool ResourceDispatcherHostDelegate::HandleExternalProtocol( - const GURL& url, - int child_id, - int route_id, - bool initiated_by_user_gesture) { +bool ResourceDispatcherHostDelegate::HandleExternalProtocol(const GURL& url, + int child_id, + int route_id) { return true; } diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h index 598cffb..0d0eebc 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.h +++ b/content/public/browser/resource_dispatcher_host_delegate.h @@ -84,12 +84,9 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate { // Launches the url for the given tab. Returns true if an attempt to handle // the url was made, e.g. by launching an app. Note that this does not // guarantee that the app successfully handled it. - // Some external protocol handlers only run in the context of a user gesture, - // so initiated_by_user_gesture should be passed accordingly. virtual bool HandleExternalProtocol(const GURL& url, int child_id, - int route_id, - bool initiated_by_user_gesture); + int route_id); // Returns true if we should force the given resource to be downloaded. // Otherwise, the content layer decides. diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc index d6420e3..5e0cffe 100644 --- a/extensions/browser/extension_function_dispatcher.cc +++ b/extensions/browser/extension_function_dispatcher.cc @@ -375,6 +375,8 @@ void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( if (violation_error.empty()) { scoped_ptr<base::ListValue> args(params.arguments.DeepCopy()); + // See crbug.com/39178. + ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler(); NotifyApiFunctionCalled( extension->id(), params.name, args.Pass(), browser_context_); function->Run(); diff --git a/extensions/browser/extensions_browser_client.h b/extensions/browser/extensions_browser_client.h index 132e77a..2e3d26d 100644 --- a/extensions/browser/extensions_browser_client.h +++ b/extensions/browser/extensions_browser_client.h @@ -106,6 +106,10 @@ class ExtensionsBrowserClient { // version for later comparison. virtual bool DidVersionUpdate(content::BrowserContext* context) = 0; + // Permits an external protocol handler to be launched. See + // ExternalProtocolHandler::PermitLaunchUrl() in Chrome. + virtual void PermitExternalProtocolHandler() = 0; + // Creates a new AppSorting instance. virtual scoped_ptr<AppSorting> CreateAppSorting() = 0; diff --git a/extensions/browser/test_extensions_browser_client.cc b/extensions/browser/test_extensions_browser_client.cc index 8a3fe23..739450b 100644 --- a/extensions/browser/test_extensions_browser_client.cc +++ b/extensions/browser/test_extensions_browser_client.cc @@ -107,6 +107,8 @@ bool TestExtensionsBrowserClient::DidVersionUpdate(BrowserContext* context) { return false; } +void TestExtensionsBrowserClient::PermitExternalProtocolHandler() {} + scoped_ptr<AppSorting> TestExtensionsBrowserClient::CreateAppSorting() { return scoped_ptr<AppSorting>(); } diff --git a/extensions/browser/test_extensions_browser_client.h b/extensions/browser/test_extensions_browser_client.h index ac82589..19f33d7 100644 --- a/extensions/browser/test_extensions_browser_client.h +++ b/extensions/browser/test_extensions_browser_client.h @@ -51,6 +51,7 @@ class TestExtensionsBrowserClient : public ExtensionsBrowserClient { virtual scoped_ptr<ExtensionHostDelegate> CreateExtensionHostDelegate() OVERRIDE; virtual bool DidVersionUpdate(content::BrowserContext* context) OVERRIDE; + virtual void PermitExternalProtocolHandler() OVERRIDE; virtual scoped_ptr<AppSorting> CreateAppSorting() OVERRIDE; virtual bool IsRunningInForcedAppMode() OVERRIDE; virtual ApiActivityMonitor* GetApiActivityMonitor( |