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

Side by Side Diff: chrome/browser/extensions/user_script_master.cc

Issue 7552028: Injected CSS localization fix (see bug no.) (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Cleaned up old unused function. Created 9 years, 4 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/user_script_master.h" 5 #include "chrome/browser/extensions/user_script_master.h"
6 6
7 #include <map>
7 #include <string> 8 #include <string>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/file_path.h" 11 #include "base/file_path.h"
11 #include "base/file_util.h" 12 #include "base/file_util.h"
12 #include "base/pickle.h" 13 #include "base/pickle.h"
13 #include "base/stl_util.h" 14 #include "base/stl_util.h"
14 #include "base/string_util.h" 15 #include "base/string_util.h"
15 #include "base/threading/thread.h" 16 #include "base/threading/thread.h"
16 #include "base/version.h" 17 #include "base/version.h"
17 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/chrome_notification_types.h" 20 #include "chrome/common/chrome_notification_types.h"
20 #include "chrome/common/extensions/extension.h" 21 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/extension_messages.h" 22 #include "chrome/common/extensions/extension_file_util.h"
23 #include "chrome/common/extensions/extension_message_bundle.h"
22 #include "chrome/common/extensions/extension_resource.h" 24 #include "chrome/common/extensions/extension_resource.h"
25 #include "chrome/common/extensions/extension_set.h"
23 #include "content/browser/renderer_host/render_process_host.h" 26 #include "content/browser/renderer_host/render_process_host.h"
24 #include "content/common/notification_service.h" 27 #include "content/common/notification_service.h"
25 28
26 // Helper function to parse greasesmonkey headers 29 // Helper function to parse greasesmonkey headers
27 static bool GetDeclarationValue(const base::StringPiece& line, 30 static bool GetDeclarationValue(const base::StringPiece& line,
28 const base::StringPiece& prefix, 31 const base::StringPiece& prefix,
29 std::string* value) { 32 std::string* value) {
30 base::StringPiece::size_type index = line.find(prefix); 33 base::StringPiece::size_type index = line.find(prefix);
31 if (index == base::StringPiece::npos) 34 if (index == base::StringPiece::npos)
32 return false; 35 return false;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 133
131 // If no patterns were specified, default to @include *. This is what 134 // If no patterns were specified, default to @include *. This is what
132 // Greasemonkey does. 135 // Greasemonkey does.
133 if (script->globs().empty() && script->url_patterns().is_empty()) 136 if (script->globs().empty() && script->url_patterns().is_empty())
134 script->add_glob("*"); 137 script->add_glob("*");
135 138
136 return true; 139 return true;
137 } 140 }
138 141
139 void UserScriptMaster::ScriptReloader::StartLoad( 142 void UserScriptMaster::ScriptReloader::StartLoad(
140 const UserScriptList& user_scripts) { 143 const UserScriptList& user_scripts,
144 const ExtensionsInfo& extensions_info_) {
141 // Add a reference to ourselves to keep ourselves alive while we're running. 145 // Add a reference to ourselves to keep ourselves alive while we're running.
142 // Balanced by NotifyMaster(). 146 // Balanced by NotifyMaster().
143 AddRef(); 147 AddRef();
148
149 this->extensions_info_ = extensions_info_;
144 BrowserThread::PostTask( 150 BrowserThread::PostTask(
145 BrowserThread::FILE, FROM_HERE, 151 BrowserThread::FILE, FROM_HERE,
146 NewRunnableMethod( 152 NewRunnableMethod(
147 this, &UserScriptMaster::ScriptReloader::RunLoad, user_scripts)); 153 this, &UserScriptMaster::ScriptReloader::RunLoad, user_scripts));
148 } 154 }
149 155
150 void UserScriptMaster::ScriptReloader::NotifyMaster( 156 void UserScriptMaster::ScriptReloader::NotifyMaster(
151 base::SharedMemory* memory) { 157 base::SharedMemory* memory) {
152 // The master went away, so these new scripts aren't useful anymore. 158 // The master went away, so these new scripts aren't useful anymore.
153 if (!master_) 159 if (!master_)
154 delete memory; 160 delete memory;
155 else 161 else
156 master_->NewScriptsAvailable(memory); 162 master_->NewScriptsAvailable(memory);
157 163
158 // Drop our self-reference. 164 // Drop our self-reference.
159 // Balances StartLoad(). 165 // Balances StartLoad().
160 Release(); 166 Release();
161 } 167 }
162 168
163 static bool LoadScriptContent(UserScript::File* script_file) { 169 static bool LoadScriptContent(UserScript::File* script_file,
170 const SubstitutionMap* localization_messages) {
164 std::string content; 171 std::string content;
165 const FilePath& path = ExtensionResource::GetFilePath( 172 const FilePath& path = ExtensionResource::GetFilePath(
166 script_file->extension_root(), script_file->relative_path()); 173 script_file->extension_root(), script_file->relative_path());
167 if (path.empty()) { 174 if (path.empty()) {
168 LOG(WARNING) << "Failed to get file path to " 175 LOG(WARNING) << "Failed to get file path to "
169 << script_file->relative_path().value() << " from " 176 << script_file->relative_path().value() << " from "
170 << script_file->extension_root().value(); 177 << script_file->extension_root().value();
171 return false; 178 return false;
172 } 179 }
173 if (!file_util::ReadFileToString(path, &content)) { 180 if (!file_util::ReadFileToString(path, &content)) {
174 LOG(WARNING) << "Failed to load user script file: " << path.value(); 181 LOG(WARNING) << "Failed to load user script file: " << path.value();
175 return false; 182 return false;
176 } 183 }
177 184
185 // Localize the content.
186 if (localization_messages) {
187 std::string error;
188 ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary(
189 *localization_messages, &content, &error);
190 if (!error.empty()) {
191 LOG(WARNING) << "Failed to replace messages in script: " << error;
192 }
193 }
194
178 // Remove BOM from the content. 195 // Remove BOM from the content.
179 std::string::size_type index = content.find(kUtf8ByteOrderMark); 196 std::string::size_type index = content.find(kUtf8ByteOrderMark);
180 if (index == 0) { 197 if (index == 0) {
181 script_file->set_content(content.substr(strlen(kUtf8ByteOrderMark))); 198 script_file->set_content(content.substr(strlen(kUtf8ByteOrderMark)));
182 } else { 199 } else {
183 script_file->set_content(content); 200 script_file->set_content(content);
184 } 201 }
185 202
186 return true; 203 return true;
187 } 204 }
188 205
189 // static
190 void UserScriptMaster::ScriptReloader::LoadUserScripts( 206 void UserScriptMaster::ScriptReloader::LoadUserScripts(
191 UserScriptList* user_scripts) { 207 UserScriptList* user_scripts) {
192 for (size_t i = 0; i < user_scripts->size(); ++i) { 208 for (size_t i = 0; i < user_scripts->size(); ++i) {
193 UserScript& script = user_scripts->at(i); 209 UserScript& script = user_scripts->at(i);
210 scoped_ptr<SubstitutionMap> localization_messages(
211 GetLocalizationMessages(script.extension_id()));
194 for (size_t k = 0; k < script.js_scripts().size(); ++k) { 212 for (size_t k = 0; k < script.js_scripts().size(); ++k) {
195 UserScript::File& script_file = script.js_scripts()[k]; 213 UserScript::File& script_file = script.js_scripts()[k];
196 if (script_file.GetContent().empty()) 214 if (script_file.GetContent().empty())
197 LoadScriptContent(&script_file); 215 LoadScriptContent(&script_file, NULL);
198 } 216 }
199 for (size_t k = 0; k < script.css_scripts().size(); ++k) { 217 for (size_t k = 0; k < script.css_scripts().size(); ++k) {
200 UserScript::File& script_file = script.css_scripts()[k]; 218 UserScript::File& script_file = script.css_scripts()[k];
201 if (script_file.GetContent().empty()) 219 if (script_file.GetContent().empty())
202 LoadScriptContent(&script_file); 220 LoadScriptContent(&script_file, localization_messages.get());
203 } 221 }
204 } 222 }
205 } 223 }
206 224
225 SubstitutionMap* UserScriptMaster::ScriptReloader::GetLocalizationMessages(
226 std::string extension_id) {
227 if (extensions_info_.find(extension_id) == extensions_info_.end()) {
228 return NULL;
229 }
230
231 return extension_file_util::LoadExtensionMessageBundleSubstitutionMap(
232 extensions_info_[extension_id].first,
233 extension_id,
234 extensions_info_[extension_id].second);
235 }
236
207 // Pickle user scripts and return pointer to the shared memory. 237 // Pickle user scripts and return pointer to the shared memory.
208 static base::SharedMemory* Serialize(const UserScriptList& scripts) { 238 static base::SharedMemory* Serialize(const UserScriptList& scripts) {
209 Pickle pickle; 239 Pickle pickle;
210 pickle.WriteSize(scripts.size()); 240 pickle.WriteSize(scripts.size());
211 for (size_t i = 0; i < scripts.size(); i++) { 241 for (size_t i = 0; i < scripts.size(); i++) {
212 const UserScript& script = scripts[i]; 242 const UserScript& script = scripts[i];
213 // TODO(aa): This can be replaced by sending content script metadata to 243 // TODO(aa): This can be replaced by sending content script metadata to
214 // renderers along with other extension data in ExtensionMsg_Loaded. 244 // renderers along with other extension data in ExtensionMsg_Loaded.
215 // See crbug.com/70516. 245 // See crbug.com/70516.
216 script.Pickle(&pickle); 246 script.Pickle(&pickle);
(...skipping 14 matching lines...) Expand all
231 261
232 if (!shared_memory->CreateAndMapAnonymous(pickle.size())) 262 if (!shared_memory->CreateAndMapAnonymous(pickle.size()))
233 return NULL; 263 return NULL;
234 264
235 // Copy the pickle to shared memory. 265 // Copy the pickle to shared memory.
236 memcpy(shared_memory->memory(), pickle.data(), pickle.size()); 266 memcpy(shared_memory->memory(), pickle.data(), pickle.size());
237 267
238 return shared_memory.release(); 268 return shared_memory.release();
239 } 269 }
240 270
241 // This method will be called from the file thread 271 // This method will be called on the file thread.
242 void UserScriptMaster::ScriptReloader::RunLoad( 272 void UserScriptMaster::ScriptReloader::RunLoad(
243 const UserScriptList& user_scripts) { 273 const UserScriptList& user_scripts) {
244 LoadUserScripts(const_cast<UserScriptList*>(&user_scripts)); 274 LoadUserScripts(const_cast<UserScriptList*>(&user_scripts));
245 275
246 // Scripts now contains list of up-to-date scripts. Load the content in the 276 // Scripts now contains list of up-to-date scripts. Load the content in the
247 // shared memory and let the master know it's ready. We need to post the task 277 // shared memory and let the master know it's ready. We need to post the task
248 // back even if no scripts ware found to balance the AddRef/Release calls 278 // back even if no scripts ware found to balance the AddRef/Release calls.
249 BrowserThread::PostTask( 279 BrowserThread::PostTask(
250 master_thread_id_, FROM_HERE, 280 master_thread_id_, FROM_HERE,
251 NewRunnableMethod( 281 NewRunnableMethod(
252 this, &ScriptReloader::NotifyMaster, Serialize(user_scripts))); 282 this, &ScriptReloader::NotifyMaster, Serialize(user_scripts)));
253 } 283 }
254 284
255 285
256 UserScriptMaster::UserScriptMaster(Profile* profile) 286 UserScriptMaster::UserScriptMaster(Profile* profile)
257 : extensions_service_ready_(false), 287 : extensions_service_ready_(false),
258 pending_load_(false), 288 pending_load_(false),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 const NotificationDetails& details) { 334 const NotificationDetails& details) {
305 bool should_start_load = false; 335 bool should_start_load = false;
306 switch (type) { 336 switch (type) {
307 case chrome::NOTIFICATION_EXTENSIONS_READY: 337 case chrome::NOTIFICATION_EXTENSIONS_READY:
308 extensions_service_ready_ = true; 338 extensions_service_ready_ = true;
309 should_start_load = true; 339 should_start_load = true;
310 break; 340 break;
311 case chrome::NOTIFICATION_EXTENSION_LOADED: { 341 case chrome::NOTIFICATION_EXTENSION_LOADED: {
312 // Add any content scripts inside the extension. 342 // Add any content scripts inside the extension.
313 const Extension* extension = Details<const Extension>(details).ptr(); 343 const Extension* extension = Details<const Extension>(details).ptr();
344 extensions_info_[extension->id()] =
345 ExtensionSet::ExtensionPathAndDefaultLocale(
346 extension->path(), extension->default_locale());
314 bool incognito_enabled = profile_->GetExtensionService()-> 347 bool incognito_enabled = profile_->GetExtensionService()->
315 IsIncognitoEnabled(extension->id()); 348 IsIncognitoEnabled(extension->id());
316 const UserScriptList& scripts = extension->content_scripts(); 349 const UserScriptList& scripts = extension->content_scripts();
317 for (UserScriptList::const_iterator iter = scripts.begin(); 350 for (UserScriptList::const_iterator iter = scripts.begin();
318 iter != scripts.end(); ++iter) { 351 iter != scripts.end(); ++iter) {
319 user_scripts_.push_back(*iter); 352 user_scripts_.push_back(*iter);
320 user_scripts_.back().set_incognito_enabled(incognito_enabled); 353 user_scripts_.back().set_incognito_enabled(incognito_enabled);
321 } 354 }
322 if (extensions_service_ready_) 355 if (extensions_service_ready_)
323 should_start_load = true; 356 should_start_load = true;
324 break; 357 break;
325 } 358 }
326 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 359 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
327 // Remove any content scripts. 360 // Remove any content scripts.
328 const Extension* extension = 361 const Extension* extension =
329 Details<UnloadedExtensionInfo>(details)->extension; 362 Details<UnloadedExtensionInfo>(details)->extension;
363 extensions_info_.erase(extension->id());
330 UserScriptList new_user_scripts; 364 UserScriptList new_user_scripts;
331 for (UserScriptList::iterator iter = user_scripts_.begin(); 365 for (UserScriptList::iterator iter = user_scripts_.begin();
332 iter != user_scripts_.end(); ++iter) { 366 iter != user_scripts_.end(); ++iter) {
333 if (iter->extension_id() != extension->id()) 367 if (iter->extension_id() != extension->id())
334 new_user_scripts.push_back(*iter); 368 new_user_scripts.push_back(*iter);
335 } 369 }
336 user_scripts_ = new_user_scripts; 370 user_scripts_ = new_user_scripts;
337 should_start_load = true; 371 should_start_load = true;
338 372
339 // TODO(aa): Do we want to do something smarter for the scripts that have 373 // TODO(aa): Do we want to do something smarter for the scripts that have
(...skipping 17 matching lines...) Expand all
357 } else { 391 } else {
358 StartLoad(); 392 StartLoad();
359 } 393 }
360 } 394 }
361 } 395 }
362 396
363 void UserScriptMaster::StartLoad() { 397 void UserScriptMaster::StartLoad() {
364 if (!script_reloader_) 398 if (!script_reloader_)
365 script_reloader_ = new ScriptReloader(this); 399 script_reloader_ = new ScriptReloader(this);
366 400
367 script_reloader_->StartLoad(user_scripts_); 401 script_reloader_->StartLoad(user_scripts_, extensions_info_);
368 } 402 }
369 403
370 void UserScriptMaster::SendUpdate(RenderProcessHost* process, 404 void UserScriptMaster::SendUpdate(RenderProcessHost* process,
371 base::SharedMemory* shared_memory) { 405 base::SharedMemory* shared_memory) {
372 Profile* profile = Profile::FromBrowserContext(process->browser_context()); 406 Profile* profile = Profile::FromBrowserContext(process->browser_context());
373 // Make sure we only send user scripts to processes in our profile. 407 // Make sure we only send user scripts to processes in our profile.
374 if (!profile_->IsSameProfile(profile)) 408 if (!profile_->IsSameProfile(profile))
375 return; 409 return;
376 410
377 // If the process is being started asynchronously, early return. We'll end up 411 // If the process is being started asynchronously, early return. We'll end up
378 // calling InitUserScripts when it's created which will call this again. 412 // calling InitUserScripts when it's created which will call this again.
379 base::ProcessHandle handle = process->GetHandle(); 413 base::ProcessHandle handle = process->GetHandle();
380 if (!handle) 414 if (!handle)
381 return; 415 return;
382 416
383 base::SharedMemoryHandle handle_for_process; 417 base::SharedMemoryHandle handle_for_process;
384 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) 418 if (!shared_memory->ShareToProcess(handle, &handle_for_process))
385 return; // This can legitimately fail if the renderer asserts at startup. 419 return; // This can legitimately fail if the renderer asserts at startup.
386 420
387 if (base::SharedMemory::IsHandleValid(handle_for_process)) 421 if (base::SharedMemory::IsHandleValid(handle_for_process))
388 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); 422 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process));
389 } 423 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/user_script_master.h ('k') | chrome/browser/extensions/user_script_master_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698