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

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: Removed race by dropping to IO thread first, before FILE thread. 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
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) {
141 // Add a reference to ourselves to keep ourselves alive while we're running. 144 // Add a reference to ourselves to keep ourselves alive while we're running.
142 // Balanced by NotifyMaster(). 145 // Balanced by NotifyMaster().
143 AddRef(); 146 AddRef();
147
148 const ExtensionInfoMap* info_map = NULL;
149 // Gather extensions information needed for localization.
150 if (master_ && master_->profile_ &&
151 master_->profile_->GetExtensionInfoMap()) {
152 info_map = master_->profile_->GetExtensionInfoMap();
153 // Add a reference to the info_map to keep it alive while we're in the IO
154 // thread iterating through the available extensions set.
155 // Balanced by GatherExtensionsInfo().
156 info_map->AddRef();
157 }
144 BrowserThread::PostTask( 158 BrowserThread::PostTask(
145 BrowserThread::FILE, FROM_HERE, 159 BrowserThread::IO, FROM_HERE,
146 NewRunnableMethod( 160 NewRunnableMethod(
147 this, &UserScriptMaster::ScriptReloader::RunLoad, user_scripts)); 161 this, &UserScriptMaster::ScriptReloader::GatherExtensionsInfo,
162 info_map, user_scripts));
148 } 163 }
149 164
165
150 void UserScriptMaster::ScriptReloader::NotifyMaster( 166 void UserScriptMaster::ScriptReloader::NotifyMaster(
151 base::SharedMemory* memory) { 167 base::SharedMemory* memory) {
152 // The master went away, so these new scripts aren't useful anymore. 168 // The master went away, so these new scripts aren't useful anymore.
153 if (!master_) 169 if (!master_)
154 delete memory; 170 delete memory;
155 else 171 else
156 master_->NewScriptsAvailable(memory); 172 master_->NewScriptsAvailable(memory);
157 173
158 // Drop our self-reference. 174 // Drop our self-reference.
159 // Balances StartLoad(). 175 // Balances StartLoad().
160 Release(); 176 Release();
161 } 177 }
162 178
163 static bool LoadScriptContent(UserScript::File* script_file) { 179 static bool LoadScriptContent(UserScript::File* script_file,
180 const SubstitutionMap* localization_messages) {
164 std::string content; 181 std::string content;
165 const FilePath& path = ExtensionResource::GetFilePath( 182 const FilePath& path = ExtensionResource::GetFilePath(
166 script_file->extension_root(), script_file->relative_path()); 183 script_file->extension_root(), script_file->relative_path());
167 if (path.empty()) { 184 if (path.empty()) {
168 LOG(WARNING) << "Failed to get file path to " 185 LOG(WARNING) << "Failed to get file path to "
169 << script_file->relative_path().value() << " from " 186 << script_file->relative_path().value() << " from "
170 << script_file->extension_root().value(); 187 << script_file->extension_root().value();
171 return false; 188 return false;
172 } 189 }
173 if (!file_util::ReadFileToString(path, &content)) { 190 if (!file_util::ReadFileToString(path, &content)) {
174 LOG(WARNING) << "Failed to load user script file: " << path.value(); 191 LOG(WARNING) << "Failed to load user script file: " << path.value();
175 return false; 192 return false;
176 } 193 }
177 194
195 // Localize the content.
196 if (localization_messages) {
197 std::string error;
198 ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary(
199 *localization_messages, &content, &error);
200 if (!error.empty()) {
201 LOG(WARNING) << "Failed to replace messages in script: " << error;
202 }
203 }
204
178 // Remove BOM from the content. 205 // Remove BOM from the content.
179 std::string::size_type index = content.find(kUtf8ByteOrderMark); 206 std::string::size_type index = content.find(kUtf8ByteOrderMark);
180 if (index == 0) { 207 if (index == 0) {
181 script_file->set_content(content.substr(strlen(kUtf8ByteOrderMark))); 208 script_file->set_content(content.substr(strlen(kUtf8ByteOrderMark)));
182 } else { 209 } else {
183 script_file->set_content(content); 210 script_file->set_content(content);
184 } 211 }
185 212
186 return true; 213 return true;
187 } 214 }
188 215
189 // static
190 void UserScriptMaster::ScriptReloader::LoadUserScripts( 216 void UserScriptMaster::ScriptReloader::LoadUserScripts(
191 UserScriptList* user_scripts) { 217 UserScriptList* user_scripts) {
192 for (size_t i = 0; i < user_scripts->size(); ++i) { 218 for (size_t i = 0; i < user_scripts->size(); ++i) {
193 UserScript& script = user_scripts->at(i); 219 UserScript& script = user_scripts->at(i);
220 scoped_ptr<SubstitutionMap> localization_messages(
221 GetLocalizationMessages(script.extension_id()));
194 for (size_t k = 0; k < script.js_scripts().size(); ++k) { 222 for (size_t k = 0; k < script.js_scripts().size(); ++k) {
195 UserScript::File& script_file = script.js_scripts()[k]; 223 UserScript::File& script_file = script.js_scripts()[k];
196 if (script_file.GetContent().empty()) 224 if (script_file.GetContent().empty())
197 LoadScriptContent(&script_file); 225 LoadScriptContent(&script_file, NULL);
198 } 226 }
199 for (size_t k = 0; k < script.css_scripts().size(); ++k) { 227 for (size_t k = 0; k < script.css_scripts().size(); ++k) {
200 UserScript::File& script_file = script.css_scripts()[k]; 228 UserScript::File& script_file = script.css_scripts()[k];
201 if (script_file.GetContent().empty()) 229 if (script_file.GetContent().empty())
202 LoadScriptContent(&script_file); 230 LoadScriptContent(&script_file, localization_messages.get());
203 } 231 }
204 } 232 }
205 } 233 }
206 234
235 SubstitutionMap* UserScriptMaster::ScriptReloader::GetLocalizationMessages(
236 std::string extension_id) {
237 if (extensions_info_.find(extension_id) == extensions_info_.end()) {
238 return NULL;
239 }
240
241 return extension_file_util::LoadExtensionMessageBundleSubstitutionMap(
242 extensions_info_[extension_id].first,
243 extension_id,
244 extensions_info_[extension_id].second);
245 }
246
207 // Pickle user scripts and return pointer to the shared memory. 247 // Pickle user scripts and return pointer to the shared memory.
208 static base::SharedMemory* Serialize(const UserScriptList& scripts) { 248 static base::SharedMemory* Serialize(const UserScriptList& scripts) {
209 Pickle pickle; 249 Pickle pickle;
210 pickle.WriteSize(scripts.size()); 250 pickle.WriteSize(scripts.size());
211 for (size_t i = 0; i < scripts.size(); i++) { 251 for (size_t i = 0; i < scripts.size(); i++) {
212 const UserScript& script = scripts[i]; 252 const UserScript& script = scripts[i];
213 // TODO(aa): This can be replaced by sending content script metadata to 253 // TODO(aa): This can be replaced by sending content script metadata to
214 // renderers along with other extension data in ExtensionMsg_Loaded. 254 // renderers along with other extension data in ExtensionMsg_Loaded.
215 // See crbug.com/70516. 255 // See crbug.com/70516.
216 script.Pickle(&pickle); 256 script.Pickle(&pickle);
(...skipping 14 matching lines...) Expand all
231 271
232 if (!shared_memory->CreateAndMapAnonymous(pickle.size())) 272 if (!shared_memory->CreateAndMapAnonymous(pickle.size()))
233 return NULL; 273 return NULL;
234 274
235 // Copy the pickle to shared memory. 275 // Copy the pickle to shared memory.
236 memcpy(shared_memory->memory(), pickle.data(), pickle.size()); 276 memcpy(shared_memory->memory(), pickle.data(), pickle.size());
237 277
238 return shared_memory.release(); 278 return shared_memory.release();
239 } 279 }
240 280
281 // This method will be called from the IO thread
282 void UserScriptMaster::ScriptReloader::GatherExtensionsInfo(
283 const ExtensionInfoMap* info_map,
284 const UserScriptList& user_scripts) {
Nebojša Ćirić 2011/08/19 21:19:15 //... called on the IO thread Can this be const a
adriansc 2011/08/19 21:48:08 Done.
285 if (info_map) {
286 info_map->extensions().GetExtensionsPathAndDefaultLocale(&extensions_info_);
287 // Drop the reference on the ExtensionInfoMap object after reading from it.
288 // Balances StartLoad().
289 info_map->Release();
290 }
291 BrowserThread::PostTask(
292 BrowserThread::FILE, FROM_HERE,
293 NewRunnableMethod(
294 this, &UserScriptMaster::ScriptReloader::RunLoad, user_scripts));
295 }
296
241 // This method will be called from the file thread 297 // This method will be called from the file thread
242 void UserScriptMaster::ScriptReloader::RunLoad( 298 void UserScriptMaster::ScriptReloader::RunLoad(
243 const UserScriptList& user_scripts) { 299 const UserScriptList& user_scripts) {
244 LoadUserScripts(const_cast<UserScriptList*>(&user_scripts)); 300 LoadUserScripts(const_cast<UserScriptList*>(&user_scripts));
245 301
246 // Scripts now contains list of up-to-date scripts. Load the content in the 302 // 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 303 // 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 304 // back even if no scripts ware found to balance the AddRef/Release calls
249 BrowserThread::PostTask( 305 BrowserThread::PostTask(
250 master_thread_id_, FROM_HERE, 306 master_thread_id_, FROM_HERE,
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 if (!handle) 436 if (!handle)
381 return; 437 return;
382 438
383 base::SharedMemoryHandle handle_for_process; 439 base::SharedMemoryHandle handle_for_process;
384 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) 440 if (!shared_memory->ShareToProcess(handle, &handle_for_process))
385 return; // This can legitimately fail if the renderer asserts at startup. 441 return; // This can legitimately fail if the renderer asserts at startup.
386 442
387 if (base::SharedMemory::IsHandleValid(handle_for_process)) 443 if (base::SharedMemory::IsHandleValid(handle_for_process))
388 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process)); 444 process->Send(new ExtensionMsg_UpdateUserScripts(handle_for_process));
389 } 445 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698