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/background_contents.cc192
-rw-r--r--chrome/browser/tab_contents/background_contents.h126
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.cc58
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.h35
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc2
-rw-r--r--chrome/browser/tab_contents/tab_contents_view.cc5
6 files changed, 399 insertions, 19 deletions
diff --git a/chrome/browser/tab_contents/background_contents.cc b/chrome/browser/tab_contents/background_contents.cc
new file mode 100644
index 0000000..c61802d
--- /dev/null
+++ b/chrome/browser/tab_contents/background_contents.cc
@@ -0,0 +1,192 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/tab_contents/background_contents.h"
+
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browsing_instance.h"
+#include "chrome/browser/in_process_webkit/dom_storage_context.h"
+#include "chrome/browser/in_process_webkit/webkit_context.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/renderer_preferences_util.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/view_types.h"
+#include "chrome/common/render_messages.h"
+
+
+////////////////
+// BackgroundContents
+
+BackgroundContents::BackgroundContents(SiteInstance* site_instance,
+ int routing_id) {
+ Profile* profile = site_instance->browsing_instance()->profile();
+
+ // TODO(rafaelw): Implement correct session storage.
+ int64 session_storage_namespace_id = profile->GetWebKitContext()->
+ dom_storage_context()->AllocateSessionStorageNamespaceId();
+ render_view_host_ = new RenderViewHost(site_instance, this, routing_id,
+ session_storage_namespace_id);
+ render_view_host_->AllowScriptToClose(true);
+
+#if defined(OS_WIN) || defined(OS_LINUX)
+ registrar_.Add(this, NotificationType::BROWSER_CLOSED,
+ NotificationService::AllSources());
+#elif defined(OS_MACOSX)
+ registrar_.Add(this, NotificationType::APP_TERMINATING,
+ NotificationService::AllSources());
+#endif
+}
+
+void BackgroundContents::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ // TODO(rafaelw): Implement pagegroup ref-counting so that non-persistent
+ // background pages are closed when the last referencing frame is closed.
+ switch (type.value) {
+#if defined(OS_WIN) || defined(OS_LINUX)
+ case NotificationType::BROWSER_CLOSED: {
+ bool app_closing = *Details<bool>(details).ptr();
+ if (app_closing)
+ delete this;
+ break;
+ }
+#elif defined(OS_MACOSX)
+ case NotificationType::APP_TERMINATING: {
+ delete this;
+ break;
+ }
+#endif
+ default:
+ NOTREACHED() << "Unexpected notification sent.";
+ break;
+ }
+}
+
+BackgroundContents::~BackgroundContents() {
+ NotificationService::current()->Notify(
+ NotificationType::BACKGROUND_CONTENTS_DELETED,
+ Source<BackgroundContents>(this),
+ Details<RenderViewHost>(render_view_host_));
+ render_view_host_->Shutdown(); // deletes render_view_host
+}
+
+void BackgroundContents::DidNavigate(
+ RenderViewHost* render_view_host,
+ const ViewHostMsg_FrameNavigate_Params& params) {
+ // We only care when the outer frame changes.
+ if (!PageTransition::IsMainFrame(params.transition))
+ return;
+
+ // Note: because BackgroundContents are only available to extension apps,
+ // navigation is limited to urls within the app's extent. This is enforced in
+ // RenderView::decidePolicyForNaviation. If BackgroundContents become
+ // available as a part of the web platform, it probably makes sense to have
+ // some way to scope navigation of a background page to its opener's security
+ // origin. Note: if the first navigation is to a URL outside the app's
+ // extent a background page will be opened but will remain at about:blank.
+ url_ = params.url;
+
+ NotificationService::current()->Notify(
+ NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
+ Source<BackgroundContents>(this),
+ Details<RenderViewHost>(render_view_host_));
+}
+
+void BackgroundContents::RunJavaScriptMessage(
+ const std::wstring& message,
+ const std::wstring& default_prompt,
+ const GURL& frame_url,
+ const int flags,
+ IPC::Message* reply_msg,
+ bool* did_suppress_message) {
+ // TODO(rafaelw): Implement, The JavaScriptModalDialog needs to learn about
+ // BackgroundContents.
+ *did_suppress_message = true;
+}
+
+std::wstring BackgroundContents::GetMessageBoxTitle(const GURL& frame_url,
+ bool is_alert) {
+ NOTIMPLEMENTED();
+ return L"";
+}
+
+gfx::NativeWindow BackgroundContents::GetMessageBoxRootWindow() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void BackgroundContents::OnMessageBoxClosed(IPC::Message* reply_msg,
+ bool success,
+ const std::wstring& prompt) {
+ render_view_host_->JavaScriptMessageBoxClosed(reply_msg, success, prompt);
+}
+
+void BackgroundContents::Close(RenderViewHost* render_view_host) {
+ delete this;
+}
+
+RendererPreferences BackgroundContents::GetRendererPrefs(
+ Profile* profile) const {
+ RendererPreferences preferences;
+ renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile);
+ return preferences;
+}
+
+WebPreferences BackgroundContents::GetWebkitPrefs() {
+ // TODO(rafaelw): Consider enabling the webkit_prefs.dom_paste_enabled for
+ // apps.
+ Profile* profile = render_view_host_->process()->profile();
+ return RenderViewHostDelegateHelper::GetWebkitPrefs(profile,
+ false); // is_dom_ui
+}
+
+void BackgroundContents::ProcessDOMUIMessage(const std::string& message,
+ const Value* content,
+ const GURL& source_url,
+ int request_id,
+ bool has_callback) {
+ // TODO(rafaelw): It may make sense for extensions to be able to open
+ // BackgroundContents to chrome-extension://<id> pages. Consider implementing.
+ render_view_host_->BlockExtensionRequest(request_id);
+}
+
+void BackgroundContents::CreateNewWindow(
+ int route_id,
+ WindowContainerType window_container_type) {
+ delegate_view_helper_.CreateNewWindow(route_id,
+ render_view_host_->process()->profile(),
+ render_view_host_->site_instance(),
+ DOMUIFactory::GetDOMUIType(url_),
+ this,
+ window_container_type);
+}
+
+void BackgroundContents::CreateNewWidget(int route_id,
+ WebKit::WebPopupType popup_type) {
+ NOTREACHED();
+}
+
+void BackgroundContents::ShowCreatedWindow(int route_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) {
+ TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id);
+ if (!contents)
+ return;
+ Browser* browser = BrowserList::GetLastActiveWithProfile(
+ render_view_host_->process()->profile());
+ if (!browser)
+ return;
+
+ browser->AddTabContents(contents, disposition, initial_pos, user_gesture);
+}
+
+void BackgroundContents::ShowCreatedWidget(int route_id,
+ const gfx::Rect& initial_pos) {
+ NOTIMPLEMENTED();
+}
+
diff --git a/chrome/browser/tab_contents/background_contents.h b/chrome/browser/tab_contents/background_contents.h
new file mode 100644
index 0000000..348b28a
--- /dev/null
+++ b/chrome/browser/tab_contents/background_contents.h
@@ -0,0 +1,126 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TAB_CONTENTS_BACKGROUND_CONTENTS_H_
+#define CHROME_BROWSER_TAB_CONTENTS_BACKGROUND_CONTENTS_H_
+
+#include <string>
+
+#include "chrome/browser/jsmessage_box_client.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/view_types.h"
+#include "chrome/common/window_container_type.h"
+
+class RenderWidgetHost;
+class RenderWidgetHostView;
+class TabContents;
+struct WebPreferences;
+
+// This class is a peer of TabContents. It can host a renderer, but does not
+// have any visible display. Its navigation is not managed by a
+// NavigationController because is has no facility for navigating (other than
+// programatically view window.location.href) or RenderViewHostManager because
+// it is never allowed to navigate across a SiteInstance boundary.
+class BackgroundContents : public RenderViewHostDelegate,
+ public RenderViewHostDelegate::View,
+ public NotificationObserver,
+ public JavaScriptMessageBoxClient {
+ public:
+ BackgroundContents(SiteInstance* site_instance,
+ int routing_id);
+ ~BackgroundContents();
+
+ // Provide access to the RenderViewHost for the
+ // RenderViewHostDelegateViewHelper
+ RenderViewHost* render_view_host() { return render_view_host_; }
+
+ // RenderViewHostDelegate implementation.
+ virtual RenderViewHostDelegate::View* GetViewDelegate() { return this; }
+ virtual const GURL& GetURL() const { return url_; }
+ virtual ViewType::Type GetRenderViewType() const {
+ return ViewType::BACKGROUND_CONTENTS;
+ }
+ virtual int GetBrowserWindowID() const {
+ return extension_misc::kUnknownWindowId;
+ }
+ virtual void DidNavigate(RenderViewHost* render_view_host,
+ const ViewHostMsg_FrameNavigate_Params& params);
+ virtual WebPreferences GetWebkitPrefs();
+ virtual void ProcessDOMUIMessage(const std::string& message,
+ const Value* content,
+ const GURL& source_url,
+ int request_id,
+ bool has_callback);
+ virtual void RunJavaScriptMessage(const std::wstring& message,
+ const std::wstring& default_prompt,
+ const GURL& frame_url,
+ const int flags,
+ IPC::Message* reply_msg,
+ bool* did_suppress_message);
+ virtual void Close(RenderViewHost* render_view_host);
+ virtual RendererPreferences GetRendererPrefs(Profile* profile) const;
+
+ // RenderViewHostDelegate::View
+ virtual void CreateNewWindow(
+ int route_id,
+ WindowContainerType window_container_type);
+ virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type);
+ virtual void ShowCreatedWindow(int route_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture);
+ virtual void ShowCreatedWidget(int route_id,
+ const gfx::Rect& initial_pos);
+ virtual void ShowContextMenu(const ContextMenuParams& params) {}
+ virtual void StartDragging(const WebDropData& drop_data,
+ WebKit::WebDragOperationsMask allowed_operations,
+ const SkBitmap& image,
+ const gfx::Point& image_offset) {}
+ virtual void UpdateDragCursor(WebKit::WebDragOperation operation) {}
+ virtual void GotFocus() {}
+ virtual void TakeFocus(bool reverse) {}
+ virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) {
+ return false;
+ }
+ virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {}
+ virtual void HandleMouseEvent() {}
+ virtual void HandleMouseLeave() {}
+ virtual void UpdatePreferredSize(const gfx::Size& new_size) {}
+
+ // NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // JavaScriptMessageBoxClient
+ virtual std::wstring GetMessageBoxTitle(const GURL& frame_url,
+ bool is_alert);
+ virtual gfx::NativeWindow GetMessageBoxRootWindow();
+ virtual void OnMessageBoxClosed(IPC::Message* reply_msg,
+ bool success,
+ const std::wstring& prompt);
+ virtual void SetSuppressMessageBoxes(bool suppress_message_boxes) {}
+ virtual TabContents* AsTabContents() { return NULL; }
+ virtual ExtensionHost* AsExtensionHost() { return NULL; }
+
+ private:
+ // The host for our HTML content.
+ RenderViewHost* render_view_host_;
+
+ // Common implementations of some RenderViewHostDelegate::View methods.
+ RenderViewHostDelegateViewHelper delegate_view_helper_;
+
+ // The URL being hosted.
+ GURL url_;
+
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundContents);
+};
+
+#endif // CHROME_BROWSER_TAB_CONTENTS_BACKGROUND_CONTENTS_H_
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 5fe2208..a1f7f01 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
@@ -8,6 +8,7 @@
#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/character_encoding.h"
+#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_view_host.h"
@@ -15,26 +16,63 @@
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/renderer_host/site_instance.h"
+#include "chrome/browser/tab_contents/background_contents.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/user_style_sheet_watcher.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+bool RenderViewHostDelegateViewHelper::ShouldOpenBackgroundContents(
+ WindowContainerType window_container_type,
+ GURL opener_url,
+ RenderProcessHost* opener_process,
+ Profile* profile) {
+ ExtensionsService* extensions_service = profile->GetExtensionsService();
+ if (window_container_type != WINDOW_CONTAINER_TYPE_BACKGROUND ||
+ !opener_url.is_valid() ||
+ !extensions_service ||
+ !extensions_service->is_ready())
+ return false;
+
+ Extension* extension = extensions_service->GetExtensionByURL(opener_url);
+ if (!extension)
+ extension = extensions_service->GetExtensionByWebExtent(opener_url);
+ if (!extension ||
+ !extension->HasApiPermission(Extension::kBackgroundPermission))
+ return false;
+
+ ExtensionProcessManager* process_manager =
+ profile->GetExtensionProcessManager();
+ if (!opener_process || !process_manager ||
+ opener_process != process_manager->GetExtensionProcess(opener_url))
+ return false;
+
+ return true;
+}
TabContents* RenderViewHostDelegateViewHelper::CreateNewWindow(
int route_id,
Profile* profile,
SiteInstance* site,
DOMUITypeID domui_type,
- TabContents* old_tab_contents,
+ RenderViewHostDelegate* opener,
WindowContainerType window_container_type) {
+ if (ShouldOpenBackgroundContents(window_container_type,
+ opener->GetURL(),
+ site->GetProcess(),
+ profile)) {
+ BackgroundContents* contents = new BackgroundContents(site, route_id);
+ pending_contents_[route_id] = contents->render_view_host();
+ 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(profile,
site,
route_id,
- old_tab_contents);
+ opener->GetAsTabContents());
new_contents->set_opener_dom_ui_type(domui_type);
TabContentsView* new_view = new_contents->view();
@@ -43,7 +81,7 @@ TabContents* RenderViewHostDelegateViewHelper::CreateNewWindow(
new_view->CreateViewForWidget(new_contents->render_view_host());
// Save the created window associated with the route so we can show it later.
- pending_contents_[route_id] = new_contents;
+ pending_contents_[route_id] = new_contents->render_view_host();
return new_contents;
}
@@ -67,19 +105,17 @@ TabContents* RenderViewHostDelegateViewHelper::GetCreatedWindow(int route_id) {
return NULL;
}
- TabContents* new_tab_contents = iter->second;
+ RenderViewHost* new_rvh = iter->second;
pending_contents_.erase(route_id);
- if (!new_tab_contents->render_view_host()->view() ||
- !new_tab_contents->GetRenderProcessHost()->HasConnection()) {
- // The view has gone away or the renderer crashed. Nothing to do.
+ // 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) this seems bogus to reach into here and initialize the host.
- new_tab_contents->render_view_host()->Init();
-
- return new_tab_contents;
+ new_rvh->Init();
+ return new_rvh->delegate()->GetAsTabContents();
}
RenderWidgetHostView* RenderViewHostDelegateViewHelper::GetCreatedWidget(
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 351e036..084762d 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.h
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.h
@@ -17,10 +17,12 @@
#include "webkit/glue/window_open_disposition.h"
class Browser;
+class ExtensionsService;
class PrefService;
class Profile;
class RenderProcessHost;
class RenderViewHost;
+class RenderViewHostDelegate;
class RenderWidgetHost;
class RenderWidgetHostView;
class SiteInstance;
@@ -32,24 +34,47 @@ class RenderViewHostDelegateViewHelper {
public:
RenderViewHostDelegateViewHelper() {}
+ // 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.
virtual TabContents* CreateNewWindow(
int route_id,
Profile* profile,
SiteInstance* site,
DOMUITypeID domui_type,
- TabContents* old_tab_contents,
+ RenderViewHostDelegate* opener,
WindowContainerType window_container_type);
+
+ // Creates a new RenderWidgetHost and saves it for later retrieval by
+ // GetCreatedWidget.
virtual RenderWidgetHostView* CreateNewWidget(int route_id,
WebKit::WebPopupType popup_type,
RenderProcessHost* process);
- virtual TabContents* GetCreatedWindow(int route_id);
+
+ // 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.
virtual RenderWidgetHostView* GetCreatedWidget(int route_id);
+
+ // 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.
+ virtual TabContents* GetCreatedWindow(int route_id);
+
+ // Removes |host| from the internal map of pending RenderWidgets.
void RenderWidgetHostDestroyed(RenderWidgetHost* host);
private:
- // Tracks created TabContents objects that have not been shown yet. They are
- // identified by the route ID passed to CreateNewWindow.
- typedef std::map<int, TabContents*> PendingContents;
+ bool ShouldOpenBackgroundContents(WindowContainerType window_container_type,
+ GURL opener_url,
+ RenderProcessHost* opener_process,
+ Profile* profile);
+
+ // Tracks created RenderViewHost objects that have not been shown yet.
+ // They are identified by the route ID passed to CreateNewWindow.
+ typedef std::map<int, RenderViewHost*> PendingContents;
PendingContents pending_contents_;
// These maps hold on to the widgets that we created on behalf of the
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 2f3e743..9d2fd42 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -946,7 +946,7 @@ void TabContents::PopupNotificationVisibilityChanged(bool visible) {
if (is_being_destroyed_)
return;
if (!dont_notify_render_view_)
- render_view_host()->PopupNotificationVisibilityChanged(visible);
+ render_view_host()->AllowScriptToClose(!visible);
if (delegate_)
delegate_->OnContentSettingsChange(this);
}
diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc
index 935b96d..0fb400e 100644
--- a/chrome/browser/tab_contents/tab_contents_view.cc
+++ b/chrome/browser/tab_contents/tab_contents_view.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
@@ -28,12 +29,12 @@ void TabContentsView::RenderViewCreated(RenderViewHost* host) {
void TabContentsView::CreateNewWindow(
int route_id,
WindowContainerType window_container_type) {
- TabContents* new_contents = delegate_view_helper_.CreateNewWindow(
+ TabContents* new_contents = delegate_view_helper_.CreateNewWindow(
route_id, tab_contents_->profile(), tab_contents_->GetSiteInstance(),
DOMUIFactory::GetDOMUIType(tab_contents_->GetURL()), tab_contents_,
window_container_type);
- if (tab_contents_->delegate())
+ if (new_contents && tab_contents_->delegate())
tab_contents_->delegate()->TabContentsCreated(new_contents);
}