OLD | NEW |
---|---|
(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 | |
OLD | NEW |