Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(852)

Side by Side Diff: extensions/renderer/user_script_injection_list.cc

Issue 321993003: Refactor renderer-side script injection (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Missing files Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "extensions/renderer/user_script_injection_list.h"
6
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/user_script_injection.h"
16 #include "third_party/WebKit/public/web/WebDocument.h"
17 #include "third_party/WebKit/public/web/WebFrame.h"
18 #include "url/gurl.h"
19
20 namespace extensions {
21
22 // static
23 GURL UserScriptInjectionList::GetDocumentUrlForFrame(blink::WebFrame* frame) {
24 GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
25 if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
26 data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
27 data_source_url.spec());
28 }
29
30 return data_source_url;
31 }
32
33 UserScriptInjectionList::UserScriptInjectionList() {
34 content::RenderThread::Get()->AddObserver(this);
35 }
36
37 UserScriptInjectionList::~UserScriptInjectionList() {
38 }
39
40 void UserScriptInjectionList::AddObserver(Observer* observer) {
41 observers_.AddObserver(observer);
42 }
43
44 void UserScriptInjectionList::RemoveObserver(Observer* observer) {
45 observers_.RemoveObserver(observer);
46 }
47
48 void UserScriptInjectionList::GetActiveExtensionIds(
49 std::set<std::string>* ids) const {
50 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
51 iter != scripts_.end();
52 ++iter) {
53 DCHECK(!(*iter)->extension_id().empty());
54 ids->insert((*iter)->extension_id());
55 }
56 }
57
58 void UserScriptInjectionList::GetInjections(
59 ScopedVector<ScriptInjection>* injections,
60 blink::WebFrame* web_frame,
61 int tab_id,
62 UserScript::RunLocation run_location,
63 const GURL& document_url,
64 const ExtensionSet* extensions) {
65 for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin();
66 iter != scripts_.end();
67 ++iter) {
68 const Extension* extension = extensions->GetByID((*iter)->extension_id());
69 if (!extension)
70 continue;
71 scoped_ptr<ScriptInjection> injection = GetInjectionForScript(
72 *iter, web_frame, tab_id, run_location, document_url, extension);
73 if (injection.get())
74 injections->push_back(injection.release());
75 }
76 }
77
78 bool UserScriptInjectionList::OnControlMessageReceived(
79 const IPC::Message& message) {
80 bool handled = true;
81 IPC_BEGIN_MESSAGE_MAP(UserScriptInjectionList, message)
82 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts)
83 IPC_MESSAGE_UNHANDLED(handled = false)
84 IPC_END_MESSAGE_MAP()
85 return handled;
86 }
87
88 void UserScriptInjectionList::OnUpdateUserScripts(
89 base::SharedMemoryHandle shared_memory,
90 const std::set<std::string>& changed_extensions) {
91 if (!base::SharedMemory::IsHandleValid(shared_memory)) {
92 NOTREACHED() << "Bad scripts handle";
93 return;
94 }
95
96 for (std::set<std::string>::const_iterator iter = changed_extensions.begin();
97 iter != changed_extensions.end();
98 ++iter) {
99 if (!Extension::IdIsValid(*iter)) {
100 NOTREACHED() << "Invalid extension id: " << *iter;
101 return;
102 }
103 }
104
105 if (UpdateScripts(shared_memory)) {
106 FOR_EACH_OBSERVER(Observer,
107 observers_,
108 OnUserScriptsUpdated(changed_extensions, scripts_.get()));
109 }
110 }
111
112 bool UserScriptInjectionList::UpdateScripts(
113 base::SharedMemoryHandle shared_memory) {
114 bool only_inject_incognito =
115 ExtensionsRendererClient::Get()->IsIncognitoProcess();
116
117 // Create the shared memory object (read only).
118 shared_memory_.reset(new base::SharedMemory(shared_memory, true));
119 if (!shared_memory_.get())
120 return false;
121
122 // First get the size of the memory block.
123 if (!shared_memory_->Map(sizeof(Pickle::Header)))
124 return false;
125 Pickle::Header* pickle_header =
126 reinterpret_cast<Pickle::Header*>(shared_memory_->memory());
127
128 // Now map in the rest of the block.
129 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size;
130 shared_memory_->Unmap();
131 if (!shared_memory_->Map(pickle_size))
132 return false;
133
134 // Unpickle scripts.
135 uint64 num_scripts = 0;
136 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size);
137 PickleIterator iter(pickle);
138 CHECK(pickle.ReadUInt64(&iter, &num_scripts));
139
140 scripts_.clear();
141 scripts_.reserve(num_scripts);
142 for (uint64 i = 0; i < num_scripts; ++i) {
143 scoped_ptr<UserScript> script(new UserScript());
144 script->Unpickle(pickle, &iter);
145
146 // Note that this is a pointer into shared memory. We don't own it. It gets
147 // cleared up when the last renderer or browser process drops their
148 // reference to the shared memory.
149 for (size_t j = 0; j < script->js_scripts().size(); ++j) {
150 const char* body = NULL;
151 int body_length = 0;
152 CHECK(pickle.ReadData(&iter, &body, &body_length));
153 script->js_scripts()[j].set_external_content(
154 base::StringPiece(body, body_length));
155 }
156 for (size_t j = 0; j < script->css_scripts().size(); ++j) {
157 const char* body = NULL;
158 int body_length = 0;
159 CHECK(pickle.ReadData(&iter, &body, &body_length));
160 script->css_scripts()[j].set_external_content(
161 base::StringPiece(body, body_length));
162 }
163
164 if (only_inject_incognito && !script->is_incognito_enabled())
165 continue; // This script shouldn't run in an incognito tab.
166
167 scripts_.push_back(script.release());
168 }
169
170 return true;
171 }
not at google - send to devlin 2014/06/15 23:53:38 blank line
Devlin 2014/06/16 18:11:17 Done.
172 scoped_ptr<ScriptInjection> UserScriptInjectionList::GetInjectionForScript(
173 UserScript* script,
174 blink::WebFrame* web_frame,
175 int tab_id,
176 UserScript::RunLocation run_location,
177 const GURL& document_url,
178 const Extension* extension) {
179 scoped_ptr<ScriptInjection> injection;
180 if (web_frame->parent() && !script->match_all_frames())
181 return injection.Pass(); // Only match subframes if the script declared it.
182
183 // Content scripts are not tab-specific.
184 static const int kNoTabId = -1;
185 // We don't have a process id in this context.
186 static const int kNoProcessId = -1;
187
188 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
189 web_frame, document_url, script->match_about_blank());
190
191 if (!script->MatchesURL(effective_document_url))
192 return injection.Pass();
193
194 if (!extension->permissions_data()->CanRunContentScriptOnPage(
195 extension,
196 effective_document_url,
197 web_frame->top()->document().url(),
198 kNoTabId,
199 kNoProcessId,
not at google - send to devlin 2014/06/15 23:53:38 inling -1 with those comments "Content scripts are
Devlin 2014/06/16 18:11:17 Done.
200 NULL /* ignore error */)) {
201 return injection.Pass();
202 }
203
204 bool inject_css = !script->css_scripts().empty() &&
205 run_location == UserScript::DOCUMENT_START;
206 bool inject_js =
207 !script->js_scripts().empty() && script->run_location() == run_location;
not at google - send to devlin 2014/06/15 23:53:38 this mixing of UserScriptInjection getting its pro
Devlin 2014/06/16 18:11:17 Caching script id is done because when we need to
208 if (inject_css || inject_js) {
209 injection.reset(new UserScriptInjection(web_frame,
210 extension->id(),
211 run_location,
212 tab_id,
213 this,
214 script,
215 inject_js,
216 inject_css));
217 }
218 return injection.Pass();
219 }
220
221 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698