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

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: sync @tott 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
« no previous file with comments | « extensions/browser/user_script_loader.h ('k') | extensions/browser/web_ui_user_script_loader.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_frame_id) { 194 int render_frame_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 added_scripts_map_.erase(id_pair.id);
186 } 206 }
187 AttemptLoad(); 207 AttemptLoad();
188 } 208 }
189 209
190 void UserScriptLoader::ClearScripts() { 210 void UserScriptLoader::ClearScripts() {
191 clear_scripts_ = true; 211 clear_scripts_ = true;
192 added_scripts_.clear(); 212 added_scripts_map_.clear();
193 removed_scripts_.clear(); 213 removed_script_hosts_.clear();
194 AttemptLoad(); 214 AttemptLoad();
195 } 215 }
196 216
197 void UserScriptLoader::Observe(int type, 217 void UserScriptLoader::Observe(int type,
198 const content::NotificationSource& source, 218 const content::NotificationSource& source,
199 const content::NotificationDetails& details) { 219 const content::NotificationDetails& details) {
200 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED); 220 DCHECK_EQ(type, content::NOTIFICATION_RENDERER_PROCESS_CREATED);
201 content::RenderProcessHost* process = 221 content::RenderProcessHost* process =
202 content::Source<content::RenderProcessHost>(source).ptr(); 222 content::Source<content::RenderProcessHost>(source).ptr();
203 if (!ExtensionsBrowserClient::Get()->IsSameContext( 223 if (!ExtensionsBrowserClient::Get()->IsSameContext(
204 browser_context_, process->GetBrowserContext())) 224 browser_context_, process->GetBrowserContext()))
205 return; 225 return;
206 if (scripts_ready()) { 226 if (scripts_ready()) {
207 SendUpdate(process, shared_memory_.get(), 227 SendUpdate(process, shared_memory_.get(),
208 std::set<HostID>()); // Include all hosts. 228 std::set<HostID>()); // Include all hosts.
209 } 229 }
210 } 230 }
211 231
212 bool UserScriptLoader::ScriptsMayHaveChanged() const { 232 bool UserScriptLoader::ScriptsMayHaveChanged() const {
213 // Scripts may have changed if there are scripts added, scripts removed, or 233 // Scripts may have changed if there are scripts added, scripts removed, or
214 // if scripts were cleared and either: 234 // if scripts were cleared and either:
215 // (1) A load is in progress (which may result in a non-zero number of 235 // (1) A load is in progress (which may result in a non-zero number of
216 // scripts that need to be cleared), or 236 // scripts that need to be cleared), or
217 // (2) The current set of scripts is non-empty (so they need to be cleared). 237 // (2) The current set of scripts is non-empty (so they need to be cleared).
218 return (added_scripts_.size() || 238 return (added_scripts_map_.size() || removed_script_hosts_.size() ||
219 removed_scripts_.size() || 239 (clear_scripts_ && (is_loading() || user_scripts_->size())));
220 (clear_scripts_ &&
221 (is_loading() || user_scripts_->size())));
222 } 240 }
223 241
224 void UserScriptLoader::AttemptLoad() { 242 void UserScriptLoader::AttemptLoad() {
225 if (ready_ && ScriptsMayHaveChanged()) { 243 if (ready_ && ScriptsMayHaveChanged()) {
226 if (is_loading()) 244 if (is_loading())
227 pending_load_ = true; 245 pending_load_ = true;
228 else 246 else
229 StartLoad(); 247 StartLoad();
230 } 248 }
231 } 249 }
232 250
233 void UserScriptLoader::StartLoad() { 251 void UserScriptLoader::StartLoad() {
234 DCHECK_CURRENTLY_ON(BrowserThread::UI); 252 DCHECK_CURRENTLY_ON(BrowserThread::UI);
235 DCHECK(!is_loading()); 253 DCHECK(!is_loading());
236 254
237 // 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
238 // them. 256 // them.
239 if (clear_scripts_) { 257 if (clear_scripts_) {
240 user_scripts_->clear(); 258 user_scripts_->clear();
241 } else { 259 } else {
242 for (UserScriptList::iterator it = user_scripts_->begin(); 260 for (UserScriptList::iterator it = user_scripts_->begin();
243 it != user_scripts_->end();) { 261 it != user_scripts_->end();) {
244 if (removed_scripts_.count(*it)) 262 UserScriptIDPair id_pair(it->id());
263 if (removed_script_hosts_.count(id_pair) > 0u)
245 it = user_scripts_->erase(it); 264 it = user_scripts_->erase(it);
246 else 265 else
247 ++it; 266 ++it;
248 } 267 }
249 } 268 }
250 269
251 user_scripts_->insert(
252 user_scripts_->end(), added_scripts_.begin(), added_scripts_.end());
253
254 std::set<int> added_script_ids; 270 std::set<int> added_script_ids;
255 for (std::set<UserScript>::const_iterator it = added_scripts_.begin(); 271 user_scripts_->reserve(user_scripts_->size() + added_scripts_map_.size());
256 it != added_scripts_.end(); 272 for (const auto& id_and_script : added_scripts_map_) {
257 ++it) { 273 const UserScript& script = id_and_script.second;
258 added_script_ids.insert(it->id()); 274 added_script_ids.insert(script.id());
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_|
277 // and |removed_script_hosts_| below.
278 changed_hosts_.insert(script.host_id());
279 // Put script from |added_scripts_map_| into |user_scripts_|.
280 user_scripts_->push_back(added_scripts_map_[script.id()]);
259 } 281 }
260 282 for (const UserScriptIDPair& id_pair : removed_script_hosts_)
261 // Expand |changed_hosts_| for OnScriptsLoaded, which will use it in 283 changed_hosts_.insert(id_pair.host_id);
262 // its IPC message. This must be done before we clear |added_scripts_| and
263 // |removed_scripts_| below.
264 std::set<UserScript> changed_scripts(added_scripts_);
265 changed_scripts.insert(removed_scripts_.begin(), removed_scripts_.end());
266 for (const UserScript& script : changed_scripts)
267 changed_hosts_.insert(script.host_id());
268 284
269 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids, 285 LoadScripts(std::move(user_scripts_), changed_hosts_, added_script_ids,
270 base::Bind(&UserScriptLoader::OnScriptsLoaded, 286 base::Bind(&UserScriptLoader::OnScriptsLoaded,
271 weak_factory_.GetWeakPtr())); 287 weak_factory_.GetWeakPtr()));
272 288
273 clear_scripts_ = false; 289 clear_scripts_ = false;
274 added_scripts_.clear(); 290 added_scripts_map_.clear();
275 removed_scripts_.clear(); 291 removed_script_hosts_.clear();
276 user_scripts_.reset(); 292 user_scripts_.reset();
277 } 293 }
278 294
279 // static 295 // static
280 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize( 296 std::unique_ptr<base::SharedMemory> UserScriptLoader::Serialize(
281 const UserScriptList& scripts) { 297 const UserScriptList& scripts) {
282 base::Pickle pickle; 298 base::Pickle pickle;
283 pickle.WriteUInt32(scripts.size()); 299 pickle.WriteUInt32(scripts.size());
284 for (const UserScript& script : scripts) { 300 for (const UserScript& script : scripts) {
285 // 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
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 if (!shared_memory->ShareToProcess(handle, &handle_for_process)) 417 if (!shared_memory->ShareToProcess(handle, &handle_for_process))
402 return; // This can legitimately fail if the renderer asserts at startup. 418 return; // This can legitimately fail if the renderer asserts at startup.
403 419
404 if (base::SharedMemory::IsHandleValid(handle_for_process)) { 420 if (base::SharedMemory::IsHandleValid(handle_for_process)) {
405 process->Send(new ExtensionMsg_UpdateUserScripts( 421 process->Send(new ExtensionMsg_UpdateUserScripts(
406 handle_for_process, host_id(), changed_hosts, whitelisted_only)); 422 handle_for_process, host_id(), changed_hosts, whitelisted_only));
407 } 423 }
408 } 424 }
409 425
410 } // namespace extensions 426 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/user_script_loader.h ('k') | extensions/browser/web_ui_user_script_loader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698