1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "extensions/renderer/extension_injection_host.h"
6 
7 #include "content/public/renderer/render_frame.h"
8 #include "extensions/common/constants.h"
9 #include "extensions/common/manifest_handlers/csp_info.h"
10 #include "extensions/renderer/renderer_extension_registry.h"
11 #include "third_party/blink/public/platform/web_security_origin.h"
12 #include "third_party/blink/public/web/web_local_frame.h"
13 
14 namespace extensions {
15 
ExtensionInjectionHost(const Extension * extension)16 ExtensionInjectionHost::ExtensionInjectionHost(
17     const Extension* extension)
18     : InjectionHost(HostID(HostID::EXTENSIONS, extension->id())),
19       extension_(extension) {
20 }
21 
~ExtensionInjectionHost()22 ExtensionInjectionHost::~ExtensionInjectionHost() {
23 }
24 
25 // static
Create(const std::string & extension_id)26 std::unique_ptr<const InjectionHost> ExtensionInjectionHost::Create(
27     const std::string& extension_id) {
28   const Extension* extension =
29       RendererExtensionRegistry::Get()->GetByID(extension_id);
30   if (!extension)
31     return std::unique_ptr<const ExtensionInjectionHost>();
32   return std::unique_ptr<const ExtensionInjectionHost>(
33       new ExtensionInjectionHost(extension));
34 }
35 
GetContentSecurityPolicy() const36 const std::string* ExtensionInjectionHost::GetContentSecurityPolicy() const {
37   return CSPInfo::GetIsolatedWorldCSP(*extension_);
38 }
39 
url() const40 const GURL& ExtensionInjectionHost::url() const {
41   return extension_->url();
42 }
43 
name() const44 const std::string& ExtensionInjectionHost::name() const {
45   return extension_->name();
46 }
47 
CanExecuteOnFrame(const GURL & document_url,content::RenderFrame * render_frame,int tab_id,bool is_declarative) const48 PermissionsData::PageAccess ExtensionInjectionHost::CanExecuteOnFrame(
49     const GURL& document_url,
50     content::RenderFrame* render_frame,
51     int tab_id,
52     bool is_declarative) const {
53   blink::WebSecurityOrigin top_frame_security_origin =
54       render_frame->GetWebFrame()->Top()->GetSecurityOrigin();
55   // Only whitelisted extensions may run scripts on another extension's page.
56   if (top_frame_security_origin.Protocol().Utf8() == kExtensionScheme &&
57       top_frame_security_origin.Host().Utf8() != extension_->id() &&
58       !PermissionsData::CanExecuteScriptEverywhere(extension_->id(),
59                                                    extension_->location())) {
60     return PermissionsData::PageAccess::kDenied;
61   }
62 
63   // Declarative user scripts use "page access" (from "permissions" section in
64   // manifest) whereas non-declarative user scripts use custom
65   // "content script access" logic.
66   PermissionsData::PageAccess access = PermissionsData::PageAccess::kAllowed;
67   if (is_declarative) {
68     access = extension_->permissions_data()->GetPageAccess(
69         document_url,
70         tab_id,
71         nullptr /* ignore error */);
72   } else {
73     access = extension_->permissions_data()->GetContentScriptAccess(
74         document_url,
75         tab_id,
76         nullptr /* ignore error */);
77   }
78   if (access == PermissionsData::PageAccess::kWithheld &&
79       (tab_id == -1 || render_frame->GetWebFrame()->Parent())) {
80     // Note: we don't consider ACCESS_WITHHELD for child frames or for frames
81     // outside of tabs because there is nowhere to surface a request.
82     // TODO(devlin): We should ask for permission somehow. crbug.com/491402.
83     access = PermissionsData::PageAccess::kDenied;
84   }
85   return access;
86 }
87 
88 }  // namespace extensions
89