Chromium Code Reviews| Index: extensions/browser/extension_navigation_throttle.cc |
| diff --git a/extensions/browser/extension_navigation_throttle.cc b/extensions/browser/extension_navigation_throttle.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9cb2e0488bb8b3f6aac05d54d1ee0345b55e1fb3 |
| --- /dev/null |
| +++ b/extensions/browser/extension_navigation_throttle.cc |
| @@ -0,0 +1,93 @@ |
| +// Copyright 2016 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 "extensions/browser/extension_navigation_throttle.h" |
| + |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/navigation_handle.h" |
| +#include "content/public/browser/render_frame_host.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "extensions/browser/extension_registry.h" |
| +#include "extensions/common/constants.h" |
| +#include "extensions/common/extension.h" |
| +#include "extensions/common/extension_set.h" |
| +#include "extensions/common/manifest_handlers/web_accessible_resources_info.h" |
| + |
| +namespace extensions { |
| + |
| +ExtensionNavigationThrottle::ExtensionNavigationThrottle( |
| + content::NavigationHandle* navigation_handle) |
| + : content::NavigationThrottle(navigation_handle) {} |
| + |
| +ExtensionNavigationThrottle::~ExtensionNavigationThrottle() {} |
| + |
| +content::NavigationThrottle::ThrottleCheckResult |
| +ExtensionNavigationThrottle::WillStartRequest() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + |
| + // This method for now enforces only web_accessible_resources for navigations. |
| + // Top-level navigations should always be allowed. |
| + DCHECK(!navigation_handle()->IsInMainFrame()); |
| + |
| + // If the navigation is not to a chrome-extension:// URL, no need to perform |
| + // any more checks. |
| + if (!navigation_handle()->GetURL().SchemeIs(extensions::kExtensionScheme)) |
| + return content::NavigationThrottle::PROCEED; |
| + |
| + // The subframe which is navigated needs to have all of its ancestors be |
| + // at the same origin, otherwise the resource needs to be explicitly listed |
| + // in web_accessible_resources. |
| + // Since the RenderFrameHost is not known until navigation has committed, |
| + // we can't get it from NavigationHandle. However, this code only cares about |
| + // the ancestor chain, so find the current RenderFrameHost and use it to |
| + // traverse up to the main frame. |
| + std::vector<content::RenderFrameHost*> frames = |
| + navigation_handle()->GetWebContents()->GetAllFrames(); |
|
Devlin
2016/06/03 22:22:45
nit: I'd probably just inline this on line 47:
for
nasko
2016/06/06 17:40:44
It isn't rare, but you don't know which RenderFram
|
| + content::RenderFrameHost* navigating_frame = nullptr; |
| + for (auto frame : frames) { |
| + if (frame->GetFrameTreeNodeId() == |
| + navigation_handle()->GetFrameTreeNodeId()) { |
| + navigating_frame = frame; |
| + break; |
| + } |
| + } |
| + DCHECK(navigating_frame); |
| + |
| + // Traverse the chain of parent frames, checking if they are the same origin |
| + // as the URL of this navigation. |
| + content::RenderFrameHost* ancestor = navigating_frame->GetParent(); |
| + bool external_ancestor = false; |
| + while (ancestor) { |
| + if (ancestor->GetLastCommittedURL().GetOrigin() != |
| + navigation_handle()->GetURL().GetOrigin()) { |
| + // Ignore DevTools, as it is allowed to embed extension pages. |
| + if (!ancestor->GetLastCommittedURL().SchemeIs("chrome-devtools")) { |
|
Devlin
2016/06/03 22:22:45
nit: content::kChromeDevToolsScheme
nasko
2016/06/06 17:40:44
Thanks! Already done, but didn't upload.
|
| + external_ancestor = true; |
| + break; |
| + } |
| + } |
| + ancestor = ancestor->GetParent(); |
| + } |
| + |
| + if (!external_ancestor) |
| + return content::NavigationThrottle::PROCEED; |
| + |
| + // Since there was at least one origin different than the navigation URL, |
| + // explicitly check for the resource in web_accessible_resources. |
| + std::string resource_path = navigation_handle()->GetURL().path(); |
| + extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get( |
|
Devlin
2016/06/03 22:22:45
no extensions:: prefix needed
nasko
2016/06/06 17:40:44
Done.
|
| + navigation_handle()->GetWebContents()->GetBrowserContext()); |
| + const extensions::Extension* extension = |
| + registry->enabled_extensions().GetByID( |
| + navigation_handle()->GetURL().host()); |
| + |
| + if (extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible( |
| + extension, resource_path)) { |
| + return content::NavigationThrottle::PROCEED; |
| + } |
| + |
| + return content::NavigationThrottle::BLOCK_REQUEST; |
| +} |
| + |
| +} // namespace extensions |