Chromium Code Reviews| 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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |