summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/render_thread.cc5
-rw-r--r--chrome/renderer/render_view.cc47
-rw-r--r--chrome/renderer/render_view.h44
3 files changed, 80 insertions, 16 deletions
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 56ed3a8..fd262de 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -205,9 +205,9 @@ void RenderThread::OnCreateNewView(HWND parent_hwnd,
int32 view_id) {
// TODO(darin): once we have a RenderThread per RenderView, this will need to
// change to assert that we are not creating more than one view.
-
RenderView::Create(
- parent_hwnd, modal_dialog_event, MSG_ROUTING_NONE, webkit_prefs, view_id);
+ parent_hwnd, modal_dialog_event, MSG_ROUTING_NONE, webkit_prefs,
+ new SharedRenderViewCounter(0), view_id);
}
void RenderThread::OnSetCacheCapacities(size_t min_dead_capacity,
@@ -238,4 +238,3 @@ void RenderThread::InformHostOfCacheStatsLater() {
&RenderThread::InformHostOfCacheStats),
kCacheStatsDelayMS);
}
-
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 48f1a4c..253a869 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -94,6 +94,9 @@ const TimeDelta kDelayForNavigationSync = TimeDelta::FromSeconds(5);
// globally unique in the renderer.
static int32 next_page_id_ = 1;
+// The maximum number of popups that can be spawned from one page.
+static const int kMaximumNumberOfUnacknowledgedPopups = 25;
+
static const char* const kUnreachableWebDataURL =
"chrome-resource://chromewebdata/";
@@ -152,6 +155,7 @@ RenderView::RenderView()
history_forward_list_count_(0),
disable_popup_blocking_(false),
has_unload_listener_(false),
+ decrement_shared_popup_at_destruction_(false),
greasemonkey_enabled_(false) {
resource_dispatcher_ = new ResourceDispatcher(this);
#ifdef CHROME_PERSONALIZATION
@@ -160,6 +164,9 @@ RenderView::RenderView()
}
RenderView::~RenderView() {
+ if (decrement_shared_popup_at_destruction_)
+ shared_popup_counter_->data--;
+
resource_dispatcher_->ClearMessageSender();
// Clear any back-pointers that might still be held by plugins.
PluginDelegateList::iterator it = plugin_delegates_.begin();
@@ -177,17 +184,20 @@ RenderView::~RenderView() {
}
/*static*/
-RenderView* RenderView::Create(HWND parent_hwnd,
- HANDLE modal_dialog_event,
- int32 opener_id,
- const WebPreferences& webkit_prefs,
- int32 routing_id) {
+RenderView* RenderView::Create(
+ HWND parent_hwnd,
+ HANDLE modal_dialog_event,
+ int32 opener_id,
+ const WebPreferences& webkit_prefs,
+ SharedRenderViewCounter* counter,
+ int32 routing_id) {
DCHECK(routing_id != MSG_ROUTING_NONE);
scoped_refptr<RenderView> view = new RenderView();
view->Init(parent_hwnd,
modal_dialog_event,
opener_id,
webkit_prefs,
+ counter,
routing_id); // adds reference
return view;
}
@@ -227,12 +237,22 @@ void RenderView::Init(HWND parent_hwnd,
HANDLE modal_dialog_event,
int32 opener_id,
const WebPreferences& webkit_prefs,
+ SharedRenderViewCounter* counter,
int32 routing_id) {
DCHECK(!webview());
if (opener_id != MSG_ROUTING_NONE)
opener_id_ = opener_id;
+ if (counter) {
+ shared_popup_counter_ = counter;
+ shared_popup_counter_->data++;
+ decrement_shared_popup_at_destruction_ = true;
+ } else {
+ shared_popup_counter_ = new SharedRenderViewCounter(0);
+ decrement_shared_popup_at_destruction_ = false;
+ }
+
// Avoid a leak here by not assigning, since WebView::Create addrefs for us.
WebWidget* view = WebView::Create(this, webkit_prefs);
webwidget_.swap(&view);
@@ -344,6 +364,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
#endif
IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
OnMessageFromExternalHost)
+ IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
+ OnDisassociateFromPopupCount)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
IPC_END_MESSAGE_MAP()
@@ -1673,6 +1695,10 @@ void RenderView::DebuggerOutput(const std::wstring& out) {
}
WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
+ // Check to make sure we aren't overloading on popups.
+ if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
+ return NULL;
+
int32 routing_id = MSG_ROUTING_NONE;
HANDLE modal_dialog_event = NULL;
bool result = RenderThread::current()->Send(
@@ -1686,7 +1712,8 @@ WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
// The WebView holds a reference to this new RenderView
const WebPreferences& prefs = webview->GetPreferences();
RenderView* view = RenderView::Create(NULL, modal_dialog_event, routing_id_,
- prefs, routing_id);
+ prefs, shared_popup_counter_,
+ routing_id);
view->set_opened_by_user_gesture(user_gesture);
// Copy over the alternate error page URL so we can have alt error pages in
@@ -2595,6 +2622,13 @@ void RenderView::OnMessageFromExternalHost(
main_frame->LoadRequest(request.get());
}
+void RenderView::OnDisassociateFromPopupCount() {
+ if (decrement_shared_popup_at_destruction_)
+ shared_popup_counter_->data--;
+ shared_popup_counter_ = new SharedRenderViewCounter(0);
+ decrement_shared_popup_at_destruction_ = false;
+}
+
std::string RenderView::GetAltHTMLForTemplate(
const DictionaryValue& error_strings, int template_resource_id) const {
const StringPiece template_html(
@@ -2609,4 +2643,3 @@ std::string RenderView::GetAltHTMLForTemplate(
return jstemplate_builder::GetTemplateHtml(
template_html, &error_strings, "t");
}
-
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index d307e48..cba9df9 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -51,6 +51,20 @@ namespace webkit_glue {
struct FileUploadData;
}
+// We need to prevent a page from trying to create infinite popups. It is not
+// as simple as keeping a count of the number of immediate children
+// popups. Having an html file that window.open()s itself would create
+// an unlimited chain of RenderViews who only have one RenderView child.
+//
+// Therefore, each new top level RenderView creates a new counter and shares it
+// with all its children and grandchildren popup RenderViews created with
+// CreateWebView() to have a sort of global limit for the page so no more than
+// kMaximumNumberOfPopups popups are created.
+//
+// This is a RefCounted holder of an int because I can't say
+// scoped_refptr<int>.
+typedef base::RefCountedData<int> SharedRenderViewCounter;
+
//
// RenderView is an object that manages a WebView object, and provides a
// communication interface with an embedding application process
@@ -64,12 +78,15 @@ class RenderView : public RenderWidget, public WebViewDelegate,
// the renderer and plugin processes know to pump window messages. If this
// is a constrained popup or as a new tab, opener_id is the routing ID of the
// RenderView responsible for creating this RenderView (corresponding to the
- // parent_hwnd).
- static RenderView* Create(HWND parent_hwnd,
- HANDLE modal_dialog_event,
- int32 opener_id,
- const WebPreferences& webkit_prefs,
- int32 routing_id);
+ // parent_hwnd). |counter| is either a currently initialized counter, or NULL
+ // (in which case we treat this RenderView as a top level window).
+ static RenderView* Create(
+ HWND parent_hwnd,
+ HANDLE modal_dialog_event,
+ int32 opener_id,
+ const WebPreferences& webkit_prefs,
+ SharedRenderViewCounter* counter,
+ int32 routing_id);
// Sets the "next page id" counter.
static void SetNextPageID(int32 next_page_id);
@@ -293,6 +310,7 @@ class RenderView : public RenderWidget, public WebViewDelegate,
HANDLE modal_dialog_event,
int32 opener_id,
const WebPreferences& webkit_prefs,
+ SharedRenderViewCounter* counter,
int32 routing_id);
void UpdateURL(WebFrame* frame);
@@ -443,6 +461,10 @@ class RenderView : public RenderWidget, public WebViewDelegate,
void OnMessageFromExternalHost(const std::string& target,
const std::string& message);
+ // Message that we should no longer be part of the current popup window
+ // grouping, and should form our own grouping.
+ void OnDisassociateFromPopupCount();
+
// Switches the frame's CSS media type to "print" and calculate the number of
// printed pages that are to be expected. |frame| will be used to calculate
// the number of expected pages for this frame only.
@@ -619,6 +641,16 @@ class RenderView : public RenderWidget, public WebViewDelegate,
// True if the page has any frame-level unload or beforeunload listeners.
bool has_unload_listener_;
+ // The total number of unrequested popups that exist and can be followed back
+ // to a common opener. This count is shared among all RenderViews created
+ // with CreateWebView(). All popups are treated as unrequested until
+ // specifically instructed otherwise by the Browser process.
+ scoped_refptr<SharedRenderViewCounter> shared_popup_counter_;
+
+ // Whether this is a top level window (instead of a popup). Top level windows
+ // shouldn't count against their own |shared_popup_counter_|.
+ bool decrement_shared_popup_at_destruction_;
+
// Handles accessibility requests into the renderer side, as well as
// maintains the cache and other features of the accessibility tree.
scoped_ptr<GlueAccessibility> glue_accessibility_;