Remove linux_chromium_gn_dbg from the chromium CQ.
[chromium-blink-merge.git] / extensions / renderer / user_script_set.cc
blob23cb833f8a0542ba3b7f4ccea6a8df9044ca103c
1 // Copyright 2014 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.
5 #include "extensions/renderer/user_script_set.h"
7 #include "base/memory/ref_counted.h"
8 #include "content/public/common/url_constants.h"
9 #include "content/public/renderer/render_frame.h"
10 #include "content/public/renderer/render_thread.h"
11 #include "extensions/common/extension.h"
12 #include "extensions/common/extensions_client.h"
13 #include "extensions/common/permissions/permissions_data.h"
14 #include "extensions/renderer/extension_injection_host.h"
15 #include "extensions/renderer/extensions_renderer_client.h"
16 #include "extensions/renderer/injection_host.h"
17 #include "extensions/renderer/renderer_extension_registry.h"
18 #include "extensions/renderer/script_context.h"
19 #include "extensions/renderer/script_injection.h"
20 #include "extensions/renderer/user_script_injector.h"
21 #include "extensions/renderer/web_ui_injection_host.h"
22 #include "third_party/WebKit/public/web/WebDocument.h"
23 #include "third_party/WebKit/public/web/WebLocalFrame.h"
24 #include "url/gurl.h"
26 namespace extensions {
28 namespace {
30 GURL GetDocumentUrlForFrame(blink::WebLocalFrame* frame) {
31 GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
32 if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
33 data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
34 data_source_url.spec());
37 return data_source_url;
40 } // namespace
42 UserScriptSet::UserScriptSet() {}
44 UserScriptSet::~UserScriptSet() {
47 void UserScriptSet::AddObserver(Observer* observer) {
48 observers_.AddObserver(observer);
51 void UserScriptSet::RemoveObserver(Observer* observer) {
52 observers_.RemoveObserver(observer);
55 void UserScriptSet::GetActiveExtensionIds(
56 std::set<std::string>* ids) const {
57 for (const UserScript* script : scripts_) {
58 if (script->host_id().type() != HostID::EXTENSIONS)
59 continue;
60 DCHECK(!script->extension_id().empty());
61 ids->insert(script->extension_id());
65 void UserScriptSet::GetInjections(
66 ScopedVector<ScriptInjection>* injections,
67 content::RenderFrame* render_frame,
68 int tab_id,
69 UserScript::RunLocation run_location) {
70 GURL document_url = GetDocumentUrlForFrame(render_frame->GetWebFrame());
71 for (const UserScript* script : scripts_) {
72 scoped_ptr<ScriptInjection> injection = GetInjectionForScript(
73 script,
74 render_frame,
75 tab_id,
76 run_location,
77 document_url,
78 false /* is_declarative */);
79 if (injection.get())
80 injections->push_back(injection.Pass());
84 bool UserScriptSet::UpdateUserScripts(base::SharedMemoryHandle shared_memory,
85 const std::set<HostID>& changed_hosts,
86 bool whitelisted_only) {
87 bool only_inject_incognito =
88 ExtensionsRendererClient::Get()->IsIncognitoProcess();
90 // Create the shared memory object (read only).
91 shared_memory_.reset(new base::SharedMemory(shared_memory, true));
92 if (!shared_memory_.get())
93 return false;
95 // First get the size of the memory block.
96 if (!shared_memory_->Map(sizeof(base::Pickle::Header)))
97 return false;
98 base::Pickle::Header* pickle_header =
99 reinterpret_cast<base::Pickle::Header*>(shared_memory_->memory());
101 // Now map in the rest of the block.
102 int pickle_size = sizeof(base::Pickle::Header) + pickle_header->payload_size;
103 shared_memory_->Unmap();
104 if (!shared_memory_->Map(pickle_size))
105 return false;
107 // Unpickle scripts.
108 size_t num_scripts = 0;
109 base::Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()),
110 pickle_size);
111 base::PickleIterator iter(pickle);
112 CHECK(iter.ReadSizeT(&num_scripts));
114 scripts_.clear();
115 scripts_.reserve(num_scripts);
116 for (size_t i = 0; i < num_scripts; ++i) {
117 scoped_ptr<UserScript> script(new UserScript());
118 script->Unpickle(pickle, &iter);
120 // Note that this is a pointer into shared memory. We don't own it. It gets
121 // cleared up when the last renderer or browser process drops their
122 // reference to the shared memory.
123 for (size_t j = 0; j < script->js_scripts().size(); ++j) {
124 const char* body = NULL;
125 int body_length = 0;
126 CHECK(iter.ReadData(&body, &body_length));
127 script->js_scripts()[j].set_external_content(
128 base::StringPiece(body, body_length));
130 for (size_t j = 0; j < script->css_scripts().size(); ++j) {
131 const char* body = NULL;
132 int body_length = 0;
133 CHECK(iter.ReadData(&body, &body_length));
134 script->css_scripts()[j].set_external_content(
135 base::StringPiece(body, body_length));
138 if (only_inject_incognito && !script->is_incognito_enabled())
139 continue; // This script shouldn't run in an incognito tab.
141 const Extension* extension =
142 RendererExtensionRegistry::Get()->GetByID(script->extension_id());
143 if (whitelisted_only &&
144 (!extension ||
145 !PermissionsData::CanExecuteScriptEverywhere(extension))) {
146 continue;
149 scripts_.push_back(script.Pass());
152 FOR_EACH_OBSERVER(Observer,
153 observers_,
154 OnUserScriptsUpdated(changed_hosts, scripts_.get()));
155 return true;
158 scoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection(
159 int script_id,
160 content::RenderFrame* render_frame,
161 int tab_id,
162 UserScript::RunLocation run_location,
163 const GURL& document_url) {
164 for (const UserScript* script : scripts_) {
165 if (script->id() == script_id) {
166 return GetInjectionForScript(script,
167 render_frame,
168 tab_id,
169 run_location,
170 document_url,
171 true /* is_declarative */);
174 return scoped_ptr<ScriptInjection>();
177 scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript(
178 const UserScript* script,
179 content::RenderFrame* render_frame,
180 int tab_id,
181 UserScript::RunLocation run_location,
182 const GURL& document_url,
183 bool is_declarative) {
184 scoped_ptr<ScriptInjection> injection;
185 scoped_ptr<const InjectionHost> injection_host;
186 blink::WebLocalFrame* web_frame = render_frame->GetWebFrame();
188 const HostID& host_id = script->host_id();
189 if (host_id.type() == HostID::EXTENSIONS) {
190 injection_host = ExtensionInjectionHost::Create(host_id.id());
191 if (!injection_host)
192 return injection.Pass();
193 } else {
194 DCHECK_EQ(host_id.type(), HostID::WEBUI);
195 injection_host.reset(new WebUIInjectionHost(host_id));
198 if (web_frame->parent() && !script->match_all_frames())
199 return injection.Pass(); // Only match subframes if the script declared it.
201 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
202 web_frame, document_url, script->match_about_blank());
204 if (!script->MatchesURL(effective_document_url))
205 return injection.Pass();
207 scoped_ptr<ScriptInjector> injector(new UserScriptInjector(script,
208 this,
209 is_declarative));
211 if (injector->CanExecuteOnFrame(
212 injection_host.get(),
213 web_frame,
214 tab_id) ==
215 PermissionsData::ACCESS_DENIED) {
216 return injection.Pass();
219 bool inject_css = !script->css_scripts().empty() &&
220 run_location == UserScript::DOCUMENT_START;
221 bool inject_js =
222 !script->js_scripts().empty() && script->run_location() == run_location;
223 if (inject_css || inject_js) {
224 injection.reset(new ScriptInjection(
225 injector.Pass(),
226 render_frame,
227 injection_host.Pass(),
228 run_location));
230 return injection.Pass();
233 } // namespace extensions