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

Side by Side Diff: extensions/browser/user_script_loader.cc

Issue 2228743002: Rework some UserScriptLoader logic in preparation to removing UserScript copy. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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
OLDNEW
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 10 matching lines...) Expand all
21 #include "extensions/browser/notification_types.h" 21 #include "extensions/browser/notification_types.h"
22 #include "extensions/common/extension_messages.h" 22 #include "extensions/common/extension_messages.h"
23 23
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()
32 bool AreScriptsUnique(const UserScriptList& scripts) {
33 std::set<int> script_ids;
34 for (const UserScript& script : scripts) {
35 if (script_ids.count(script.id()))
36 return false;
37 script_ids.insert(script.id());
38 }
39 return true;
40 }
41 #endif // DCHECK_IS_ON()
42
31 // Helper function to parse greasesmonkey headers 43 // Helper function to parse greasesmonkey headers
32 bool GetDeclarationValue(const base::StringPiece& line, 44 bool GetDeclarationValue(const base::StringPiece& line,
33 const base::StringPiece& prefix, 45 const base::StringPiece& prefix,
34 std::string* value) { 46 std::string* value) {
35 base::StringPiece::size_type index = line.find(prefix); 47 base::StringPiece::size_type index = line.find(prefix);
36 if (index == base::StringPiece::npos) 48 if (index == base::StringPiece::npos)
37 return false; 49 return false;
38 50
39 std::string temp(line.data() + index + prefix.length(), 51 std::string temp(line.data() + index + prefix.length(),
40 line.length() - index - prefix.length()); 52 line.length() - index - prefix.length());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 weak_factory_(this) { 166 weak_factory_(this) {
155 registrar_.Add(this, 167 registrar_.Add(this,
156 content::NOTIFICATION_RENDERER_PROCESS_CREATED, 168 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
157 content::NotificationService::AllBrowserContextsAndSources()); 169 content::NotificationService::AllBrowserContextsAndSources());
158 } 170 }
159 171
160 UserScriptLoader::~UserScriptLoader() { 172 UserScriptLoader::~UserScriptLoader() {
161 FOR_EACH_OBSERVER(Observer, observers_, OnUserScriptLoaderDestroyed(this)); 173 FOR_EACH_OBSERVER(Observer, observers_, OnUserScriptLoaderDestroyed(this));
162 } 174 }
163 175
164 void UserScriptLoader::AddScripts(const std::set<UserScript>& scripts) { 176 void UserScriptLoader::AddScripts(const UserScriptList& scripts) {
165 for (std::set<UserScript>::const_iterator it = scripts.begin(); 177 #if DCHECK_IS_ON()
166 it != scripts.end(); 178 // |scripts| with non-unique IDs will work, but that would indicate we are
167 ++it) { 179 // doing something wrong somewhere, so DCHECK that.
168 removed_scripts_.erase(*it); 180 DCHECK(AreScriptsUnique(scripts))
169 added_scripts_.insert(*it); 181 << "AddScripts() expects scripts with unique IDs.";
182 #endif // DCHECK_IS_ON()
183 for (const UserScript& user_script : scripts) {
184 int id = user_script.id();
185 removed_script_hosts_map_.erase(id);
186 if (added_scripts_map_.count(id) == 0)
Devlin 2016/08/09 23:28:54 When does this happen? (This could be a behavior
lazyboy 2016/08/10 00:03:41 Not sure, I'm keeping the behavior as is. (This co
187 added_scripts_map_[id] = user_script;
170 } 188 }
171 AttemptLoad(); 189 AttemptLoad();
172 } 190 }
173 191
174 void UserScriptLoader::AddScripts(const std::set<UserScript>& scripts, 192 void UserScriptLoader::AddScripts(const UserScriptList& scripts,
175 int render_process_id, 193 int render_process_id,
176 int render_view_id) { 194 int render_view_id) {
177 AddScripts(scripts); 195 AddScripts(scripts);
178 } 196 }
179 197
180 void UserScriptLoader::RemoveScripts(const std::set<UserScript>& scripts) { 198 void UserScriptLoader::RemoveScripts(
181 for (std::set<UserScript>::const_iterator it = scripts.begin(); 199 const std::set<UserScriptIDPair>& scripts) {
182 it != scripts.end(); 200 for (const UserScriptIDPair& id_pair : scripts) {
183 ++it) { 201 removed_script_hosts_map_[id_pair.id] = id_pair.host_id;
Devlin 2016/08/09 23:28:54 If we don't actually remove any scripts, do we sti
lazyboy 2016/08/10 00:03:41 Can you elaborate this one, not sure I understand?
Devlin 2016/08/10 16:22:40 I think it would involve checking added_scripts_ma
lazyboy 2016/08/10 22:39:54 OK, I've added a DCHECK and added a todo for this.
184 added_scripts_.erase(*it); 202 added_scripts_map_.erase(id_pair.id);
185 removed_scripts_.insert(*it);
186 } 203 }
187 AttemptLoad(); 204 AttemptLoad();
188 } 205 }
189 206
190 void UserScriptLoader::ClearScripts() { 207 void UserScriptLoader::ClearScripts() {
191 clear_scripts_ = true; 208 clear_scripts_ = true;
192 added_scripts_.clear(); 209 added_scripts_map_.clear();
193 removed_scripts_.clear(); 210 removed_script_hosts_map_.clear();
194 AttemptLoad(); 211 AttemptLoad();
195 } 212 }
196 213
197 void UserScriptLoader::Observe(int type, 214 void UserScriptLoader::Observe(int type,
198 const content::NotificationSource& source, 215 const content::NotificationSource& source,
199 const content::NotificationDetails& details) { 216 const content::NotificationDetails& details) {
200 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED); 217 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED);
201 content::RenderProcessHost* process = 218 content::RenderProcessHost* process =
202 content::Source<content::RenderProcessHost>(source).ptr(); 219 content::Source<content::RenderProcessHost>(source).ptr();
203 if (!ExtensionsBrowserClient::Get()->IsSameContext( 220 if (!ExtensionsBrowserClient::Get()->IsSameContext(
204 browser_context_, process->GetBrowserContext())) 221 browser_context_, process->GetBrowserContext()))
205 return; 222 return;
206 if (scripts_ready()) { 223 if (scripts_ready()) {
207 SendUpdate(process, shared_memory_.get(), 224 SendUpdate(process, shared_memory_.get(),
208 std::set<HostID>()); // Include all hosts. 225 std::set<HostID>()); // Include all hosts.
209 } 226 }
210 } 227 }
211 228
212 bool UserScriptLoader::ScriptsMayHaveChanged() const { 229 bool UserScriptLoader::ScriptsMayHaveChanged() const {
213 // Scripts may have changed if there are scripts added, scripts removed, or 230 // Scripts may have changed if there are scripts added, scripts removed, or
214 // if scripts were cleared and either: 231 // if scripts were cleared and either:
215 // (1) A load is in progress (which may result in a non-zero number of 232 // (1) A load is in progress (which may result in a non-zero number of
216 // scripts that need to be cleared), or 233 // scripts that need to be cleared), or
217 // (2) The current set of scripts is non-empty (so they need to be cleared). 234 // (2) The current set of scripts is non-empty (so they need to be cleared).
218 return (added_scripts_.size() || 235 return (added_scripts_map_.size() || removed_script_hosts_map_.size() ||
219 removed_scripts_.size() || 236 (clear_scripts_ && (is_loading() || user_scripts_->size())));
220 (clear_scripts_ &&
221 (is_loading() || user_scripts_->size())));
222 } 237 }
223 238
224 void UserScriptLoader::AttemptLoad() { 239 void UserScriptLoader::AttemptLoad() {
225 if (ready_ && ScriptsMayHaveChanged()) { 240 if (ready_ && ScriptsMayHaveChanged()) {
226 if (is_loading()) 241 if (is_loading())
227 pending_load_ = true; 242 pending_load_ = true;
228 else 243 else
229 StartLoad(); 244 StartLoad();
230 } 245 }
231 } 246 }
232 247
233 void UserScriptLoader::StartLoad() { 248 void UserScriptLoader::StartLoad() {
234 DCHECK_CURRENTLY_ON(BrowserThread::UI); 249 DCHECK_CURRENTLY_ON(BrowserThread::UI);
235 DCHECK(!is_loading()); 250 DCHECK(!is_loading());
236 251
237 // If scripts were marked for clearing before adding and removing, then clear 252 // If scripts were marked for clearing before adding and removing, then clear
238 // them. 253 // them.
239 if (clear_scripts_) { 254 if (clear_scripts_) {
240 user_scripts_->clear(); 255 user_scripts_->clear();
241 } else { 256 } else {
242 for (UserScriptList::iterator it = user_scripts_->begin(); 257 for (UserScriptList::iterator it = user_scripts_->begin();
243 it != user_scripts_->end();) { 258 it != user_scripts_->end();) {
244 if (removed_scripts_.count(*it)) 259 if (removed_script_hosts_map_.count(it->id()) > 0u)
245 it = user_scripts_->erase(it); 260 it = user_scripts_->erase(it);
246 else 261 else
247 ++it; 262 ++it;
248 } 263 }
249 } 264 }
250 265
251 user_scripts_->insert(
lazyboy 2016/08/09 00:48:51 This is a major source of copy, because it might e
252 user_scripts_->end(), added_scripts_.begin(), added_scripts_.end());
253
254 std::set<int> added_script_ids; 266 std::set<int> added_script_ids;
255 for (std::set<UserScript>::const_iterator it = added_scripts_.begin(); 267 for (const auto& id_and_script : added_scripts_map_)
256 it != added_scripts_.end(); 268 added_script_ids.insert(id_and_script.second.id());
257 ++it) {
258 added_script_ids.insert(it->id());
259 }
260 269
261 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in 270 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in
262 // its IPC message. This must be done before we clear |added_scripts_| and 271 // its IPC message. This must be done before we clear |added_scripts_| and
Devlin 2016/08/09 23:28:54 added_scripts_map_
lazyboy 2016/08/10 00:03:41 Done.
263 // |removed_scripts_| below. 272 // |removed_script_hosts_map_| below.
264 std::set<UserScript> changed_scripts(added_scripts_); 273 for (const auto& id_and_script : added_scripts_map_)
265 changed_scripts.insert(removed_scripts_.begin(), removed_scripts_.end()); 274 changed_hosts_.insert(id_and_script.second.host_id());
266 for (const UserScript& script : changed_scripts) 275 for (const std::pair<int, HostID>& host_id : removed_script_hosts_map_)
267 changed_hosts_.insert(script.host_id()); 276 changed_hosts_.insert(host_id.second);
277
278 // Done with |added_scripts_map_|, now put them into |user_scripts_|.
279 user_scripts_->reserve(user_scripts_->size() + added_scripts_map_.size());
280 for (int id : added_script_ids)
281 user_scripts_->push_back(std::move(added_scripts_map_[id]));
268 282
269 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids, 283 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids,
270 base::Bind(&UserScriptLoader::OnScriptsLoaded, 284 base::Bind(&UserScriptLoader::OnScriptsLoaded,
271 weak_factory_.GetWeakPtr())); 285 weak_factory_.GetWeakPtr()));
272 286
273 clear_scripts_ = false; 287 clear_scripts_ = false;
274 added_scripts_.clear(); 288 added_scripts_map_.clear();
275 removed_scripts_.clear(); 289 removed_script_hosts_map_.clear();
276 user_scripts_.reset(); 290 user_scripts_.reset();
277 } 291 }
278 292
279 // static 293 // static
280 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize( 294 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize(
281 const UserScriptList& scripts) { 295 const UserScriptList& scripts) {
282 base::Pickle pickle; 296 base::Pickle pickle;
283 pickle.WriteUInt32(scripts.size()); 297 pickle.WriteUInt32(scripts.size());
284 for (const UserScript& script : scripts) { 298 for (const UserScript& script : scripts) {
285 // TODO(aa): This can be replaced by sending content script metadata to 299 // TODO(aa): This can be replaced by sending content script metadata to
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) 415 if (!shared_memory->ShareToProcess(handle, &handle_for_process))
402 return; // This can legitimately fail if the renderer asserts at startup. 416 return; // This can legitimately fail if the renderer asserts at startup.
403 417
404 if (base::SharedMemory::IsHandleValid(handle_for_process)) { 418 if (base::SharedMemory::IsHandleValid(handle_for_process)) {
405 process->Send(new ExtensionMsg_UpdateUserScripts( 419 process->Send(new ExtensionMsg_UpdateUserScripts(
406 handle_for_process, host_id(), changed_hosts, whitelisted_only)); 420 handle_for_process, host_id(), changed_hosts, whitelisted_only));
407 } 421 }
408 } 422 }
409 423
410 } // namespace extensions 424 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698