Task Manager: Remove goat teleporter.
[chromium-blink-merge.git] / extensions / renderer / user_script_set.cc
blobc14abd1e55871c3ff77073958a9ebd60c4ed1cff
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_messages.h"
11 #include "extensions/common/extension_set.h"
12 #include "extensions/common/permissions/permissions_data.h"
13 #include "extensions/renderer/extensions_renderer_client.h"
14 #include "extensions/renderer/script_context.h"
15 #include "extensions/renderer/script_injection.h"
16 #include "extensions/renderer/user_script_injector.h"
17 #include "third_party/WebKit/public/web/WebDocument.h"
18 #include "third_party/WebKit/public/web/WebFrame.h"
19 #include "url/gurl.h"
21 namespace extensions {
23 namespace {
25 GURL GetDocumentUrlForFrame(blink::WebFrame* frame) {
26 GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
27 if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
28 data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
29 data_source_url.spec());
32 return data_source_url;
35 } // namespace
37 UserScriptSet::UserScriptSet(const ExtensionSet* extensions)
38 : extensions_(extensions) {
41 UserScriptSet::~UserScriptSet() {
44 void UserScriptSet::AddObserver(Observer* observer) {
45 observers_.AddObserver(observer);
48 void UserScriptSet::RemoveObserver(Observer* observer) {
49 observers_.RemoveObserver(observer);
52 void UserScriptSet::GetActiveExtensionIds(
53 std::set<std::string>* ids) const {
54 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
55 iter != scripts_.end();
56 ++iter) {
57 DCHECK(!(*iter)->extension_id().empty());
58 ids->insert((*iter)->extension_id());
62 void UserScriptSet::GetInjections(
63 ScopedVector<ScriptInjection>* injections,
64 blink::WebFrame* web_frame,
65 int tab_id,
66 UserScript::RunLocation run_location) {
67 GURL document_url = GetDocumentUrlForFrame(web_frame);
68 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
69 iter != scripts_.end();
70 ++iter) {
71 const Extension* extension = extensions_->GetByID((*iter)->extension_id());
72 if (!extension)
73 continue;
74 scoped_ptr<ScriptInjection> injection = GetInjectionForScript(
75 *iter,
76 web_frame,
77 tab_id,
78 run_location,
79 document_url,
80 extension,
81 false /* is_declarative */);
82 if (injection.get())
83 injections->push_back(injection.release());
87 bool UserScriptSet::UpdateUserScripts(
88 base::SharedMemoryHandle shared_memory,
89 const std::set<std::string>& changed_extensions) {
90 bool only_inject_incognito =
91 ExtensionsRendererClient::Get()->IsIncognitoProcess();
93 // Create the shared memory object (read only).
94 shared_memory_.reset(new base::SharedMemory(shared_memory, true));
95 if (!shared_memory_.get())
96 return false;
98 // First get the size of the memory block.
99 if (!shared_memory_->Map(sizeof(Pickle::Header)))
100 return false;
101 Pickle::Header* pickle_header =
102 reinterpret_cast<Pickle::Header*>(shared_memory_->memory());
104 // Now map in the rest of the block.
105 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size;
106 shared_memory_->Unmap();
107 if (!shared_memory_->Map(pickle_size))
108 return false;
110 // Unpickle scripts.
111 uint64 num_scripts = 0;
112 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size);
113 PickleIterator iter(pickle);
114 CHECK(pickle.ReadUInt64(&iter, &num_scripts));
116 scripts_.clear();
117 scripts_.reserve(num_scripts);
118 for (uint64 i = 0; i < num_scripts; ++i) {
119 scoped_ptr<UserScript> script(new UserScript());
120 script->Unpickle(pickle, &iter);
122 // Note that this is a pointer into shared memory. We don't own it. It gets
123 // cleared up when the last renderer or browser process drops their
124 // reference to the shared memory.
125 for (size_t j = 0; j < script->js_scripts().size(); ++j) {
126 const char* body = NULL;
127 int body_length = 0;
128 CHECK(pickle.ReadData(&iter, &body, &body_length));
129 script->js_scripts()[j].set_external_content(
130 base::StringPiece(body, body_length));
132 for (size_t j = 0; j < script->css_scripts().size(); ++j) {
133 const char* body = NULL;
134 int body_length = 0;
135 CHECK(pickle.ReadData(&iter, &body, &body_length));
136 script->css_scripts()[j].set_external_content(
137 base::StringPiece(body, body_length));
140 if (only_inject_incognito && !script->is_incognito_enabled())
141 continue; // This script shouldn't run in an incognito tab.
143 scripts_.push_back(script.release());
146 FOR_EACH_OBSERVER(Observer,
147 observers_,
148 OnUserScriptsUpdated(changed_extensions, scripts_.get()));
149 return true;
152 scoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection(
153 int script_id,
154 blink::WebFrame* web_frame,
155 int tab_id,
156 UserScript::RunLocation run_location,
157 const GURL& document_url,
158 const Extension* extension) {
159 for (ScopedVector<UserScript>::const_iterator it = scripts_.begin();
160 it != scripts_.end();
161 ++it) {
162 if ((*it)->id() == script_id) {
163 return GetInjectionForScript(*it,
164 web_frame,
165 tab_id,
166 run_location,
167 document_url,
168 extension,
169 true /* is_declarative */);
172 return scoped_ptr<ScriptInjection>();
175 scoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript(
176 UserScript* script,
177 blink::WebFrame* web_frame,
178 int tab_id,
179 UserScript::RunLocation run_location,
180 const GURL& document_url,
181 const Extension* extension,
182 bool is_declarative) {
183 scoped_ptr<ScriptInjection> injection;
184 if (web_frame->parent() && !script->match_all_frames())
185 return injection.Pass(); // Only match subframes if the script declared it.
187 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
188 web_frame, document_url, script->match_about_blank());
190 if (!script->MatchesURL(effective_document_url))
191 return injection.Pass();
193 scoped_ptr<ScriptInjector> injector(new UserScriptInjector(script,
194 this,
195 is_declarative));
196 if (injector->CanExecuteOnFrame(
197 extension,
198 web_frame,
199 -1, // Content scripts are not tab-specific.
200 web_frame->top()->document().url()) ==
201 PermissionsData::ACCESS_DENIED) {
202 return injection.Pass();
205 bool inject_css = !script->css_scripts().empty() &&
206 run_location == UserScript::DOCUMENT_START;
207 bool inject_js =
208 !script->js_scripts().empty() && script->run_location() == run_location;
209 if (inject_css || inject_js) {
210 injection.reset(new ScriptInjection(
211 injector.Pass(),
212 web_frame,
213 extension->id(),
214 run_location,
215 tab_id));
217 return injection.Pass();
220 } // namespace extensions