Index: chrome/renderer/chrome_content_renderer_client.cc |
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc |
index ef9c3fc04d9a306ee5b4af59a4784042814afd79..40bd1b9794335a7061ba89d1b3cf73825bc89433 100644 |
--- a/chrome/renderer/chrome_content_renderer_client.cc |
+++ b/chrome/renderer/chrome_content_renderer_client.cc |
@@ -17,10 +17,12 @@ |
#include "chrome/common/chrome_paths.h" |
#include "chrome/common/chrome_switches.h" |
#include "chrome/common/content_settings_pattern.h" |
+#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" |
#include "chrome/common/extensions/chrome_extensions_client.h" |
#include "chrome/common/extensions/extension.h" |
#include "chrome/common/extensions/extension_constants.h" |
#include "chrome/common/extensions/extension_manifest_constants.h" |
+#include "chrome/common/extensions/extension_messages.h" |
#include "chrome/common/extensions/extension_process_policy.h" |
#include "chrome/common/extensions/extension_set.h" |
#include "chrome/common/external_ipc_fuzzer.h" |
@@ -72,6 +74,7 @@ |
#include "content/public/renderer/render_view_visitor.h" |
#include "extensions/common/constants.h" |
#include "extensions/common/extension_urls.h" |
+#include "extensions/common/switches.h" |
#include "grit/generated_resources.h" |
#include "grit/locale_settings.h" |
#include "grit/renderer_resources.h" |
@@ -92,6 +95,7 @@ |
#include "third_party/WebKit/public/platform/WebURL.h" |
#include "third_party/WebKit/public/platform/WebURLError.h" |
#include "third_party/WebKit/public/platform/WebURLRequest.h" |
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" |
#include "ui/base/l10n/l10n_util.h" |
#include "ui/base/layout.h" |
#include "ui/base/resource/resource_bundle.h" |
@@ -924,6 +928,66 @@ bool ChromeContentRendererClient::AllowPopup() { |
extensions::Feature::CONTENT_SCRIPT_CONTEXT); |
} |
+// For top-level navigations, tries to find a platform app that has registered |
+// a URL handler matching the URL. If found, delegates further URL processing |
+// to the browser (the browser is supposed to launch the app), and returns true |
+// to cancel navigation on the renderer side. Otherwise, returns false. |
+bool ChromeContentRendererClient::HandleNavigation( |
+ WebKit::WebFrame* frame, |
+ const WebKit::WebURLRequest& request, |
+ WebKit::WebNavigationType type, |
+ WebKit::WebNavigationPolicy default_policy, |
+ bool is_redirect) { |
+ // TODO(sergeygs): Remove this and update includes once url_handlers are |
+ // moved out of experimental. |
+ if (!CommandLine::ForCurrentProcess()->HasSwitch( |
+ extensions::switches::kEnableExperimentalExtensionApis)) |
+ return false; |
+ |
+ // Limit redirection to top-level frames only. |
+ if (frame != frame->top()) |
+ return false; |
+ |
+ // Exclude reloads (shouldn't happen anyway) and back/forward. |
+ bool navigation_type_ok = |
+ WebKit::WebUserGestureIndicator::isProcessingUserGesture() || |
+ (type == WebKit::WebNavigationTypeLinkClicked) || |
+ (((type == WebKit::WebNavigationTypeFormSubmitted) || |
+ (type == WebKit::WebNavigationTypeFormResubmitted) || |
+ (type == WebKit::WebNavigationTypeOther) |
+ ) && frame->opener() |
+ ); |
+ |
+ if (!navigation_type_ok) |
+ return false; |
+ |
+ // Get the top-level RenderView (tab or extension window) so that we can send |
+ // a routed IPC message to the correct observer. |
+ content::RenderView* render_view = frame->opener() ? |
+ content::RenderView::FromWebView(frame->opener()->view()) : |
+ content::RenderView::FromWebView(frame->view()); |
+ if (!render_view) |
+ return false; |
+ |
+ // Find out if there is an extension that can handle the URL, and if there is, |
+ // send an IPC to the render view to launch it. |
+ const GURL url(request.url()); |
+ const ExtensionSet* exts = extension_dispatcher_->extensions(); |
+ for (ExtensionSet::const_iterator iter = exts->begin(); |
+ iter != exts->end(); |
+ ++iter) { |
+ if (extensions::UrlHandlers::CanExtensionHandleUrl(*iter, url)) { |
+ const GURL referrer_url( |
+ request.httpHeaderField(WebString::fromUTF8("Referer"))); |
+ return RenderThread::Get()->Send( |
+ new ExtensionHostMsg_RedirectUrl( |
+ render_view->GetRoutingID(), url, referrer_url)); |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
bool ChromeContentRendererClient::ShouldFork(WebFrame* frame, |
const GURL& url, |
const std::string& http_method, |