OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "base/files/file_path.h" | 5 #include "base/files/file_path.h" |
6 #include "base/strings/utf_string_conversions.h" | 6 #include "base/strings/utf_string_conversions.h" |
7 #include "content/browser/frame_host/cross_site_transferring_request.h" | 7 #include "content/browser/frame_host/cross_site_transferring_request.h" |
8 #include "content/browser/frame_host/navigation_controller_impl.h" | 8 #include "content/browser/frame_host/navigation_controller_impl.h" |
9 #include "content/browser/frame_host/navigation_entry_impl.h" | 9 #include "content/browser/frame_host/navigation_entry_impl.h" |
10 #include "content/browser/frame_host/navigator.h" | 10 #include "content/browser/frame_host/navigator.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 } | 117 } |
118 | 118 |
119 private: | 119 private: |
120 int process_id_; | 120 int process_id_; |
121 int routing_id_; | 121 int routing_id_; |
122 bool deleted_; | 122 bool deleted_; |
123 | 123 |
124 DISALLOW_COPY_AND_ASSIGN(RenderViewHostDeletedObserver); | 124 DISALLOW_COPY_AND_ASSIGN(RenderViewHostDeletedObserver); |
125 }; | 125 }; |
126 | 126 |
127 | 127 // This observer keeps track of the last deleted RenderFrameHost to avoid |
128 // This observer keeps track of the last deleted RenderViewHost to avoid | |
129 // accessing it and causing use-after-free condition. | 128 // accessing it and causing use-after-free condition. |
130 class RenderFrameHostDeletedObserver : public WebContentsObserver { | 129 class RenderFrameHostDeletedObserver : public WebContentsObserver { |
131 public: | 130 public: |
132 RenderFrameHostDeletedObserver(RenderFrameHost* rfh) | 131 RenderFrameHostDeletedObserver(RenderFrameHost* rfh) |
133 : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)), | 132 : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)), |
134 process_id_(rfh->GetProcess()->GetID()), | 133 process_id_(rfh->GetProcess()->GetID()), |
135 routing_id_(rfh->GetRoutingID()), | 134 routing_id_(rfh->GetRoutingID()), |
136 deleted_(false) { | 135 deleted_(false) { |
137 } | 136 } |
138 | 137 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 return favicon_received_; | 185 return favicon_received_; |
187 } | 186 } |
188 | 187 |
189 private: | 188 private: |
190 bool plugin_crashed_; | 189 bool plugin_crashed_; |
191 bool favicon_received_; | 190 bool favicon_received_; |
192 | 191 |
193 DISALLOW_COPY_AND_ASSIGN(PluginFaviconMessageObserver); | 192 DISALLOW_COPY_AND_ASSIGN(PluginFaviconMessageObserver); |
194 }; | 193 }; |
195 | 194 |
| 195 // Ensures that RenderFrameDeleted and RenderFrameCreated are called in a |
| 196 // consistent manner. |
| 197 class FrameLifetimeConsistencyChecker : public WebContentsObserver { |
| 198 public: |
| 199 explicit FrameLifetimeConsistencyChecker(WebContentsImpl* web_contents) |
| 200 : WebContentsObserver(web_contents) { |
| 201 RenderViewCreated(web_contents->GetRenderViewHost()); |
| 202 RenderFrameCreated(web_contents->GetMainFrame()); |
| 203 } |
| 204 |
| 205 virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE { |
| 206 std::pair<int, int> routing_pair = |
| 207 std::make_pair(render_frame_host->GetProcess()->GetID(), |
| 208 render_frame_host->GetRoutingID()); |
| 209 bool was_live_already = !live_routes_.insert(routing_pair).second; |
| 210 bool was_used_before = deleted_routes_.count(routing_pair) != 0; |
| 211 |
| 212 if (was_live_already) { |
| 213 FAIL() << "RenderFrameCreated called more than once for routing pair: " |
| 214 << Format(render_frame_host); |
| 215 } else if (was_used_before) { |
| 216 FAIL() << "RenderFrameCreated called for routing pair " |
| 217 << Format(render_frame_host) << " that was previously deleted."; |
| 218 } |
| 219 } |
| 220 |
| 221 virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE { |
| 222 std::pair<int, int> routing_pair = |
| 223 std::make_pair(render_frame_host->GetProcess()->GetID(), |
| 224 render_frame_host->GetRoutingID()); |
| 225 bool was_live = live_routes_.erase(routing_pair); |
| 226 bool was_dead_already = !deleted_routes_.insert(routing_pair).second; |
| 227 |
| 228 if (was_dead_already) { |
| 229 FAIL() << "RenderFrameDeleted called more than once for routing pair " |
| 230 << Format(render_frame_host); |
| 231 } else if (!was_live) { |
| 232 FAIL() << "RenderFrameDeleted called for routing pair " |
| 233 << Format(render_frame_host) |
| 234 << " for which RenderFrameCreated was never called"; |
| 235 } |
| 236 } |
| 237 |
| 238 private: |
| 239 std::string Format(RenderFrameHost* render_frame_host) { |
| 240 return base::StringPrintf( |
| 241 "(%d, %d -> %s )", |
| 242 render_frame_host->GetProcess()->GetID(), |
| 243 render_frame_host->GetRoutingID(), |
| 244 render_frame_host->GetSiteInstance()->GetSiteURL().spec().c_str()); |
| 245 } |
| 246 std::set<std::pair<int, int> > live_routes_; |
| 247 std::set<std::pair<int, int> > deleted_routes_; |
| 248 }; |
196 | 249 |
197 } // namespace | 250 } // namespace |
198 | 251 |
199 class RenderFrameHostManagerTest | 252 class RenderFrameHostManagerTest |
200 : public RenderViewHostImplTestHarness { | 253 : public RenderViewHostImplTestHarness { |
201 public: | 254 public: |
202 virtual void SetUp() OVERRIDE { | 255 virtual void SetUp() OVERRIDE { |
203 RenderViewHostImplTestHarness::SetUp(); | 256 RenderViewHostImplTestHarness::SetUp(); |
204 WebUIControllerFactory::RegisterFactory(&factory_); | 257 WebUIControllerFactory::RegisterFactory(&factory_); |
| 258 lifetime_checker_.reset(new FrameLifetimeConsistencyChecker(contents())); |
205 } | 259 } |
206 | 260 |
207 virtual void TearDown() OVERRIDE { | 261 virtual void TearDown() OVERRIDE { |
| 262 lifetime_checker_.reset(); |
208 RenderViewHostImplTestHarness::TearDown(); | 263 RenderViewHostImplTestHarness::TearDown(); |
209 WebUIControllerFactory::UnregisterFactoryForTesting(&factory_); | 264 WebUIControllerFactory::UnregisterFactoryForTesting(&factory_); |
210 } | 265 } |
211 | 266 |
212 void set_should_create_webui(bool should_create_webui) { | 267 void set_should_create_webui(bool should_create_webui) { |
213 factory_.set_should_create_webui(should_create_webui); | 268 factory_.set_should_create_webui(should_create_webui); |
214 } | 269 } |
215 | 270 |
216 void StartCrossSiteTransition(TestWebContents* contents) { | 271 void StartCrossSiteTransition(TestWebContents* contents) { |
217 std::vector<GURL> url_chain; | 272 std::vector<GURL> url_chain; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 358 |
304 dest_rvh->SendNavigate(101, kDestUrl); | 359 dest_rvh->SendNavigate(101, kDestUrl); |
305 ntp_rvh->OnSwappedOut(false); | 360 ntp_rvh->OnSwappedOut(false); |
306 | 361 |
307 EXPECT_TRUE(ntp_rvh->IsSwappedOut()); | 362 EXPECT_TRUE(ntp_rvh->IsSwappedOut()); |
308 return ntp_rvh; | 363 return ntp_rvh; |
309 } | 364 } |
310 | 365 |
311 private: | 366 private: |
312 RenderFrameHostManagerTestWebUIControllerFactory factory_; | 367 RenderFrameHostManagerTestWebUIControllerFactory factory_; |
| 368 scoped_ptr<FrameLifetimeConsistencyChecker> lifetime_checker_; |
313 }; | 369 }; |
314 | 370 |
315 // Tests that when you navigate from a chrome:// url to another page, and | 371 // Tests that when you navigate from a chrome:// url to another page, and |
316 // then do that same thing in another tab, that the two resulting pages have | 372 // then do that same thing in another tab, that the two resulting pages have |
317 // different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is | 373 // different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is |
318 // a regression test for bug 9364. | 374 // a regression test for bug 9364. |
319 TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) { | 375 TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) { |
320 set_should_create_webui(true); | 376 set_should_create_webui(true); |
321 const GURL kChromeUrl("chrome://foo"); | 377 const GURL kChromeUrl("chrome://foo"); |
322 const GURL kDestUrl("http://www.google.com/"); | 378 const GURL kDestUrl("http://www.google.com/"); |
(...skipping 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1782 pending_rfh->GetSiteInstance())->increment_active_view_count(); | 1838 pending_rfh->GetSiteInstance())->increment_active_view_count(); |
1783 | 1839 |
1784 main_test_rfh()->OnMessageReceived( | 1840 main_test_rfh()->OnMessageReceived( |
1785 FrameHostMsg_BeforeUnload_ACK(0, false, now, now)); | 1841 FrameHostMsg_BeforeUnload_ACK(0, false, now, now)); |
1786 EXPECT_FALSE(contents()->cross_navigation_pending()); | 1842 EXPECT_FALSE(contents()->cross_navigation_pending()); |
1787 EXPECT_FALSE(rvh_deleted_observer.deleted()); | 1843 EXPECT_FALSE(rvh_deleted_observer.deleted()); |
1788 } | 1844 } |
1789 } | 1845 } |
1790 | 1846 |
1791 } // namespace content | 1847 } // namespace content |
OLD | NEW |