summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tab_contents
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/tab_contents')
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.cc192
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.h47
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>(&params));
+ }
+
+ 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