diff options
Diffstat (limited to 'chrome/browser/tab_contents')
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_delegate_helper.cc | 192 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_delegate_helper.h | 47 |
2 files changed, 187 insertions, 52 deletions
diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc index 451e7b9..b4301a3 100644 --- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc +++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc @@ -4,24 +4,32 @@ #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/background/background_contents_service.h" +#include "chrome/browser/background/background_contents_service_factory.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/process_map.h" +#include "chrome/browser/prerender/prerender_manager.h" +#include "chrome/browser/prerender/prerender_manager_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/tab_contents/background_contents.h" +#include "chrome/browser/tab_contents/retargeting_details.h" +#include "chrome/common/chrome_notification_types.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/renderer_host/render_widget_host.h" #include "content/browser/renderer_host/render_widget_host_view.h" +#include "content/browser/site_instance.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/browser/tab_contents/tab_contents_view.h" #include "content/common/view_messages.h" #include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" using content::WebContents; RenderViewHostDelegateViewHelper::RenderViewHostDelegateViewHelper() { - registrar_.Add(this, - content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, - content::NotificationService::AllBrowserContextsAndSources()); + registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, + content::NotificationService::AllSources()); } RenderViewHostDelegateViewHelper::~RenderViewHostDelegateViewHelper() {} @@ -41,47 +49,107 @@ void RenderViewHostDelegateViewHelper::Observe( } } -TabContents* RenderViewHostDelegateViewHelper::CreateNewWindow( - WebContents* web_contents, +BackgroundContents* +RenderViewHostDelegateViewHelper::MaybeCreateBackgroundContents( int route_id, - const ViewHostMsg_CreateWindow_Params& params) { - bool should_create = true; - if (web_contents->GetDelegate()) { - should_create = web_contents->GetDelegate()->ShouldCreateWebContents( - web_contents, + Profile* profile, + SiteInstance* site, + const GURL& opener_url, + const string16& frame_name) { + ExtensionService* extensions_service = profile->GetExtensionService(); + + if (!opener_url.is_valid() || + frame_name.empty() || + !extensions_service || + !extensions_service->is_ready()) + return NULL; + + // Only hosted apps have web extents, so this ensures that only hosted apps + // can create BackgroundContents. We don't have to check for background + // permission as that is checked in RenderMessageFilter when the CreateWindow + // message is processed. + const Extension* extension = + extensions_service->extensions()->GetHostedAppByURL( + ExtensionURLInfo(opener_url)); + if (!extension) + return NULL; + + // No BackgroundContents allowed if BackgroundContentsService doesn't exist. + BackgroundContentsService* service = + BackgroundContentsServiceFactory::GetForProfile(profile); + if (!service) + return NULL; + + // Ensure that we're trying to open this from the extension's process. + extensions::ProcessMap* process_map = extensions_service->process_map(); + if (!site->GetProcess() || + !process_map->Contains(extension->id(), site->GetProcess()->GetID())) { + return NULL; + } + + // Only allow a single background contents per app. If one already exists, + // close it (even if it was specified in the manifest). + BackgroundContents* existing = + service->GetAppBackgroundContents(ASCIIToUTF16(extension->id())); + if (existing) { + DLOG(INFO) << "Closing existing BackgroundContents for " << opener_url; + delete existing; + } + + // Passed all the checks, so this should be created as a BackgroundContents. + return service->CreateBackgroundContents(site, route_id, profile, frame_name, + ASCIIToUTF16(extension->id())); +} + +TabContents* RenderViewHostDelegateViewHelper::CreateNewWindowImpl( + int route_id, + Profile* profile, + SiteInstance* site, + WebUI::TypeID webui_type, + RenderViewHostDelegate* opener, + WindowContainerType window_container_type, + const string16& frame_name) { + if (window_container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) { + BackgroundContents* contents = MaybeCreateBackgroundContents( route_id, - params.window_container_type, - params.frame_name); + profile, + site, + opener->GetURL(), + frame_name); + if (contents) { + pending_contents_[route_id] = + contents->web_contents()->GetRenderViewHost(); + return NULL; + } } - if (!should_create) + TabContents* base_tab_contents = opener->GetAsTabContents(); + + // Do not create the new TabContents if the opener is a prerender TabContents. + prerender::PrerenderManager* prerender_manager = + prerender::PrerenderManagerFactory::GetForProfile(profile); + if (prerender_manager && + prerender_manager->IsWebContentsPrerendering(base_tab_contents)) { return NULL; + } // Create the new web contents. This will automatically create the new // TabContentsView. In the future, we may want to create the view separately. TabContents* new_contents = - new TabContents(web_contents->GetBrowserContext(), - web_contents->GetSiteInstance(), + new TabContents(profile, + site, route_id, - static_cast<TabContents*>(web_contents), + base_tab_contents, NULL); - new_contents->set_opener_web_ui_type( - web_contents->GetWebUITypeForCurrentState()); + new_contents->set_opener_web_ui_type(webui_type); TabContentsView* new_view = new_contents->GetView(); - // TODO(brettw): It seems bogus that we have to call this function on the + // TODO(brettw) it seems bogus that we have to call this function on the // newly created object and give it one of its own member variables. new_view->CreateViewForWidget(new_contents->GetRenderViewHost()); // Save the created window associated with the route so we can show it later. - pending_contents_[route_id] = new_contents; - - if (web_contents->GetDelegate()) - web_contents->GetDelegate()->WebContentsCreated(web_contents, - params.opener_frame_id, - params.target_url, - new_contents); - + pending_contents_[route_id] = new_contents->GetRenderViewHost(); return new_contents; } @@ -91,7 +159,8 @@ RenderWidgetHostView* RenderViewHostDelegateViewHelper::CreateNewWidget( bool is_fullscreen, WebKit::WebPopupType popup_type) { content::RenderProcessHost* process = web_contents->GetRenderProcessHost(); - RenderWidgetHost* widget_host = new RenderWidgetHost(process, route_id); + RenderWidgetHost* widget_host = + new RenderWidgetHost(process, route_id); RenderWidgetHostView* widget_view = RenderWidgetHostView::CreateViewForWidget(widget_host); if (!is_fullscreen) { @@ -112,16 +181,17 @@ TabContents* RenderViewHostDelegateViewHelper::GetCreatedWindow(int route_id) { return NULL; } - TabContents* new_contents = iter->second; + RenderViewHost* new_rvh = iter->second; pending_contents_.erase(route_id); - if (!new_contents->GetRenderProcessHost()->HasConnection() || - !new_contents->GetRenderViewHost()->view()) + // The renderer crashed or it is a TabContents and has no view. + if (!new_rvh->process()->HasConnection() || + (new_rvh->delegate()->GetAsTabContents() && !new_rvh->view())) return NULL; - // TODO(brettw): It seems bogus to reach into here and initialize the host. - new_contents->GetRenderViewHost()->Init(); - return new_contents; + // TODO(brettw) this seems bogus to reach into here and initialize the host. + new_rvh->Init(); + return new_rvh->delegate()->GetAsTabContents(); } RenderWidgetHostView* RenderViewHostDelegateViewHelper::GetCreatedWidget( @@ -144,20 +214,56 @@ RenderWidgetHostView* RenderViewHostDelegateViewHelper::GetCreatedWidget( return widget_host_view; } +TabContents* RenderViewHostDelegateViewHelper::CreateNewWindow( + WebContents* web_contents, + int route_id, + const ViewHostMsg_CreateWindow_Params& params) { + TabContents* new_contents = CreateNewWindowImpl( + route_id, + Profile::FromBrowserContext(web_contents->GetBrowserContext()), + web_contents->GetSiteInstance(), + web_contents->GetWebUITypeForCurrentState(), + static_cast<TabContents*>(web_contents), + params.window_container_type, + params.frame_name); + + if (new_contents) { + if (web_contents->GetDelegate()) + web_contents->GetDelegate()->WebContentsCreated(new_contents); + + RetargetingDetails details; + details.source_web_contents = web_contents; + details.source_frame_id = params.opener_frame_id; + details.target_url = params.target_url; + details.target_web_contents = new_contents; + details.not_yet_in_tabstrip = true; + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_RETARGETING, + content::Source<Profile>( + Profile::FromBrowserContext(web_contents->GetBrowserContext())), + content::Details<RetargetingDetails>(&details)); + } else { + content::NotificationService::current()->Notify( + content::NOTIFICATION_CREATING_NEW_WINDOW_CANCELLED, + content::Source<WebContents>(web_contents), + content::Details<const ViewHostMsg_CreateWindow_Params>(¶ms)); + } + + return new_contents; +} + TabContents* RenderViewHostDelegateViewHelper::ShowCreatedWindow( WebContents* web_contents, int route_id, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture) { - TabContents* contents = GetCreatedWindow(route_id); + WebContents* contents = GetCreatedWindow(route_id); if (contents) { - web_contents->AddNewContents(contents, - disposition, - initial_pos, - user_gesture); + web_contents->AddNewContents( + contents, disposition, initial_pos, user_gesture); } - return contents; + return static_cast<TabContents*>(contents); } RenderWidgetHostView* RenderViewHostDelegateViewHelper::ShowCreatedWidget( diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.h b/chrome/browser/tab_contents/render_view_host_delegate_helper.h index 1d38de4..7959e0f 100644 --- a/chrome/browser/tab_contents/render_view_host_delegate_helper.h +++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.h @@ -7,19 +7,30 @@ #pragma once #include <map> +#include <string> #include "base/basictypes.h" -#include "base/compiler_specific.h" +#include "content/browser/webui/web_ui.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "content/public/common/window_container_type.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h" +#include "webkit/glue/webpreferences.h" #include "webkit/glue/window_open_disposition.h" +class BackgroundContents; +class Profile; +class RenderViewHost; +class RenderViewHostDelegate; +class RenderWidgetHost; class RenderWidgetHostView; +class SiteInstance; class TabContents; struct ViewHostMsg_CreateWindow_Params; namespace content { +class BrowserContext; +class RenderProcessHost; class WebContents; } @@ -27,10 +38,6 @@ namespace gfx { class Rect; } -// TODO(avi): Once all the TabContentsViews implementations are in content (I'm -// looking at you, TabContentsViewViews...) then change the parameters to take -// WebContentsImpl rather than WebContents. - // Provides helper methods that provide common implementations of some // TabContentsView methods. class RenderViewHostDelegateViewHelper : public content::NotificationObserver { @@ -71,18 +78,40 @@ class RenderViewHostDelegateViewHelper : public content::NotificationObserver { const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; + // Creates a new renderer for window.open. This will either be a + // BackgroundContents (if the window_container_type == + // WINDOW_CONTAINER_TYPE_BACKGROUND and permissions allow) or a TabContents. + // If a TabContents is created, it is returned. Otherwise NULL is returned. + TabContents* CreateNewWindowImpl( + int route_id, + Profile* profile, + SiteInstance* site, + WebUI::TypeID webui_type, + RenderViewHostDelegate* opener, + WindowContainerType window_container_type, + const string16& frame_name); + + BackgroundContents* MaybeCreateBackgroundContents( + int route_id, + Profile* profile, + SiteInstance* site, + const GURL& opener_url, + const string16& frame_name); + // Finds the new RenderWidgetHost and returns it. Note that this can only be // called once as this call also removes it from the internal map. RenderWidgetHostView* GetCreatedWidget(int route_id); - // Finds the new TabContents by route_id, initializes it for - // renderer-initiated creation, and returns it. Note that this can only be - // called once as this call also removes it from the internal map. + // Finds the new RenderViewHost/Delegate by route_id, initializes it for + // for renderer-initiated creation, and returns the TabContents that needs + // to be shown, if there is one (i.e. not a BackgroundContents). Note that + // this can only be called once as this call also removes it from the internal + // map. TabContents* GetCreatedWindow(int route_id); // Tracks created RenderViewHost objects that have not been shown yet. // They are identified by the route ID passed to CreateNewWindow. - typedef std::map<int, TabContents*> PendingContents; + typedef std::map<int, RenderViewHost*> PendingContents; PendingContents pending_contents_; // These maps hold on to the widgets that we created on behalf of the |