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

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: fix DCHECK 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_.erase(UserScriptIDPair(id));
186 if (added_scripts_map_.count(id) == 0)
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_.insert(UserScriptIDPair(id_pair.id, id_pair.host_id));
184 added_scripts_.erase(*it); 202 // TODO(lazyboy): We shouldn't be trying to remove scripts that were never
185 removed_scripts_.insert(*it); 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.
205 DCHECK(added_scripts_map_.count(id_pair.id) > 0u);
Devlin 2016/08/11 01:09:27 Nit: DCHECK_GT
lazyboy 2016/08/11 01:51:06 Done.
lazyboy 2016/08/11 02:00:21 Actually just realized that this DCHECK is wrong b
206 added_scripts_map_.erase(id_pair.id);
186 } 207 }
187 AttemptLoad(); 208 AttemptLoad();
188 } 209 }
189 210
190 void UserScriptLoader::ClearScripts() { 211 void UserScriptLoader::ClearScripts() {
191 clear_scripts_ = true; 212 clear_scripts_ = true;
192 added_scripts_.clear(); 213 added_scripts_map_.clear();
193 removed_scripts_.clear(); 214 removed_script_hosts_.clear();
194 AttemptLoad(); 215 AttemptLoad();
195 } 216 }
196 217
197 void UserScriptLoader::Observe(int type, 218 void UserScriptLoader::Observe(int type,
198 const content::NotificationSource& source, 219 const content::NotificationSource& source,
199 const content::NotificationDetails& details) { 220 const content::NotificationDetails& details) {
200 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED); 221 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED);
201 content::RenderProcessHost* process = 222 content::RenderProcessHost* process =
202 content::Source<content::RenderProcessHost>(source).ptr(); 223 content::Source<content::RenderProcessHost>(source).ptr();
203 if (!ExtensionsBrowserClient::Get()->IsSameContext( 224 if (!ExtensionsBrowserClient::Get()->IsSameContext(
204 browser_context_, process->GetBrowserContext())) 225 browser_context_, process->GetBrowserContext()))
205 return; 226 return;
206 if (scripts_ready()) { 227 if (scripts_ready()) {
207 SendUpdate(process, shared_memory_.get(), 228 SendUpdate(process, shared_memory_.get(),
208 std::set<HostID>()); // Include all hosts. 229 std::set<HostID>()); // Include all hosts.
209 } 230 }
210 } 231 }
211 232
212 bool UserScriptLoader::ScriptsMayHaveChanged() const { 233 bool UserScriptLoader::ScriptsMayHaveChanged() const {
213 // Scripts may have changed if there are scripts added, scripts removed, or 234 // Scripts may have changed if there are scripts added, scripts removed, or
214 // if scripts were cleared and either: 235 // if scripts were cleared and either:
215 // (1) A load is in progress (which may result in a non-zero number of 236 // (1) A load is in progress (which may result in a non-zero number of
216 // scripts that need to be cleared), or 237 // scripts that need to be cleared), or
217 // (2) The current set of scripts is non-empty (so they need to be cleared). 238 // (2) The current set of scripts is non-empty (so they need to be cleared).
218 return (added_scripts_.size() || 239 return (added_scripts_map_.size() || removed_script_hosts_.size() ||
219 removed_scripts_.size() || 240 (clear_scripts_ && (is_loading() || user_scripts_->size())));
220 (clear_scripts_ &&
221 (is_loading() || user_scripts_->size())));
222 } 241 }
223 242
224 void UserScriptLoader::AttemptLoad() { 243 void UserScriptLoader::AttemptLoad() {
225 if (ready_ && ScriptsMayHaveChanged()) { 244 if (ready_ && ScriptsMayHaveChanged()) {
226 if (is_loading()) 245 if (is_loading())
227 pending_load_ = true; 246 pending_load_ = true;
228 else 247 else
229 StartLoad(); 248 StartLoad();
230 } 249 }
231 } 250 }
232 251
233 void UserScriptLoader::StartLoad() { 252 void UserScriptLoader::StartLoad() {
234 DCHECK_CURRENTLY_ON(BrowserThread::UI); 253 DCHECK_CURRENTLY_ON(BrowserThread::UI);
235 DCHECK(!is_loading()); 254 DCHECK(!is_loading());
236 255
237 // If scripts were marked for clearing before adding and removing, then clear 256 // If scripts were marked for clearing before adding and removing, then clear
238 // them. 257 // them.
239 if (clear_scripts_) { 258 if (clear_scripts_) {
240 user_scripts_->clear(); 259 user_scripts_->clear();
241 } else { 260 } else {
242 for (UserScriptList::iterator it = user_scripts_->begin(); 261 for (UserScriptList::iterator it = user_scripts_->begin();
243 it != user_scripts_->end();) { 262 it != user_scripts_->end();) {
244 if (removed_scripts_.count(*it)) 263 UserScriptIDPair id_pair(it->id());
264 if (removed_script_hosts_.count(id_pair) > 0u)
245 it = user_scripts_->erase(it); 265 it = user_scripts_->erase(it);
246 else 266 else
247 ++it; 267 ++it;
248 } 268 }
249 } 269 }
250 270
251 user_scripts_->insert(
252 user_scripts_->end(), added_scripts_.begin(), added_scripts_.end());
253
254 std::set<int> added_script_ids; 271 std::set<int> added_script_ids;
255 for (std::set<UserScript>::const_iterator it = added_scripts_.begin(); 272 for (const auto& id_and_script : added_scripts_map_)
256 it != added_scripts_.end(); 273 added_script_ids.insert(id_and_script.second.id());
257 ++it) {
258 added_script_ids.insert(it->id());
259 }
260 274
261 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in 275 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in
262 // its IPC message. This must be done before we clear |added_scripts_| and 276 // its IPC message. This must be done before we clear |added_scripts_map_| and
263 // |removed_scripts_| below. 277 // |removed_script_hosts_| below.
264 std::set<UserScript> changed_scripts(added_scripts_); 278 for (const auto& id_and_script : added_scripts_map_)
Devlin 2016/08/11 01:09:27 Could we do this and the addition to user scripts
Devlin 2016/08/11 01:09:27 Could we do this and the addition to user scripts
lazyboy 2016/08/11 01:51:06 Done.
265 changed_scripts.insert(removed_scripts_.begin(), removed_scripts_.end()); 279 changed_hosts_.insert(id_and_script.second.host_id());
266 for (const UserScript& script : changed_scripts) 280 for (const UserScriptIDPair& id_pair : removed_script_hosts_)
267 changed_hosts_.insert(script.host_id()); 281 changed_hosts_.insert(id_pair.host_id);
282
283 // Done with |added_scripts_map_|, now put them into |user_scripts_|.
284 user_scripts_->reserve(user_scripts_->size() + added_scripts_map_.size());
285 for (int id : added_script_ids)
286 user_scripts_->push_back(std::move(added_scripts_map_[id]));
268 287
269 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids, 288 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids,
270 base::Bind(&UserScriptLoader::OnScriptsLoaded, 289 base::Bind(&UserScriptLoader::OnScriptsLoaded,
271 weak_factory_.GetWeakPtr())); 290 weak_factory_.GetWeakPtr()));
272 291
273 clear_scripts_ = false; 292 clear_scripts_ = false;
274 added_scripts_.clear(); 293 added_scripts_map_.clear();
275 removed_scripts_.clear(); 294 removed_script_hosts_.clear();
276 user_scripts_.reset(); 295 user_scripts_.reset();
277 } 296 }
278 297
279 // static 298 // static
280 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize( 299 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize(
281 const UserScriptList& scripts) { 300 const UserScriptList& scripts) {
282 base::Pickle pickle; 301 base::Pickle pickle;
283 pickle.WriteUInt32(scripts.size()); 302 pickle.WriteUInt32(scripts.size());
284 for (const UserScript& script : scripts) { 303 for (const UserScript& script : scripts) {
285 // TODO(aa): This can be replaced by sending content script metadata to 304 // 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)) 420 if (!shared_memory->ShareToProcess(handle, &handle_for_process))
402 return; // This can legitimately fail if the renderer asserts at startup. 421 return; // This can legitimately fail if the renderer asserts at startup.
403 422
404 if (base::SharedMemory::IsHandleValid(handle_for_process)) { 423 if (base::SharedMemory::IsHandleValid(handle_for_process)) {
405 process->Send(new ExtensionMsg_UpdateUserScripts( 424 process->Send(new ExtensionMsg_UpdateUserScripts(
406 handle_for_process, host_id(), changed_hosts, whitelisted_only)); 425 handle_for_process, host_id(), changed_hosts, whitelisted_only));
407 } 426 }
408 } 427 }
409 428
410 } // namespace extensions 429 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698