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

Side by Side Diff: extensions/renderer/script_injection_manager.cc

Issue 2134613002: Stop injection when injections are invalidated Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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/renderer/script_injection_manager.h" 5 #include "extensions/renderer/script_injection_manager.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 void InvalidateAndResetFrame(); 96 void InvalidateAndResetFrame();
97 97
98 // The owning ScriptInjectionManager. 98 // The owning ScriptInjectionManager.
99 ScriptInjectionManager* manager_; 99 ScriptInjectionManager* manager_;
100 100
101 bool should_run_idle_; 101 bool should_run_idle_;
102 102
103 base::WeakPtrFactory<RFOHelper> weak_factory_; 103 base::WeakPtrFactory<RFOHelper> weak_factory_;
104 }; 104 };
105 105
106 class ScriptInjectionManager::ScriptInjectionWatcher {
107 public:
108 ScriptInjectionWatcher(ScriptInjection* injection,
109 ScriptInjectionManager* manager)
110 : injection_(injection), manager_(manager), host_id_(injection->host_id()) {
111 manager_->injection_watchers_.push_back(this);
112 }
113
114 ~ScriptInjectionWatcher() {
115 auto& watchers = manager_->injection_watchers_;
116 for (auto it = watchers.begin(); it != watchers.end(); ++it) {
117 if (*it == this) {
118 watchers.erase(it);
119 break;
120 }
121 }
122 }
123
124 void InvalidateHost() {
125 injection_->OnHostRemoved();
126 }
127
128 const HostID& host_id() const { return host_id_; }
129
130 private:
131 ScriptInjection* injection_;
132 ScriptInjectionManager* manager_;
133 HostID host_id_;
134 };
135
106 ScriptInjectionManager::RFOHelper::RFOHelper(content::RenderFrame* render_frame, 136 ScriptInjectionManager::RFOHelper::RFOHelper(content::RenderFrame* render_frame,
107 ScriptInjectionManager* manager) 137 ScriptInjectionManager* manager)
108 : content::RenderFrameObserver(render_frame), 138 : content::RenderFrameObserver(render_frame),
109 manager_(manager), 139 manager_(manager),
110 should_run_idle_(true), 140 should_run_idle_(true),
111 weak_factory_(this) { 141 weak_factory_(this) {
112 } 142 }
113 143
114 ScriptInjectionManager::RFOHelper::~RFOHelper() { 144 ScriptInjectionManager::RFOHelper::~RFOHelper() {
115 } 145 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 const std::string& extension_id) { 308 const std::string& extension_id) {
279 for (auto iter = pending_injections_.begin(); 309 for (auto iter = pending_injections_.begin();
280 iter != pending_injections_.end();) { 310 iter != pending_injections_.end();) {
281 if ((*iter)->host_id().id() == extension_id) { 311 if ((*iter)->host_id().id() == extension_id) {
282 (*iter)->OnHostRemoved(); 312 (*iter)->OnHostRemoved();
283 iter = pending_injections_.erase(iter); 313 iter = pending_injections_.erase(iter);
284 } else { 314 } else {
285 ++iter; 315 ++iter;
286 } 316 }
287 } 317 }
318
319 for (auto watcher : injection_watchers_) {
320 if (watcher->host_id().id() == extension_id)
321 watcher->InvalidateHost();
322 }
288 } 323 }
289 324
290 void ScriptInjectionManager::OnInjectionFinished( 325 void ScriptInjectionManager::OnInjectionFinished(
291 ScriptInjection* injection) { 326 ScriptInjection* injection) {
292 auto iter = 327 auto iter =
293 std::find_if(running_injections_.begin(), running_injections_.end(), 328 std::find_if(running_injections_.begin(), running_injections_.end(),
294 [injection](const std::unique_ptr<ScriptInjection>& mode) { 329 [injection](const std::unique_ptr<ScriptInjection>& mode) {
295 return injection == mode.get(); 330 return injection == mode.get();
296 }); 331 });
297 if (iter != running_injections_.end()) 332 if (iter != running_injections_.end())
298 running_injections_.erase(iter); 333 running_injections_.erase(iter);
299 } 334 }
300 335
301 void ScriptInjectionManager::OnUserScriptsUpdated( 336 void ScriptInjectionManager::OnUserScriptsUpdated(
302 const std::set<HostID>& changed_hosts, 337 const std::set<HostID>& changed_hosts,
303 const std::vector<UserScript*>& scripts) { 338 const std::vector<UserScript*>& scripts) {
304 for (auto iter = pending_injections_.begin(); 339 for (auto iter = pending_injections_.begin();
305 iter != pending_injections_.end();) { 340 iter != pending_injections_.end();) {
306 if (changed_hosts.count((*iter)->host_id()) > 0) 341 if (changed_hosts.count((*iter)->host_id()) > 0) {
342 (*iter)->OnHostRemoved();
307 iter = pending_injections_.erase(iter); 343 iter = pending_injections_.erase(iter);
308 else 344 } else {
309 ++iter; 345 ++iter;
346 }
347 }
348
349 for (auto watcher : injection_watchers_) {
350 if (changed_hosts.count(watcher->host_id()) > 0)
351 watcher->InvalidateHost();
310 } 352 }
311 } 353 }
312 354
313 void ScriptInjectionManager::RemoveObserver(RFOHelper* helper) { 355 void ScriptInjectionManager::RemoveObserver(RFOHelper* helper) {
314 for (auto iter = rfo_helpers_.begin(); iter != rfo_helpers_.end(); ++iter) { 356 for (auto iter = rfo_helpers_.begin(); iter != rfo_helpers_.end(); ++iter) {
315 if (iter->get() == helper) { 357 if (iter->get() == helper) {
316 rfo_helpers_.erase(iter); 358 rfo_helpers_.erase(iter);
317 break; 359 break;
318 } 360 }
319 } 361 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 active_injection_frames_.insert(frame); 436 active_injection_frames_.insert(frame);
395 437
396 ScriptsRunInfo scripts_run_info(frame, run_location); 438 ScriptsRunInfo scripts_run_info(frame, run_location);
397 for (auto iter = frame_injections.begin(); iter != frame_injections.end();) { 439 for (auto iter = frame_injections.begin(); iter != frame_injections.end();) {
398 // It's possible for the frame to be invalidated in the course of injection 440 // It's possible for the frame to be invalidated in the course of injection
399 // (if a script removes its own frame, for example). If this happens, abort. 441 // (if a script removes its own frame, for example). If this happens, abort.
400 if (!active_injection_frames_.count(frame)) 442 if (!active_injection_frames_.count(frame))
401 break; 443 break;
402 std::unique_ptr<ScriptInjection> injection(std::move(*iter)); 444 std::unique_ptr<ScriptInjection> injection(std::move(*iter));
403 iter = frame_injections.erase(iter); 445 iter = frame_injections.erase(iter);
446 ScriptInjectionWatcher watcher(injection.get(), this);
Devlin 2016/07/08 20:51:09 Hmm... I think this isn't quite sufficient. Consi
robwu 2016/07/09 05:22:02 You're right - I solved the issue by constructing
404 TryToInject(std::move(injection), run_location, &scripts_run_info); 447 TryToInject(std::move(injection), run_location, &scripts_run_info);
405 } 448 }
406 449
407 // We are done running in the frame. 450 // We are done running in the frame.
408 active_injection_frames_.erase(frame); 451 active_injection_frames_.erase(frame);
409 452
410 scripts_run_info.LogRun(activity_logging_enabled_); 453 scripts_run_info.LogRun(activity_logging_enabled_);
411 } 454 }
412 455
413 void ScriptInjectionManager::TryToInject( 456 void ScriptInjectionManager::TryToInject(
(...skipping 10 matching lines...) Expand all
424 scripts_run_info, 467 scripts_run_info,
425 base::Bind(&ScriptInjectionManager::OnInjectionFinished, 468 base::Bind(&ScriptInjectionManager::OnInjectionFinished,
426 base::Unretained(this)))) { 469 base::Unretained(this)))) {
427 case ScriptInjection::INJECTION_WAITING: 470 case ScriptInjection::INJECTION_WAITING:
428 pending_injections_.push_back(std::move(injection)); 471 pending_injections_.push_back(std::move(injection));
429 break; 472 break;
430 case ScriptInjection::INJECTION_BLOCKED: 473 case ScriptInjection::INJECTION_BLOCKED:
431 running_injections_.push_back(std::move(injection)); 474 running_injections_.push_back(std::move(injection));
432 break; 475 break;
433 case ScriptInjection::INJECTION_FINISHED: 476 case ScriptInjection::INJECTION_FINISHED:
477 case ScriptInjection::INJECTION_CANCELED:
434 break; 478 break;
435 } 479 }
436 } 480 }
437 481
438 void ScriptInjectionManager::HandleExecuteCode( 482 void ScriptInjectionManager::HandleExecuteCode(
439 const ExtensionMsg_ExecuteCode_Params& params, 483 const ExtensionMsg_ExecuteCode_Params& params,
440 content::RenderFrame* render_frame) { 484 content::RenderFrame* render_frame) {
441 std::unique_ptr<const InjectionHost> injection_host; 485 std::unique_ptr<const InjectionHost> injection_host;
442 if (params.host_id.type() == HostID::EXTENSIONS) { 486 if (params.host_id.type() == HostID::EXTENSIONS) {
443 injection_host = ExtensionInjectionHost::Create(params.host_id.id()); 487 injection_host = ExtensionInjectionHost::Create(params.host_id.id());
444 if (!injection_host) 488 if (!injection_host)
445 return; 489 return;
446 } else if (params.host_id.type() == HostID::WEBUI) { 490 } else if (params.host_id.type() == HostID::WEBUI) {
447 injection_host.reset( 491 injection_host.reset(
448 new WebUIInjectionHost(params.host_id)); 492 new WebUIInjectionHost(params.host_id));
449 } 493 }
450 494
451 std::unique_ptr<ScriptInjection> injection(new ScriptInjection( 495 std::unique_ptr<ScriptInjection> injection(new ScriptInjection(
452 std::unique_ptr<ScriptInjector>( 496 std::unique_ptr<ScriptInjector>(
453 new ProgrammaticScriptInjector(params, render_frame)), 497 new ProgrammaticScriptInjector(params, render_frame)),
454 render_frame, std::move(injection_host), 498 render_frame, std::move(injection_host),
455 static_cast<UserScript::RunLocation>(params.run_at), 499 static_cast<UserScript::RunLocation>(params.run_at),
456 activity_logging_enabled_)); 500 activity_logging_enabled_));
457 501
458 FrameStatusMap::const_iterator iter = frame_statuses_.find(render_frame); 502 FrameStatusMap::const_iterator iter = frame_statuses_.find(render_frame);
459 UserScript::RunLocation run_location = 503 UserScript::RunLocation run_location =
460 iter == frame_statuses_.end() ? UserScript::UNDEFINED : iter->second; 504 iter == frame_statuses_.end() ? UserScript::UNDEFINED : iter->second;
461 505
462 ScriptsRunInfo scripts_run_info(render_frame, run_location); 506 ScriptsRunInfo scripts_run_info(render_frame, run_location);
507 ScriptInjectionWatcher watcher(injection.get(), this);
463 TryToInject(std::move(injection), run_location, &scripts_run_info); 508 TryToInject(std::move(injection), run_location, &scripts_run_info);
464 } 509 }
465 510
466 void ScriptInjectionManager::HandleExecuteDeclarativeScript( 511 void ScriptInjectionManager::HandleExecuteDeclarativeScript(
467 content::RenderFrame* render_frame, 512 content::RenderFrame* render_frame,
468 int tab_id, 513 int tab_id,
469 const ExtensionId& extension_id, 514 const ExtensionId& extension_id,
470 int script_id, 515 int script_id,
471 const GURL& url) { 516 const GURL& url) {
472 std::unique_ptr<ScriptInjection> injection = 517 std::unique_ptr<ScriptInjection> injection =
473 user_script_set_manager_->GetInjectionForDeclarativeScript( 518 user_script_set_manager_->GetInjectionForDeclarativeScript(
474 script_id, render_frame, tab_id, url, extension_id); 519 script_id, render_frame, tab_id, url, extension_id);
475 if (injection.get()) { 520 if (injection.get()) {
476 ScriptsRunInfo scripts_run_info(render_frame, UserScript::BROWSER_DRIVEN); 521 ScriptsRunInfo scripts_run_info(render_frame, UserScript::BROWSER_DRIVEN);
522 ScriptInjectionWatcher watcher(injection.get(), this);
477 // TODO(markdittmer): Use return value of TryToInject for error handling. 523 // TODO(markdittmer): Use return value of TryToInject for error handling.
478 TryToInject(std::move(injection), UserScript::BROWSER_DRIVEN, 524 TryToInject(std::move(injection), UserScript::BROWSER_DRIVEN,
479 &scripts_run_info); 525 &scripts_run_info);
480 526
481 scripts_run_info.LogRun(activity_logging_enabled_); 527 scripts_run_info.LogRun(activity_logging_enabled_);
482 } 528 }
483 } 529 }
484 530
485 void ScriptInjectionManager::HandlePermitScriptInjection(int64_t request_id) { 531 void ScriptInjectionManager::HandlePermitScriptInjection(int64_t request_id) {
486 auto iter = pending_injections_.begin(); 532 auto iter = pending_injections_.begin();
487 for (; iter != pending_injections_.end(); ++iter) { 533 for (; iter != pending_injections_.end(); ++iter) {
488 if ((*iter)->request_id() == request_id) { 534 if ((*iter)->request_id() == request_id) {
489 DCHECK((*iter)->host_id().type() == HostID::EXTENSIONS); 535 DCHECK((*iter)->host_id().type() == HostID::EXTENSIONS);
490 break; 536 break;
491 } 537 }
492 } 538 }
493 if (iter == pending_injections_.end()) 539 if (iter == pending_injections_.end())
494 return; 540 return;
495 541
496 // At this point, because the request is present in pending_injections_, we 542 // At this point, because the request is present in pending_injections_, we
497 // know that this is the same page that issued the request (otherwise, 543 // know that this is the same page that issued the request (otherwise,
498 // RFOHelper::InvalidateAndResetFrame would have caused it to be cleared out). 544 // RFOHelper::InvalidateAndResetFrame would have caused it to be cleared out).
499 545
500 std::unique_ptr<ScriptInjection> injection(std::move(*iter)); 546 std::unique_ptr<ScriptInjection> injection(std::move(*iter));
501 pending_injections_.erase(iter); 547 pending_injections_.erase(iter);
502 548
503 ScriptsRunInfo scripts_run_info(injection->render_frame(), 549 ScriptsRunInfo scripts_run_info(injection->render_frame(),
504 UserScript::RUN_DEFERRED); 550 UserScript::RUN_DEFERRED);
551 ScriptInjectionWatcher watcher(injection.get(), this);
505 ScriptInjection::InjectionResult res = injection->OnPermissionGranted( 552 ScriptInjection::InjectionResult res = injection->OnPermissionGranted(
506 &scripts_run_info); 553 &scripts_run_info);
507 if (res == ScriptInjection::INJECTION_BLOCKED) 554 if (res == ScriptInjection::INJECTION_BLOCKED)
508 running_injections_.push_back(std::move(injection)); 555 running_injections_.push_back(std::move(injection));
509 scripts_run_info.LogRun(activity_logging_enabled_); 556 scripts_run_info.LogRun(activity_logging_enabled_);
510 } 557 }
511 558
512 } // namespace extensions 559 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698