Index: extensions/renderer/programmatic_script_injector.cc |
diff --git a/extensions/renderer/programmatic_script_injector.cc b/extensions/renderer/programmatic_script_injector.cc |
index bc94d043b27c9b756061ec694b95e1c9af7e45de..3c9b938f27968c8aad806ceab25b73e300c99c0b 100644 |
--- a/extensions/renderer/programmatic_script_injector.cc |
+++ b/extensions/renderer/programmatic_script_injector.cc |
@@ -9,6 +9,7 @@ |
#include "base/values.h" |
#include "content/public/common/url_constants.h" |
#include "content/public/renderer/render_frame.h" |
+#include "content/public/renderer/render_frame_observer.h" |
#include "extensions/common/error_utils.h" |
#include "extensions/common/extension_messages.h" |
#include "extensions/common/manifest_constants.h" |
@@ -22,13 +23,33 @@ |
namespace extensions { |
+// Watches for the deletion of a RenderFrame, after which is_valid will return |
+// false. |
+class ProgrammaticScriptInjector::FrameWatcher |
+ : public content::RenderFrameObserver { |
+ public: |
+ explicit FrameWatcher(content::RenderFrame* render_frame) |
+ : content::RenderFrameObserver(render_frame), is_valid_(true) {} |
+ ~FrameWatcher() override {} |
+ |
+ bool is_frame_valid() const { return is_valid_; } |
+ |
+ private: |
+ void FrameDetached() override { is_valid_ = false; } |
+ void OnDestruct() override { is_valid_ = false; } |
+ |
+ bool is_valid_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FrameWatcher); |
+}; |
+ |
ProgrammaticScriptInjector::ProgrammaticScriptInjector( |
const ExtensionMsg_ExecuteCode_Params& params, |
content::RenderFrame* render_frame) |
: params_(new ExtensionMsg_ExecuteCode_Params(params)), |
- url_(ScriptContext::GetDataSourceURLForFrame( |
- render_frame->GetWebFrame())), |
- render_frame_(render_frame), |
+ url_( |
+ ScriptContext::GetDataSourceURLForFrame(render_frame->GetWebFrame())), |
+ frame_watcher_(new FrameWatcher(render_frame)), |
finished_(false) { |
effective_url_ = ScriptContext::GetEffectiveDocumentURL( |
render_frame->GetWebFrame(), url_, params.match_about_blank); |
@@ -150,12 +171,15 @@ void ProgrammaticScriptInjector::Finish(const std::string& error) { |
DCHECK(!finished_); |
finished_ = true; |
- render_frame_->Send(new ExtensionHostMsg_ExecuteCodeFinished( |
- render_frame_->GetRoutingID(), |
- params_->request_id, |
- error, |
- url_, |
- results_)); |
+ // It's possible that the render frame was destroyed in the course of |
+ // injecting scripts. Don't respond if it was (the browser side watches for |
+ // frame deletions so nothing is left hanging). |
+ if (frame_watcher_->is_frame_valid()) { |
+ frame_watcher_->render_frame()->Send( |
+ new ExtensionHostMsg_ExecuteCodeFinished( |
+ frame_watcher_->render_frame()->GetRoutingID(), params_->request_id, |
+ error, url_, results_)); |
+ } |
} |
} // namespace extensions |