Reland the ULONG -> SIZE_T change from 317177
[chromium-blink-merge.git] / extensions / renderer / user_script_set.cc
blob1d66aaa1e9660c7f6f5d7dcd27cefa9cb6d9f4ea
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_thread.h"
10 #include "extensions/common/extension.h"
11 #include "extensions/common/extension_set.h"
12 #include "extensions/common/permissions/permissions_data.h"
13 #include "extensions/renderer/extension_injection_host.h"
14 #include "extensions/renderer/extensions_renderer_client.h"
15 #include "extensions/renderer/script_context.h"
16 #include "extensions/renderer/script_injection.h"
17 #include "extensions/renderer/user_script_injector.h"
18 #include "third_party/WebKit/public/web/WebDocument.h"
19 #include "third_party/WebKit/public/web/WebFrame.h"
20 #include "url/gurl.h"
22 namespace extensions {
24 namespace {
26 GURL GetDocumentUrlForFrame(blink::WebFrame* frame) {
27 GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
28 if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
29 data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
30 data_source_url.spec());
33 return data_source_url;
36 } // namespace
38 UserScriptSet::UserScriptSet(const ExtensionSet* extensions)
39 : extensions_(extensions) {
42 UserScriptSet::~UserScriptSet() {
45 void UserScriptSet::AddObserver(Observer* observer) {
46 observers_.AddObserver(observer);
49 void UserScriptSet::RemoveObserver(Observer* observer) {
50 observers_.RemoveObserver(observer);
53 void UserScriptSet::GetActiveExtensionIds(
54 std::set<std::string>* ids) const {
55 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
56 iter != scripts_.end();
57 ++iter) {
58 DCHECK(!(*iter)->extension_id().empty());
59 ids->insert((*iter)->extension_id());
63 void UserScriptSet::GetInjections(
64 ScopedVector<ScriptInjection>* injections,
65 blink::WebFrame* web_frame,
66 int tab_id,
67 UserScript::RunLocation run_location) {
68 GURL document_url = GetDocumentUrlForFrame(web_frame);
69 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
70 iter != scripts_.end();
71 ++iter) {
72 const Extension* extension = extensions_->GetByID((*iter)->extension_id());
73 if (!extension)
74 continue;
75 scoped_ptr<ScriptInjection> injection = GetInjectionForScript(
76 *iter,
77 web_frame,
78 tab_id,
79 run_location,
80 document_url,
81 extension,
82 false /* is_declarative */);
83 if (injection.get())
84 injections->push_back(injection.release());
88 bool UserScriptSet::UpdateUserScripts(
89 base::SharedMemoryHandle shared_memory,
90 const std::set<std::string>& changed_extensions) {
91 bool only_inject_incognito =
92 ExtensionsRendererClient::Get()->IsIncognitoProcess();
94 // Create the shared memory object (read only).
95 shared_memory_.reset(new base::SharedMemory(shared_memory, true));
96 if (!shared_memory_.get())
97 return false;
99 // First get the size of the memory block.
100 if (!shared_memory_->Map(sizeof(Pickle::Header)))
101 return false;
102 Pickle::Header* pickle_header =
103 reinterpret_cast<Pickle::Header*>(shared_memory_->memory());
105 // Now map in the rest of the block.
106 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size;
107 shared_memory_->Unmap();
108 if (!shared_memory_->Map(pickle_size))
109 return false;
111 // Unpickle scripts.
112 size_t num_scripts = 0;
113 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size);
114 PickleIterator iter(pickle);
115 CHECK(iter.ReadSizeT(&num_scripts));
117 scripts_.clear();
118 scripts_.reserve(num_scripts);
119 for (size_t i = 0; i < num_scripts; ++i) {
120 scoped_ptr<UserScript> script(new UserScript());
121 script->Unpickle(pickle, &iter);
123 // Note that this is a pointer into shared memory. We don't own it. It gets
124 // cleared up when the last renderer or browser process drops their
125 // reference to the shared memory.
126 for (size_t j = 0; j < script->js_scripts().size(); ++j) {
127 const char* body = NULL;
128 int body_length = 0;
129 CHECK(iter.ReadData(&body, &body_length));
130 script->js_scripts()[j].set_external_content(
131 base::StringPiece(body, body_length));
133 for (size_t j = 0; j < script->css_scripts().size(); ++j) {
134 const char* body = NULL;
135 int body_length = 0;
136 CHECK(iter.ReadData(&body, &body_length));
137 script->css_scripts()[j].set_external_content(
138 base::StringPiece(body, body_length));
141 if (only_inject_incognito && !script->is_incognito_enabled())
142 continue; // This script shouldn't run in an incognito tab.
144 scripts_.push_back(script.release());
147 FOR_EACH_OBSERVER(Observer,
148 observers_,
149 OnUserScriptsUpdated(changed_extensions, scripts_.get()));
150 return true;
153 scoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection(
154 int script_id,
155 blink::WebFrame* web_frame,
156 int tab_id,
157 UserScript::RunLocation run_location,
158 const GURL& document_url,
159 const Extension* extension) {
160 for (ScopedVector<UserScript>::const_iterator it = scripts_.begin();
161 it != scripts_.end();
162 ++it) {
163 if ((*it)->id() == script_id) {
164 return GetInjectionForScript(*it,
165 web_frame,
166 tab_id,
167 run_location,
168 document_url,
169 extension,
170 true /* is_declarative */);
173 return scoped_ptr<ScriptInjection>();
176 // TODO(dcheng): Scripts can't be injected on a remote frame, so this function
177 // signature needs to be updated.
178 scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript(
179 UserScript* script,
180 blink::WebFrame* web_frame,
181 int tab_id,
182 UserScript::RunLocation run_location,
183 const GURL& document_url,
184 const Extension* extension,
185 bool is_declarative) {
186 scoped_ptr<ScriptInjection> injection;
187 if (web_frame->parent() && !script->match_all_frames())
188 return injection.Pass(); // Only match subframes if the script declared it.
190 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
191 web_frame, document_url, script->match_about_blank());
193 if (!script->MatchesURL(effective_document_url))
194 return injection.Pass();
196 scoped_ptr<ScriptInjector> injector(new UserScriptInjector(script,
197 this,
198 is_declarative));
199 HostID host_id(HostID::EXTENSIONS, extension->id());
200 ExtensionInjectionHost extension_injection_host(
201 make_scoped_refptr<const Extension>(extension));
202 if (injector->CanExecuteOnFrame(
203 &extension_injection_host,
204 web_frame,
205 -1, // Content scripts are not tab-specific.
206 web_frame->top()->document().url()) ==
207 PermissionsData::ACCESS_DENIED) {
208 return injection.Pass();
211 bool inject_css = !script->css_scripts().empty() &&
212 run_location == UserScript::DOCUMENT_START;
213 bool inject_js =
214 !script->js_scripts().empty() && script->run_location() == run_location;
215 if (inject_css || inject_js) {
216 injection.reset(new ScriptInjection(
217 injector.Pass(),
218 web_frame->toWebLocalFrame(),
219 host_id,
220 run_location,
221 tab_id));
223 return injection.Pass();
226 } // namespace extensions