| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "extensions/browser/user_script_loader.h" | 5 #include "extensions/browser/user_script_loader.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 using content::BrowserThread; | 24 using content::BrowserThread; |
| 25 using content::BrowserContext; | 25 using content::BrowserContext; |
| 26 | 26 |
| 27 namespace extensions { | 27 namespace extensions { |
| 28 | 28 |
| 29 namespace { | 29 namespace { |
| 30 | 30 |
| 31 #if DCHECK_IS_ON() | 31 #if DCHECK_IS_ON() |
| 32 bool AreScriptsUnique(const UserScriptList& scripts) { | 32 bool AreScriptsUnique(const UserScriptList& scripts) { |
| 33 std::set<int> script_ids; | 33 std::set<int> script_ids; |
| 34 for (const UserScript& script : scripts) { | 34 for (const std::unique_ptr<UserScript>& script : scripts) { |
| 35 if (script_ids.count(script.id())) | 35 if (script_ids.count(script->id())) |
| 36 return false; | 36 return false; |
| 37 script_ids.insert(script.id()); | 37 script_ids.insert(script->id()); |
| 38 } | 38 } |
| 39 return true; | 39 return true; |
| 40 } | 40 } |
| 41 #endif // DCHECK_IS_ON() | 41 #endif // DCHECK_IS_ON() |
| 42 | 42 |
| 43 // Helper function to parse greasesmonkey headers | 43 // Helper function to parse greasesmonkey headers |
| 44 bool GetDeclarationValue(const base::StringPiece& line, | 44 bool GetDeclarationValue(const base::StringPiece& line, |
| 45 const base::StringPiece& prefix, | 45 const base::StringPiece& prefix, |
| 46 std::string* value) { | 46 std::string* value) { |
| 47 base::StringPiece::size_type index = line.find(prefix); | 47 base::StringPiece::size_type index = line.find(prefix); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 weak_factory_(this) { | 166 weak_factory_(this) { |
| 167 registrar_.Add(this, | 167 registrar_.Add(this, |
| 168 content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 168 content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 169 content::NotificationService::AllBrowserContextsAndSources()); | 169 content::NotificationService::AllBrowserContextsAndSources()); |
| 170 } | 170 } |
| 171 | 171 |
| 172 UserScriptLoader::~UserScriptLoader() { | 172 UserScriptLoader::~UserScriptLoader() { |
| 173 FOR_EACH_OBSERVER(Observer, observers_, OnUserScriptLoaderDestroyed(this)); | 173 FOR_EACH_OBSERVER(Observer, observers_, OnUserScriptLoaderDestroyed(this)); |
| 174 } | 174 } |
| 175 | 175 |
| 176 void UserScriptLoader::AddScripts(const UserScriptList& scripts) { | 176 void UserScriptLoader::AddScripts(std::unique_ptr<UserScriptList> scripts) { |
| 177 #if DCHECK_IS_ON() | 177 #if DCHECK_IS_ON() |
| 178 // |scripts| with non-unique IDs will work, but that would indicate we are | 178 // |scripts| with non-unique IDs will work, but that would indicate we are |
| 179 // doing something wrong somewhere, so DCHECK that. | 179 // doing something wrong somewhere, so DCHECK that. |
| 180 DCHECK(AreScriptsUnique(scripts)) | 180 DCHECK(AreScriptsUnique(*scripts)) |
| 181 << "AddScripts() expects scripts with unique IDs."; | 181 << "AddScripts() expects scripts with unique IDs."; |
| 182 #endif // DCHECK_IS_ON() | 182 #endif // DCHECK_IS_ON() |
| 183 for (const UserScript& user_script : scripts) { | 183 for (std::unique_ptr<UserScript>& user_script : *scripts) { |
| 184 int id = user_script.id(); | 184 int id = user_script->id(); |
| 185 removed_script_hosts_.erase(UserScriptIDPair(id)); | 185 removed_script_hosts_.erase(UserScriptIDPair(id)); |
| 186 if (added_scripts_map_.count(id) == 0) | 186 if (added_scripts_map_.count(id) == 0) |
| 187 added_scripts_map_[id] = user_script; | 187 added_scripts_map_[id] = std::move(user_script); |
| 188 } | 188 } |
| 189 AttemptLoad(); | 189 AttemptLoad(); |
| 190 } | 190 } |
| 191 | 191 |
| 192 void UserScriptLoader::AddScripts(const UserScriptList& scripts, | 192 void UserScriptLoader::AddScripts(std::unique_ptr<UserScriptList> scripts, |
| 193 int render_process_id, | 193 int render_process_id, |
| 194 int render_frame_id) { | 194 int render_frame_id) { |
| 195 AddScripts(scripts); | 195 AddScripts(std::move(scripts)); |
| 196 } | 196 } |
| 197 | 197 |
| 198 void UserScriptLoader::RemoveScripts( | 198 void UserScriptLoader::RemoveScripts( |
| 199 const std::set<UserScriptIDPair>& scripts) { | 199 const std::set<UserScriptIDPair>& scripts) { |
| 200 for (const UserScriptIDPair& id_pair : scripts) { | 200 for (const UserScriptIDPair& id_pair : scripts) { |
| 201 removed_script_hosts_.insert(UserScriptIDPair(id_pair.id, id_pair.host_id)); | 201 removed_script_hosts_.insert(UserScriptIDPair(id_pair.id, id_pair.host_id)); |
| 202 // TODO(lazyboy): We shouldn't be trying to remove scripts that were never | 202 // TODO(lazyboy): We shouldn't be trying to remove scripts that were never |
| 203 // a) added to |added_scripts_map_| or b) being loaded or has done loading | 203 // a) added to |added_scripts_map_| or b) being loaded or has done loading |
| 204 // through |user_scripts_|. This would reduce sending redundant IPC. | 204 // through |user_scripts_|. This would reduce sending redundant IPC. |
| 205 added_scripts_map_.erase(id_pair.id); | 205 added_scripts_map_.erase(id_pair.id); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 252 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 253 DCHECK(!is_loading()); | 253 DCHECK(!is_loading()); |
| 254 | 254 |
| 255 // If scripts were marked for clearing before adding and removing, then clear | 255 // If scripts were marked for clearing before adding and removing, then clear |
| 256 // them. | 256 // them. |
| 257 if (clear_scripts_) { | 257 if (clear_scripts_) { |
| 258 user_scripts_->clear(); | 258 user_scripts_->clear(); |
| 259 } else { | 259 } else { |
| 260 for (UserScriptList::iterator it = user_scripts_->begin(); | 260 for (UserScriptList::iterator it = user_scripts_->begin(); |
| 261 it != user_scripts_->end();) { | 261 it != user_scripts_->end();) { |
| 262 UserScriptIDPair id_pair(it->id()); | 262 UserScriptIDPair id_pair(it->get()->id()); |
| 263 if (removed_script_hosts_.count(id_pair) > 0u) | 263 if (removed_script_hosts_.count(id_pair) > 0u) |
| 264 it = user_scripts_->erase(it); | 264 it = user_scripts_->erase(it); |
| 265 else | 265 else |
| 266 ++it; | 266 ++it; |
| 267 } | 267 } |
| 268 } | 268 } |
| 269 | 269 |
| 270 std::set<int> added_script_ids; | 270 std::set<int> added_script_ids; |
| 271 user_scripts_->reserve(user_scripts_->size() + added_scripts_map_.size()); | 271 user_scripts_->reserve(user_scripts_->size() + added_scripts_map_.size()); |
| 272 for (const auto& id_and_script : added_scripts_map_) { | 272 for (auto& id_and_script : added_scripts_map_) { |
| 273 const UserScript& script = id_and_script.second; | 273 std::unique_ptr<UserScript>& script = id_and_script.second; |
| 274 added_script_ids.insert(script.id()); | 274 added_script_ids.insert(script->id()); |
| 275 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in | 275 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in |
| 276 // its IPC message. This must be done before we clear |added_scripts_map_| | 276 // its IPC message. This must be done before we clear |added_scripts_map_| |
| 277 // and |removed_script_hosts_| below. | 277 // and |removed_script_hosts_| below. |
| 278 changed_hosts_.insert(script.host_id()); | 278 changed_hosts_.insert(script->host_id()); |
| 279 // Put script from |added_scripts_map_| into |user_scripts_|. | 279 // Move script from |added_scripts_map_| into |user_scripts_|. |
| 280 user_scripts_->push_back(added_scripts_map_[script.id()]); | 280 user_scripts_->push_back(std::move(script)); |
| 281 } | 281 } |
| 282 for (const UserScriptIDPair& id_pair : removed_script_hosts_) | 282 for (const UserScriptIDPair& id_pair : removed_script_hosts_) |
| 283 changed_hosts_.insert(id_pair.host_id); | 283 changed_hosts_.insert(id_pair.host_id); |
| 284 | 284 |
| 285 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids, | 285 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids, |
| 286 base::Bind(&UserScriptLoader::OnScriptsLoaded, | 286 base::Bind(&UserScriptLoader::OnScriptsLoaded, |
| 287 weak_factory_.GetWeakPtr())); | 287 weak_factory_.GetWeakPtr())); |
| 288 | 288 |
| 289 clear_scripts_ = false; | 289 clear_scripts_ = false; |
| 290 added_scripts_map_.clear(); | 290 added_scripts_map_.clear(); |
| 291 removed_script_hosts_.clear(); | 291 removed_script_hosts_.clear(); |
| 292 user_scripts_.reset(); | 292 user_scripts_.reset(); |
| 293 } | 293 } |
| 294 | 294 |
| 295 // static | 295 // static |
| 296 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize( | 296 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize( |
| 297 const UserScriptList& scripts) { | 297 const UserScriptList& scripts) { |
| 298 base::Pickle pickle; | 298 base::Pickle pickle; |
| 299 pickle.WriteUInt32(scripts.size()); | 299 pickle.WriteUInt32(scripts.size()); |
| 300 for (const UserScript& script : scripts) { | 300 for (const std::unique_ptr<UserScript>& script : scripts) { |
| 301 // TODO(aa): This can be replaced by sending content script metadata to | 301 // TODO(aa): This can be replaced by sending content script metadata to |
| 302 // renderers along with other extension data in ExtensionMsg_Loaded. | 302 // renderers along with other extension data in ExtensionMsg_Loaded. |
| 303 // See crbug.com/70516. | 303 // See crbug.com/70516. |
| 304 script.Pickle(&pickle); | 304 script->Pickle(&pickle); |
| 305 // Write scripts as 'data' so that we can read it out in the slave without | 305 // Write scripts as 'data' so that we can read it out in the slave without |
| 306 // allocating a new string. | 306 // allocating a new string. |
| 307 for (const UserScript::File& script_file : script.js_scripts()) { | 307 for (const std::unique_ptr<UserScript::File>& js_file : |
| 308 base::StringPiece contents = script_file.GetContent(); | 308 script->js_scripts()) { |
| 309 base::StringPiece contents = js_file->GetContent(); |
| 309 pickle.WriteData(contents.data(), contents.length()); | 310 pickle.WriteData(contents.data(), contents.length()); |
| 310 } | 311 } |
| 311 for (const UserScript::File& script_file : script.css_scripts()) { | 312 for (const std::unique_ptr<UserScript::File>& css_file : |
| 312 base::StringPiece contents = script_file.GetContent(); | 313 script->css_scripts()) { |
| 314 base::StringPiece contents = css_file->GetContent(); |
| 313 pickle.WriteData(contents.data(), contents.length()); | 315 pickle.WriteData(contents.data(), contents.length()); |
| 314 } | 316 } |
| 315 } | 317 } |
| 316 | 318 |
| 317 // Create the shared memory object. | 319 // Create the shared memory object. |
| 318 base::SharedMemory shared_memory; | 320 base::SharedMemory shared_memory; |
| 319 | 321 |
| 320 base::SharedMemoryCreateOptions options; | 322 base::SharedMemoryCreateOptions options; |
| 321 options.size = pickle.size(); | 323 options.size = pickle.size(); |
| 322 options.share_read_only = true; | 324 options.share_read_only = true; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) | 419 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) |
| 418 return; // This can legitimately fail if the renderer asserts at startup. | 420 return; // This can legitimately fail if the renderer asserts at startup. |
| 419 | 421 |
| 420 if (base::SharedMemory::IsHandleValid(handle_for_process)) { | 422 if (base::SharedMemory::IsHandleValid(handle_for_process)) { |
| 421 process->Send(new ExtensionMsg_UpdateUserScripts( | 423 process->Send(new ExtensionMsg_UpdateUserScripts( |
| 422 handle_for_process, host_id(), changed_hosts, whitelisted_only)); | 424 handle_for_process, host_id(), changed_hosts, whitelisted_only)); |
| 423 } | 425 } |
| 424 } | 426 } |
| 425 | 427 |
| 426 } // namespace extensions | 428 } // namespace extensions |
| OLD | NEW |