Revert "Revert of Revert of Revert of ChromeOS NetworkScreenHandler should not call...
[chromium-blink-merge.git] / extensions / renderer / user_script_set.cc
blob96d542ea99b36d7c75620baf133984e0df9616fc
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 "content/public/common/url_constants.h"
8 #include "content/public/renderer/render_thread.h"
9 #include "extensions/common/extension.h"
10 #include "extensions/common/extension_set.h"
11 #include "extensions/common/permissions/permissions_data.h"
12 #include "extensions/renderer/extensions_renderer_client.h"
13 #include "extensions/renderer/script_context.h"
14 #include "extensions/renderer/script_injection.h"
15 #include "extensions/renderer/user_script_injector.h"
16 #include "third_party/WebKit/public/web/WebDocument.h"
17 #include "third_party/WebKit/public/web/WebFrame.h"
18 #include "url/gurl.h"
20 namespace extensions {
22 namespace {
24 GURL GetDocumentUrlForFrame(blink::WebFrame* frame) {
25 GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
26 if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
27 data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
28 data_source_url.spec());
31 return data_source_url;
34 } // namespace
36 UserScriptSet::UserScriptSet(const ExtensionSet* extensions)
37 : extensions_(extensions) {
40 UserScriptSet::~UserScriptSet() {
43 void UserScriptSet::AddObserver(Observer* observer) {
44 observers_.AddObserver(observer);
47 void UserScriptSet::RemoveObserver(Observer* observer) {
48 observers_.RemoveObserver(observer);
51 void UserScriptSet::GetActiveExtensionIds(
52 std::set<std::string>* ids) const {
53 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
54 iter != scripts_.end();
55 ++iter) {
56 DCHECK(!(*iter)->extension_id().empty());
57 ids->insert((*iter)->extension_id());
61 void UserScriptSet::GetInjections(
62 ScopedVector<ScriptInjection>* injections,
63 blink::WebFrame* web_frame,
64 int tab_id,
65 UserScript::RunLocation run_location) {
66 GURL document_url = GetDocumentUrlForFrame(web_frame);
67 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
68 iter != scripts_.end();
69 ++iter) {
70 const Extension* extension = extensions_->GetByID((*iter)->extension_id());
71 if (!extension)
72 continue;
73 scoped_ptr<ScriptInjection> injection = GetInjectionForScript(
74 *iter,
75 web_frame,
76 tab_id,
77 run_location,
78 document_url,
79 extension,
80 false /* is_declarative */);
81 if (injection.get())
82 injections->push_back(injection.release());
86 bool UserScriptSet::UpdateUserScripts(
87 base::SharedMemoryHandle shared_memory,
88 const std::set<std::string>& changed_extensions) {
89 bool only_inject_incognito =
90 ExtensionsRendererClient::Get()->IsIncognitoProcess();
92 // Create the shared memory object (read only).
93 shared_memory_.reset(new base::SharedMemory(shared_memory, true));
94 if (!shared_memory_.get())
95 return false;
97 // First get the size of the memory block.
98 if (!shared_memory_->Map(sizeof(Pickle::Header)))
99 return false;
100 Pickle::Header* pickle_header =
101 reinterpret_cast<Pickle::Header*>(shared_memory_->memory());
103 // Now map in the rest of the block.
104 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size;
105 shared_memory_->Unmap();
106 if (!shared_memory_->Map(pickle_size))
107 return false;
109 // Unpickle scripts.
110 size_t num_scripts = 0;
111 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size);
112 PickleIterator iter(pickle);
113 CHECK(pickle.ReadSizeT(&iter, &num_scripts));
115 scripts_.clear();
116 scripts_.reserve(num_scripts);
117 for (size_t i = 0; i < num_scripts; ++i) {
118 scoped_ptr<UserScript> script(new UserScript());
119 script->Unpickle(pickle, &iter);
121 // Note that this is a pointer into shared memory. We don't own it. It gets
122 // cleared up when the last renderer or browser process drops their
123 // reference to the shared memory.
124 for (size_t j = 0; j < script->js_scripts().size(); ++j) {
125 const char* body = NULL;
126 int body_length = 0;
127 CHECK(pickle.ReadData(&iter, &body, &body_length));
128 script->js_scripts()[j].set_external_content(
129 base::StringPiece(body, body_length));
131 for (size_t j = 0; j < script->css_scripts().size(); ++j) {
132 const char* body = NULL;
133 int body_length = 0;
134 CHECK(pickle.ReadData(&iter, &body, &body_length));
135 script->css_scripts()[j].set_external_content(
136 base::StringPiece(body, body_length));
139 if (only_inject_incognito && !script->is_incognito_enabled())
140 continue; // This script shouldn't run in an incognito tab.
142 scripts_.push_back(script.release());
145 FOR_EACH_OBSERVER(Observer,
146 observers_,
147 OnUserScriptsUpdated(changed_extensions, scripts_.get()));
148 return true;
151 scoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection(
152 int script_id,
153 blink::WebFrame* web_frame,
154 int tab_id,
155 UserScript::RunLocation run_location,
156 const GURL& document_url,
157 const Extension* extension) {
158 for (ScopedVector<UserScript>::const_iterator it = scripts_.begin();
159 it != scripts_.end();
160 ++it) {
161 if ((*it)->id() == script_id) {
162 return GetInjectionForScript(*it,
163 web_frame,
164 tab_id,
165 run_location,
166 document_url,
167 extension,
168 true /* is_declarative */);
171 return scoped_ptr<ScriptInjection>();
174 // TODO(dcheng): Scripts can't be injected on a remote frame, so this function
175 // signature needs to be updated.
176 scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript(
177 UserScript* script,
178 blink::WebFrame* web_frame,
179 int tab_id,
180 UserScript::RunLocation run_location,
181 const GURL& document_url,
182 const Extension* extension,
183 bool is_declarative) {
184 scoped_ptr<ScriptInjection> injection;
185 if (web_frame->parent() && !script->match_all_frames())
186 return injection.Pass(); // Only match subframes if the script declared it.
188 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
189 web_frame, document_url, script->match_about_blank());
191 if (!script->MatchesURL(effective_document_url))
192 return injection.Pass();
194 scoped_ptr<ScriptInjector> injector(new UserScriptInjector(script,
195 this,
196 is_declarative));
197 if (injector->CanExecuteOnFrame(
198 extension,
199 web_frame,
200 -1, // Content scripts are not tab-specific.
201 web_frame->top()->document().url()) ==
202 PermissionsData::ACCESS_DENIED) {
203 return injection.Pass();
206 bool inject_css = !script->css_scripts().empty() &&
207 run_location == UserScript::DOCUMENT_START;
208 bool inject_js =
209 !script->js_scripts().empty() && script->run_location() == run_location;
210 if (inject_css || inject_js) {
211 injection.reset(new ScriptInjection(
212 injector.Pass(),
213 web_frame->toWebLocalFrame(),
214 extension->id(),
215 run_location,
216 tab_id));
218 return injection.Pass();
221 } // namespace extensions