summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-02 01:35:22 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-02 01:35:22 +0000
commit54aa17b1e77346c84d068be5d6eaddf576c440b7 (patch)
tree2dae52bf7eb8209d0224b679b311ccb17d810eb7
parent9e04fe63a65381f35b40902719e7d6c776c2de90 (diff)
downloadchromium_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
-rw-r--r--android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc8
-rw-r--r--android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h3
-rw-r--r--chrome/browser/autocomplete/autocomplete_input.cc5
-rw-r--r--chrome/browser/extensions/active_tab_permission_granter.cc3
-rw-r--r--chrome/browser/extensions/chrome_extensions_browser_client.cc4
-rw-r--r--chrome/browser/extensions/chrome_extensions_browser_client.h1
-rw-r--r--chrome/browser/external_protocol/external_protocol_handler.cc40
-rw-r--r--chrome/browser/external_protocol/external_protocol_handler.h28
-rw-r--r--chrome/browser/external_protocol/external_protocol_handler_unittest.cc10
-rw-r--r--chrome/browser/external_protocol/external_protocol_observer.cc22
-rw-r--r--chrome/browser/external_protocol/external_protocol_observer.h29
-rw-r--r--chrome/browser/prerender/prerender_browsertest.cc3
-rw-r--r--chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc14
-rw-r--r--chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h3
-rw-r--r--chrome/browser/ui/tab_helpers.cc2
-rw-r--r--chrome/chrome_browser.gypi3
-rw-r--r--content/browser/loader/resource_dispatcher_host_impl.cc11
-rw-r--r--content/public/browser/resource_dispatcher_host_delegate.cc8
-rw-r--r--content/public/browser/resource_dispatcher_host_delegate.h5
-rw-r--r--extensions/browser/extension_function_dispatcher.cc2
-rw-r--r--extensions/browser/extensions_browser_client.h4
-rw-r--r--extensions/browser/test_extensions_browser_client.cc2
-rw-r--r--extensions/browser/test_extensions_browser_client.h1
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(