Index: chrome/browser/prerender/prerender_browsertest.cc |
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc |
index af8e09ed433e94793eb371b79ce30424c3a2e5a5..0ca3679326fcd6906921a9787e3d0217855ba56e 100644 |
--- a/chrome/browser/prerender/prerender_browsertest.cc |
+++ b/chrome/browser/prerender/prerender_browsertest.cc |
@@ -46,6 +46,7 @@ |
#include "chrome/browser/ui/browser_commands.h" |
#include "chrome/browser/ui/browser_finder.h" |
#include "chrome/browser/ui/browser_navigator.h" |
+#include "chrome/browser/ui/browser_tabstrip.h" |
#include "chrome/browser/ui/browser_window.h" |
#include "chrome/browser/ui/tabs/tab_strip_model.h" |
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" |
@@ -322,12 +323,17 @@ class NewTabNavigationOrSwapObserver { |
: new_tab_observer_( |
chrome::NOTIFICATION_TAB_ADDED, |
base::Bind(&NewTabNavigationOrSwapObserver::OnTabAdded, |
- base::Unretained(this))) { |
+ base::Unretained(this))), |
+ new_tab_(NULL) { |
// Watch for NOTIFICATION_TAB_ADDED. Add a callback so that the |
// NavigationOrSwapObserver can be attached synchronously and no events are |
// missed. |
} |
+ WebContents* new_tab() const { |
+ return new_tab_; |
+ } |
+ |
void Wait() { |
new_tab_observer_.Wait(); |
swap_observer_->Wait(); |
@@ -337,17 +343,18 @@ class NewTabNavigationOrSwapObserver { |
const content::NotificationDetails& details) { |
if (swap_observer_) |
return true; |
- WebContents* new_tab = content::Details<WebContents>(details).ptr(); |
+ new_tab_ = content::Details<WebContents>(details).ptr(); |
// Get the TabStripModel. Assume this is attached to a Browser. |
TabStripModel* tab_strip_model = |
- static_cast<Browser*>(new_tab->GetDelegate())->tab_strip_model(); |
+ static_cast<Browser*>(new_tab_->GetDelegate())->tab_strip_model(); |
swap_observer_.reset(new NavigationOrSwapObserver(tab_strip_model, |
- new_tab)); |
+ new_tab_)); |
return true; |
} |
private: |
content::WindowedNotificationObserver new_tab_observer_; |
+ WebContents* new_tab_; |
scoped_ptr<NavigationOrSwapObserver> swap_observer_; |
}; |
@@ -1155,36 +1162,40 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
OpenURLWithJSImpl("Click", url, GURL(), false); |
} |
- void OpenDestURLViaClickTarget() const { |
- OpenURLWithJSImpl("ClickTarget", dest_url_, GURL(), true); |
+ WebContents* OpenDestURLViaClickTarget() const { |
+ return OpenURLWithJSImpl("ClickTarget", dest_url_, GURL(), true); |
} |
void OpenDestURLViaClickPing(const GURL& ping_url) const { |
OpenURLWithJSImpl("ClickPing", dest_url_, ping_url, false); |
} |
- void OpenDestURLViaClickNewWindow() const { |
- OpenURLWithJSImpl("ShiftClick", dest_url_, GURL(), true); |
+ WebContents* OpenDestURLViaClickNewWindow() const { |
+ return OpenURLWithJSImpl("ShiftClick", dest_url_, GURL(), true); |
} |
- void OpenDestURLViaClickNewForegroundTab() const { |
+ WebContents* OpenDestURLViaClickNewForegroundTab() const { |
#if defined(OS_MACOSX) |
- OpenURLWithJSImpl("MetaShiftClick", dest_url_, GURL(), true); |
+ return OpenURLWithJSImpl("MetaShiftClick", dest_url_, GURL(), true); |
#else |
- OpenURLWithJSImpl("CtrlShiftClick", dest_url_, GURL(), true); |
+ return OpenURLWithJSImpl("CtrlShiftClick", dest_url_, GURL(), true); |
#endif |
} |
- void OpenDestURLViaClickNewBackgroundTab() const { |
+ WebContents* OpenDestURLViaClickNewBackgroundTab() const { |
#if defined(OS_MACOSX) |
- OpenURLWithJSImpl("MetaClick", dest_url_, GURL(), true); |
+ return OpenURLWithJSImpl("MetaClick", dest_url_, GURL(), true); |
#else |
- OpenURLWithJSImpl("CtrlClick", dest_url_, GURL(), true); |
+ return OpenURLWithJSImpl("CtrlClick", dest_url_, GURL(), true); |
#endif |
} |
- void OpenDestURLViaWindowOpen() const { |
- OpenURLWithJSImpl("WindowOpen", dest_url_, GURL(), true); |
+ WebContents* OpenDestURLViaWindowOpen() const { |
+ return OpenURLViaWindowOpen(dest_url_); |
+ } |
+ |
+ WebContents* OpenURLViaWindowOpen(const GURL& url) const { |
+ return OpenURLWithJSImpl("WindowOpen", url, GURL(), true); |
} |
void RemoveLinkElement(int i) const { |
@@ -1580,12 +1591,12 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
// Opens the prerendered page using javascript functions in the loader |
// page. |javascript_function_name| should be a 0 argument function which is |
- // invoked. |new_web_contents| is true if the navigation is expected to |
- // happen in a new WebContents via OpenURL. |
- void OpenURLWithJSImpl(const std::string& javascript_function_name, |
- const GURL& url, |
- const GURL& ping_url, |
- bool new_web_contents) const { |
+ // invoked. |new_web_contents| is true if the navigation is expected to happen |
+ // in a new WebContents via OpenURL and the new WebContents is returned. |
+ WebContents* OpenURLWithJSImpl(const std::string& javascript_function_name, |
+ const GURL& url, |
+ const GURL& ping_url, |
+ bool new_web_contents) const { |
WebContents* web_contents = GetActiveWebContents(); |
RenderFrameHost* render_frame_host = web_contents->GetMainFrame(); |
// Extra arguments in JS are ignored. |
@@ -1597,11 +1608,13 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { |
NewTabNavigationOrSwapObserver observer; |
render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript)); |
observer.Wait(); |
+ return observer.new_tab(); |
} else { |
NavigationOrSwapObserver observer(current_browser()->tab_strip_model(), |
web_contents); |
render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript)); |
observer.Wait(); |
+ return NULL; |
} |
} |
@@ -2869,6 +2882,37 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, |
OpenDestURLViaClickTarget(); |
} |
+// Checks that, if a popup's opener is closed, it still will not accept |
+// prerender swaps. This is relevant in determining whether window.close() may |
+// be called. |
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderOpenerClosed) { |
+ // Bump the abandon timeout to ensure the prerender survives its referrer |
+ // closing. |
+ GetPrerenderManager()->mutable_config().abandon_time_to_live = |
+ base::TimeDelta::FromMinutes(5); |
+ |
+ PrerenderTestURL("files/prerender/prerender_page.html", |
+ FINAL_STATUS_WINDOW_OPENER, |
+ 1); |
+ |
+ // Open a popup with the referring page as opener. |
+ WebContents* opener = GetActiveWebContents(); |
+ WebContents* popup = OpenURLViaWindowOpen(GURL(content::kAboutBlankURL)); |
+ |
+ // Close the opener. The opener is gone, but WasOpenedByDOM() remains true. |
+ EXPECT_TRUE(popup->HasOpener()); |
+ EXPECT_TRUE(popup->CreatedWithOpener()); |
+ chrome::CloseWebContents(browser(), opener, false); |
+ EXPECT_FALSE(popup->HasOpener()); |
+ EXPECT_TRUE(popup->CreatedWithOpener()); |
+ |
+ // Assume the popup is attached to a Browser. |
+ set_browser(static_cast<Browser*>(popup->GetDelegate())); |
+ |
+ // The prerender should not swap. |
+ NavigateToURLWithDisposition(dest_url(), CURRENT_TAB, false); |
+} |
+ |
class TestClientCertStore : public net::ClientCertStore { |
public: |
TestClientCertStore() {} |