summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-17 21:53:08 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-17 21:53:08 +0000
commit0aa5531f4cfa1a5e4fcb571201f6c39221b1260a (patch)
tree889fd0590f06fdc99d2bee143e060a2d26c8326e /chrome/browser
parent8ef59c3b8d485227dae56a1ce4edc784be329f59 (diff)
downloadchromium_src-0aa5531f4cfa1a5e4fcb571201f6c39221b1260a.zip
chromium_src-0aa5531f4cfa1a5e4fcb571201f6c39221b1260a.tar.gz
chromium_src-0aa5531f4cfa1a5e4fcb571201f6c39221b1260a.tar.bz2
Remove throttling code from the Browser process and implement throttling in the Renderer.
The previous way of doing throttling was just calling CloseContents() on a window to reject it. But since the Browser is notified about a window opening asynchronously, by the time the CloseContents() sends a message back to the Renderer, a bunch more windows have been opened, leading to memory exhaustion. Instead, make all RenderViews created from a parent RenderView share a counter and start refusing to create RenderViews if too many RV have been created. Every RenderView (except for the first one) is assumed to be an unrequested popup, until notified by the Browser process by either a ViewMsg_DisassociateFromPopupCount message (this RenderView is a new top level page) or a ViewMsg_DisassociatePopup message (this RenderView is a requested popup and therefore shouldn't count against the count.) BUG=3382, 2632 Review URL: http://codereview.chromium.org/7388 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3568 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/render_view_host.cc5
-rw-r--r--chrome/browser/render_view_host.h5
-rw-r--r--chrome/browser/tab_contents.cc10
-rw-r--r--chrome/browser/tab_contents.h3
-rw-r--r--chrome/browser/views/constrained_window_impl_interactive_uitest.cc55
-rw-r--r--chrome/browser/web_contents.cc4
-rw-r--r--chrome/browser/web_contents.h1
7 files changed, 74 insertions, 9 deletions
diff --git a/chrome/browser/render_view_host.cc b/chrome/browser/render_view_host.cc
index 03eec5a..0ac3e16 100644
--- a/chrome/browser/render_view_host.cc
+++ b/chrome/browser/render_view_host.cc
@@ -1005,6 +1005,10 @@ void RenderViewHost::OnPersonalizationEvent(const std::string& message,
}
#endif
+void RenderViewHost::DisassociateFromPopupCount() {
+ Send(new ViewMsg_DisassociateFromPopupCount(routing_id_));
+}
+
void RenderViewHost::OnMsgGoToEntryAtOffset(int offset) {
delegate_->GoToEntryAtOffset(offset);
}
@@ -1222,4 +1226,3 @@ void RenderViewHost::ForwardMessageFromExternalHost(
const std::string& target, const std::string& message) {
Send(new ViewMsg_HandleMessageFromExternalHost(routing_id_, target, message));
}
-
diff --git a/chrome/browser/render_view_host.h b/chrome/browser/render_view_host.h
index 34616a3..8bf8e7f 100644
--- a/chrome/browser/render_view_host.h
+++ b/chrome/browser/render_view_host.h
@@ -382,6 +382,10 @@ class RenderViewHost : public RenderWidgetHost {
void ForwardMessageFromExternalHost(const std::string& target,
const std::string& message);
+ // Message the renderer that we should be counted as a new document and not
+ // as a popup.
+ void DisassociateFromPopupCount();
+
protected:
// Overridden from RenderWidgetHost:
virtual void UnhandledInputEvent(const WebInputEvent& event);
@@ -579,4 +583,3 @@ class RenderViewHostFactory {
};
#endif // CHROME_BROWSER_RENDER_VIEW_HOST_H__
-
diff --git a/chrome/browser/tab_contents.cc b/chrome/browser/tab_contents.cc
index fcd2b93..6234abb 100644
--- a/chrome/browser/tab_contents.cc
+++ b/chrome/browser/tab_contents.cc
@@ -21,8 +21,6 @@
#include "generated_resources.h"
-static size_t kMaxNumberOfConstrainedPopups = 20;
-
namespace {
BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
@@ -283,6 +281,8 @@ void TabContents::AddNewContents(TabContents* new_contents,
popup_owner = our_owner;
popup_owner->AddConstrainedPopup(new_contents, initial_pos);
} else {
+ new_contents->DisassociateFromPopupCount();
+
delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
user_gesture);
}
@@ -290,11 +290,6 @@ void TabContents::AddNewContents(TabContents* new_contents,
void TabContents::AddConstrainedPopup(TabContents* new_contents,
const gfx::Rect& initial_pos) {
- if (child_windows_.size() > kMaxNumberOfConstrainedPopups) {
- new_contents->CloseContents();
- return;
- }
-
ConstrainedWindow* window =
ConstrainedWindow::CreateConstrainedPopup(
this, initial_pos, new_contents);
@@ -499,6 +494,7 @@ void TabContents::DetachContents(ConstrainedWindow* window,
int frame_component) {
WillClose(window);
if (delegate_) {
+ contents->DisassociateFromPopupCount();
delegate_->StartDraggingDetachedContents(
this, contents, contents_bounds, mouse_pt, frame_component);
}
diff --git a/chrome/browser/tab_contents.h b/chrome/browser/tab_contents.h
index 99daf5d..3b38963 100644
--- a/chrome/browser/tab_contents.h
+++ b/chrome/browser/tab_contents.h
@@ -314,6 +314,9 @@ class TabContents : public PageNavigator,
virtual void Copy() { }
virtual void Paste() { }
+ // Called on a TabContents when it isn't a popup, but a new window.
+ virtual void DisassociateFromPopupCount() { }
+
// Window management ---------------------------------------------------------
// Create a new window constrained to this TabContents' clip and visibility.
diff --git a/chrome/browser/views/constrained_window_impl_interactive_uitest.cc b/chrome/browser/views/constrained_window_impl_interactive_uitest.cc
index 3dc184f..860a009 100644
--- a/chrome/browser/views/constrained_window_impl_interactive_uitest.cc
+++ b/chrome/browser/views/constrained_window_impl_interactive_uitest.cc
@@ -143,3 +143,58 @@ TEST_F(InteractiveConstrainedWindowTest, ClickingXClosesConstrained) {
EXPECT_TRUE(automation()->GetBrowserWindowCount(&browser_window_count));
EXPECT_EQ(browser_window_count, 1);
}
+
+// Tests that in the window.open() equivalent of a fork bomb, we stop building
+// windows.
+TEST_F(InteractiveConstrainedWindowTest, DontSpawnEndlessPopups) {
+ scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
+ ASSERT_TRUE(browser.get());
+
+ scoped_ptr<WindowProxy> window(
+ automation()->GetWindowForBrowser(browser.get()));
+ ASSERT_TRUE(window.get());
+
+ scoped_ptr<TabProxy> tab(browser->GetTab(0));
+ ASSERT_TRUE(tab.get());
+
+ std::wstring filename(test_data_directory_);
+ file_util::AppendToPath(&filename, L"constrained_files");
+ file_util::AppendToPath(&filename,
+ L"infinite_popups.html");
+ ASSERT_TRUE(tab->NavigateToURL(net::FilePathToFileURL(filename)));
+
+ gfx::Rect tab_view_bounds;
+ ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_CONTAINER,
+ &tab_view_bounds, true));
+
+ // Simulate a click of the actual link to force user_gesture to be
+ // true; if we don't, the resulting popup will be constrained, which
+ // isn't what we want to test.
+ POINT link_point(tab_view_bounds.CenterPoint().ToPOINT());
+ ASSERT_TRUE(window->SimulateOSClick(link_point,
+ views::Event::EF_LEFT_BUTTON_DOWN));
+
+ ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2, 1000));
+
+ scoped_ptr<BrowserProxy> popup_browser(automation()->GetBrowserWindow(1));
+ ASSERT_TRUE(popup_browser.get());
+ scoped_ptr<TabProxy> popup_tab(popup_browser->GetTab(0));
+ ASSERT_TRUE(popup_tab.get());
+
+ // And now we spin on this, waiting to make sure that we don't spawn popup
+ // windows endlessly. The current limit is 25, so allowing for possible race
+ // conditions and one off errors, don't break out until we go over 35 popup
+ // windows (in which case we are bork bork bork).
+ const int kMaxPopupWindows = 35;
+ int constrained_window_count = 0;
+ int new_constrained_window_count;
+ bool continuing = true;
+ while (continuing && constrained_window_count < kMaxPopupWindows) {
+ continuing = popup_tab->WaitForChildWindowCountToChange(
+ constrained_window_count, &new_constrained_window_count,
+ 100000);
+ EXPECT_GE(new_constrained_window_count, constrained_window_count);
+ EXPECT_LE(new_constrained_window_count, kMaxPopupWindows);
+ constrained_window_count = new_constrained_window_count;
+ }
+}
diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc
index e842db8..f7c9daf 100644
--- a/chrome/browser/web_contents.cc
+++ b/chrome/browser/web_contents.cc
@@ -414,6 +414,10 @@ void WebContents::Paste() {
render_view_host()->Paste();
}
+void WebContents::DisassociateFromPopupCount() {
+ render_view_host()->DisassociateFromPopupCount();
+}
+
void WebContents::DidBecomeSelected() {
TabContents::DidBecomeSelected();
diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h
index 8a5f6aa..a58cf58 100644
--- a/chrome/browser/web_contents.h
+++ b/chrome/browser/web_contents.h
@@ -92,6 +92,7 @@ class WebContents : public TabContents,
virtual void Cut();
virtual void Copy();
virtual void Paste();
+ virtual void DisassociateFromPopupCount();
virtual void DidBecomeSelected();
virtual void WasHidden();
virtual void ShowContents();