diff options
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/render_thread.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 47 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 44 |
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_; |