| Index: content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| index 798ab6a4ecf9b918db0c00b4b1da49195e966022..a5100dfbe4b2dc071a52f2e80d9c8271e3b260c9 100644
|
| --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| @@ -124,8 +124,7 @@ class RenderViewHostDeletedObserver : public WebContentsObserver {
|
| DISALLOW_COPY_AND_ASSIGN(RenderViewHostDeletedObserver);
|
| };
|
|
|
| -
|
| -// This observer keeps track of the last deleted RenderViewHost to avoid
|
| +// This observer keeps track of the last deleted RenderFrameHost to avoid
|
| // accessing it and causing use-after-free condition.
|
| class RenderFrameHostDeletedObserver : public WebContentsObserver {
|
| public:
|
| @@ -193,6 +192,60 @@ class PluginFaviconMessageObserver : public WebContentsObserver {
|
| DISALLOW_COPY_AND_ASSIGN(PluginFaviconMessageObserver);
|
| };
|
|
|
| +// Ensures that RenderFrameDeleted and RenderFrameCreated are called in a
|
| +// consistent manner.
|
| +class FrameLifetimeConsistencyChecker : public WebContentsObserver {
|
| + public:
|
| + explicit FrameLifetimeConsistencyChecker(WebContentsImpl* web_contents)
|
| + : WebContentsObserver(web_contents) {
|
| + RenderViewCreated(web_contents->GetRenderViewHost());
|
| + RenderFrameCreated(web_contents->GetMainFrame());
|
| + }
|
| +
|
| + virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE {
|
| + std::pair<int, int> routing_pair =
|
| + std::make_pair(render_frame_host->GetProcess()->GetID(),
|
| + render_frame_host->GetRoutingID());
|
| + bool was_live_already = !live_routes_.insert(routing_pair).second;
|
| + bool was_used_before = deleted_routes_.count(routing_pair) != 0;
|
| +
|
| + if (was_live_already) {
|
| + FAIL() << "RenderFrameCreated called more than once for routing pair: "
|
| + << Format(render_frame_host);
|
| + } else if (was_used_before) {
|
| + FAIL() << "RenderFrameCreated called for routing pair "
|
| + << Format(render_frame_host) << " that was previously deleted.";
|
| + }
|
| + }
|
| +
|
| + virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE {
|
| + std::pair<int, int> routing_pair =
|
| + std::make_pair(render_frame_host->GetProcess()->GetID(),
|
| + render_frame_host->GetRoutingID());
|
| + bool was_live = live_routes_.erase(routing_pair);
|
| + bool was_dead_already = !deleted_routes_.insert(routing_pair).second;
|
| +
|
| + if (was_dead_already) {
|
| + FAIL() << "RenderFrameDeleted called more than once for routing pair "
|
| + << Format(render_frame_host);
|
| + } else if (!was_live) {
|
| + FAIL() << "RenderFrameDeleted called for routing pair "
|
| + << Format(render_frame_host)
|
| + << " for which RenderFrameCreated was never called";
|
| + }
|
| + }
|
| +
|
| + private:
|
| + std::string Format(RenderFrameHost* render_frame_host) {
|
| + return base::StringPrintf(
|
| + "(%d, %d -> %s )",
|
| + render_frame_host->GetProcess()->GetID(),
|
| + render_frame_host->GetRoutingID(),
|
| + render_frame_host->GetSiteInstance()->GetSiteURL().spec().c_str());
|
| + }
|
| + std::set<std::pair<int, int> > live_routes_;
|
| + std::set<std::pair<int, int> > deleted_routes_;
|
| +};
|
|
|
| } // namespace
|
|
|
| @@ -202,9 +255,11 @@ class RenderFrameHostManagerTest
|
| virtual void SetUp() OVERRIDE {
|
| RenderViewHostImplTestHarness::SetUp();
|
| WebUIControllerFactory::RegisterFactory(&factory_);
|
| + lifetime_checker_.reset(new FrameLifetimeConsistencyChecker(contents()));
|
| }
|
|
|
| virtual void TearDown() OVERRIDE {
|
| + lifetime_checker_.reset();
|
| RenderViewHostImplTestHarness::TearDown();
|
| WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
|
| }
|
| @@ -310,6 +365,7 @@ class RenderFrameHostManagerTest
|
|
|
| private:
|
| RenderFrameHostManagerTestWebUIControllerFactory factory_;
|
| + scoped_ptr<FrameLifetimeConsistencyChecker> lifetime_checker_;
|
| };
|
|
|
| // Tests that when you navigate from a chrome:// url to another page, and
|
|
|