diff options
23 files changed, 494 insertions, 73 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index e62f6bb..3921aa6 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -21,6 +21,7 @@ #include "chrome/browser/dom_ui/dom_ui_factory.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_tabs_module.h" +#include "chrome/browser/extensions/extension_tabs_module_constants.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/in_process_webkit/dom_storage_context.h" #include "chrome/browser/in_process_webkit/webkit_context.h" @@ -38,6 +39,7 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/common/bindings_policy.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/view_types.h" @@ -298,11 +300,8 @@ void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) { void ExtensionHost::DidNavigate(RenderViewHost* render_view_host, const ViewHostMsg_FrameNavigate_Params& params) { // We only care when the outer frame changes. - switch (params.transition) { - case PageTransition::AUTO_SUBFRAME: - case PageTransition::MANUAL_SUBFRAME: - return; - } + if (!PageTransition::IsMainFrame(params.transition)) + return; if (!params.url.SchemeIs(chrome::kExtensionScheme)) { extension_function_dispatcher_.reset(NULL); @@ -516,9 +515,14 @@ RendererPreferences ExtensionHost::GetRendererPrefs(Profile* profile) const { WebPreferences ExtensionHost::GetWebkitPrefs() { Profile* profile = render_view_host()->process()->profile(); - const bool kIsDomUI = true; WebPreferences webkit_prefs = - RenderViewHostDelegateHelper::GetWebkitPrefs(profile, kIsDomUI); + RenderViewHostDelegateHelper::GetWebkitPrefs(profile, + false); // is_dom_ui + // Extensions are trusted so we override any user preferences for disabling + // javascript or images. + webkit_prefs.loads_images_automatically = true; + webkit_prefs.javascript_enabled = true; + if (extension_host_type_ == ViewType::EXTENSION_POPUP || extension_host_type_ == ViewType::EXTENSION_INFOBAR) webkit_prefs.allow_scripts_to_close_windows = true; @@ -551,8 +555,11 @@ void ExtensionHost::CreateNewWindow( int route_id, WindowContainerType window_container_type) { delegate_view_helper_.CreateNewWindow( - route_id, render_view_host()->process()->profile(), - site_instance(), DOMUIFactory::GetDOMUIType(url_), NULL, + route_id, + render_view_host()->process()->profile(), + site_instance(), + DOMUIFactory::GetDOMUIType(url_), + this, window_container_type); } @@ -580,10 +587,7 @@ void ExtensionHost::ShowCreatedWindow(int route_id, if (!browser) return; - // TODO(aa): It seems like this means popup windows don't work via - // window.open() from ExtensionHost? - browser->AddTabContents(contents, disposition, initial_pos, - user_gesture); + browser->AddTabContents(contents, disposition, initial_pos, user_gesture); } void ExtensionHost::ShowCreatedWidget(int route_id, @@ -713,7 +717,7 @@ void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { int ExtensionHost::GetBrowserWindowID() const { // Hosts not attached to any browser window have an id of -1. This includes // those mentioned below, and background pages. - int window_id = -1; + int window_id = extension_misc::kUnknownWindowId; if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || extension_host_type_ == ViewType::EXTENSION_MOLE || extension_host_type_ == ViewType::EXTENSION_POPUP || diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index ffaaf75..c06e931 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -289,15 +289,13 @@ void ExtensionProcessManager::Observe(NotificationType type, // Close background hosts when the last browser is closed so that they // have time to shutdown various objects on different threads. Our // destructor is called too late in the shutdown sequence. - bool app_closing_non_mac = *Details<bool>(details).ptr(); - if (app_closing_non_mac) + bool app_closing = *Details<bool>(details).ptr(); + if (app_closing) CloseBackgroundHosts(); break; } #elif defined(OS_MACOSX) case NotificationType::APP_TERMINATING: { - // Don't follow the behavior of having the last browser window closed - // being an indication that the app should close. CloseBackgroundHosts(); break; } diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index 32b4976..fda3849 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -374,10 +374,16 @@ void ExtensionsDOMHandler::OnIconsLoaded(DictionaryValue* json) { NotificationService::AllSources()); registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, - NotificationService::AllSources()); + NotificationService::AllSources()); registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED, - NotificationService::AllSources()); + NotificationService::AllSources()); + registrar_.Add(this, + NotificationType::BACKGROUND_CONTENTS_NAVIGATED, + NotificationService::AllSources()); + registrar_.Add(this, + NotificationType::BACKGROUND_CONTENTS_DELETED, + NotificationService::AllSources()); } ExtensionResource ExtensionsDOMHandler::PickExtensionIcon( @@ -692,7 +698,8 @@ void ExtensionsDOMHandler::Observe(NotificationType type, // // Doing it this way gets everything but causes the page to be rendered // more than we need. It doesn't seem to result in any noticeable flicker. - case NotificationType::RENDER_VIEW_HOST_DELETED: + case NotificationType::RENDER_VIEW_HOST_DELETED: + case NotificationType::BACKGROUND_CONTENTS_DELETED: deleting_rvh_ = Details<RenderViewHost>(details).ptr(); case NotificationType::EXTENSION_LOADED: case NotificationType::EXTENSION_PROCESS_CREATED: @@ -702,11 +709,12 @@ void ExtensionsDOMHandler::Observe(NotificationType type, case NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED: case NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED: case NotificationType::NAV_ENTRY_COMMITTED: + case NotificationType::BACKGROUND_CONTENTS_NAVIGATED: if (!ignore_notifications_ && dom_ui_->tab_contents()) HandleRequestExtensionsData(NULL); - deleting_rvh_ = NULL; + deleting_rvh_ = NULL; break; - + default: NOTREACHED(); } @@ -840,7 +848,7 @@ std::vector<ExtensionPage> ExtensionsDOMHandler::GetActivePagesForExtension( if (host == deleting_rvh_ || ViewType::EXTENSION_POPUP == host->delegate()->GetRenderViewType()) continue; - + GURL url = host->delegate()->GetURL(); if (url.SchemeIs(chrome::kExtensionScheme)) { if (url.host() != extension->id()) diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc index da819b0..9ac6455 100644 --- a/chrome/browser/notifications/balloon_host.cc +++ b/chrome/browser/notifications/balloon_host.cc @@ -88,8 +88,11 @@ void BalloonHost::CreateNewWindow( int route_id, WindowContainerType window_container_type) { delegate_view_helper_.CreateNewWindow( - route_id, balloon_->profile(), site_instance_.get(), - DOMUIFactory::GetDOMUIType(balloon_->notification().content_url()), NULL, + route_id, + balloon_->profile(), + site_instance_.get(), + DOMUIFactory::GetDOMUIType(balloon_->notification().content_url()), + this, window_container_type); } @@ -102,10 +105,13 @@ void BalloonHost::ShowCreatedWindow(int route_id, return; TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id); - if (contents) { - Browser* browser = BrowserList::GetLastActive(); - browser->AddTabContents(contents, disposition, initial_pos, user_gesture); - } + if (!contents) + return; + Browser* browser = BrowserList::GetLastActiveWithProfile(balloon_->profile()); + if (!browser) + return; + + browser->AddTabContents(contents, disposition, initial_pos, user_gesture); } void BalloonHost::UpdatePreferredSize(const gfx::Size& new_size) { diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h index 4aabe39..4e7a77c 100644 --- a/chrome/browser/notifications/balloon_host.h +++ b/chrome/browser/notifications/balloon_host.h @@ -13,6 +13,7 @@ #include "chrome/browser/renderer_host/render_view_host_delegate.h" #include "chrome/browser/renderer_host/site_instance.h" #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" +#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/renderer_preferences.h" #include "webkit/glue/webpreferences.h" @@ -63,7 +64,9 @@ class BalloonHost : public RenderViewHostDelegate, virtual void RenderViewGone(RenderViewHost* render_view_host); virtual void UpdateTitle(RenderViewHost* render_view_host, int32 page_id, const std::wstring& title) {} - virtual int GetBrowserWindowID() const { return -1; } + virtual int GetBrowserWindowID() const { + return extension_misc::kUnknownWindowId; + } virtual ViewType::Type GetRenderViewType() const { return ViewType::NOTIFICATION; } diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index c592b81..2dc570e 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1263,8 +1263,8 @@ void RenderViewHost::DisassociateFromPopupCount() { Send(new ViewMsg_DisassociateFromPopupCount(routing_id())); } -void RenderViewHost::PopupNotificationVisibilityChanged(bool visible) { - Send(new ViewMsg_PopupNotificationVisibilityChanged(routing_id(), visible)); +void RenderViewHost::AllowScriptToClose(bool script_can_close) { + Send(new ViewMsg_AllowScriptToClose(routing_id(), script_can_close)); } void RenderViewHost::OnMsgGoToEntryAtOffset(int offset) { diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 84dec34..0fffedd 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -376,9 +376,9 @@ class RenderViewHost : public RenderWidgetHost { // as a popup. void DisassociateFromPopupCount(); - // Notifies the Renderer that we've either displayed or hidden the popup - // notification. - void PopupNotificationVisibilityChanged(bool visible); + // Tells the renderer whether it should allow window.close. This is initially + // set to false when creating a renderer-initiated window via window.open. + void AllowScriptToClose(bool visible); // Called by the AutoFillManager when the list of suggestions is ready. void AutoFillSuggestionsReturned( 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); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 892a048..c8a0c66 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2072,6 +2072,8 @@ 'browser/sync/sync_ui_util.h', 'browser/sync/sync_ui_util_mac.mm', 'browser/sync/sync_ui_util_mac.h', + 'browser/tab_contents/background_contents.cc', + 'browser/tab_contents/background_contents.h', 'browser/tab_contents/constrained_window.h', 'browser/tab_contents/infobar_delegate.cc', 'browser/tab_contents/infobar_delegate.h', diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 4c82ad1..fad9130 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -119,6 +119,7 @@ const int Extension::kIconSizes[] = { const int Extension::kPageActionIconMaxSize = 19; const int Extension::kBrowserActionIconMaxSize = 19; +const char* Extension::kBackgroundPermission = "background"; const char* Extension::kBookmarkPermission = "bookmarks"; const char* Extension::kExperimentalPermission = "experimental"; const char* Extension::kGeolocationPermission = "geolocation"; @@ -128,6 +129,7 @@ const char* Extension::kTabPermission = "tabs"; const char* Extension::kUnlimitedStoragePermission = "unlimited_storage"; const char* Extension::kPermissionNames[] = { + Extension::kBackgroundPermission, Extension::kBookmarkPermission, Extension::kExperimentalPermission, Extension::kGeolocationPermission, diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index 7a1fe93..be015d2 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -87,6 +87,7 @@ class Extension { static const int kBrowserActionIconMaxSize; // Each permission is a module that the extension is permitted to use. + static const char* kBackgroundPermission; static const char* kBookmarkPermission; static const char* kExperimentalPermission; static const char* kGeolocationPermission; diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index 36ba762..2353b35 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h @@ -188,4 +188,8 @@ namespace extension_filenames { extern const char* kDecodedMessageCatalogsFilename; } +namespace extension_misc { + const int kUnknownWindowId = -1; +} // extension_misc + #endif // CHROME_COMMON_EXTENSIONS_EXTENSION_CONSTANTS_H_ diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index d2463a5..d8b46b4 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -467,6 +467,16 @@ class NotificationType { // view host for the page, there are no details. FOCUS_CHANGED_IN_PAGE, + // BackgroundContents ------------------------------------------------------ + + // The background contents navigated to a new location. The source is the + // BackgroundContents, and the details are contained RenderViewHost. + BACKGROUND_CONTENTS_NAVIGATED, + + // The background contents is being deleted. The source is the + // BackgroundContents, and the details are the contained RendeViewHost. + BACKGROUND_CONTENTS_DELETED, + // Child Processes --------------------------------------------------------- // This notification is sent when a child process host has connected to a diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index d575873..2bc18dd 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -654,11 +654,11 @@ IPC_BEGIN_MESSAGES(View) int /* id of the request message */, webkit_glue::FormData /* form data */) - // Sent by the Browser process to alert a window about whether a blocked - // popup notification is visible. The renderer assumes every new window is a + // Sent by the Browser process to alert a window about whether a it should + // allow a scripted window.close(). The renderer assumes every new window is a // blocked popup until notified otherwise. - IPC_MESSAGE_ROUTED1(ViewMsg_PopupNotificationVisibilityChanged, - bool /* Whether it is visible */) + IPC_MESSAGE_ROUTED1(ViewMsg_AllowScriptToClose, + bool /* script_can_close */) // Sent by AudioRendererHost to renderer to request an audio packet. IPC_MESSAGE_ROUTED3(ViewMsg_RequestAudioPacket, diff --git a/chrome/common/view_types.h b/chrome/common/view_types.h index d3f1782..f74eb36 100644 --- a/chrome/common/view_types.h +++ b/chrome/common/view_types.h @@ -12,6 +12,7 @@ class ViewType { public: enum Type { INVALID, + BACKGROUND_CONTENTS, TAB_CONTENTS, EXTENSION_TOOLSTRIP, EXTENSION_MOLE, diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index a12ef09..0a586c4 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -15,6 +15,7 @@ #include "base/string_util.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/url_pattern.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" @@ -139,8 +140,9 @@ class ExtensionViewAccumulator : public RenderViewVisitor { // match that of the arguments to the accumulator. // See bug: http://crbug.com/29646 if (!(view_type_ == ViewType::EXTENSION_POPUP && - render_view->browser_window_id() == -1)) { - if (browser_window_id_ != -1 && + render_view->browser_window_id() == + extension_misc::kUnknownWindowId)) { + if (browser_window_id_ != extension_misc::kUnknownWindowId && render_view->browser_window_id() != browser_window_id_) { return true; } @@ -318,8 +320,8 @@ class ExtensionImpl : public ExtensionBase { if (!args[0]->IsInt32() || !args[1]->IsString()) return v8::Undefined(); - // |browser_window_id| == -1 means getting views attached to any browser - // window. + // |browser_window_id| == extension_misc::kUnknownWindowId means getting + // views attached to any browser window. int browser_window_id = args[0]->Int32Value(); std::string view_type_string = *v8::String::Utf8Value(args[1]->ToString()); diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 804df48..d76a5ac 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -379,7 +379,7 @@ RenderView::RenderView(RenderThreadBase* render_thread, has_unload_listener_(false), decrement_shared_popup_at_destruction_(false), autofill_query_id_(0), - popup_notification_visible_(false), + script_can_close_(true), spelling_panel_visible_(false), send_content_state_immediately_(false), send_preferred_size_changes_(false), @@ -653,8 +653,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnAutocompleteSuggestionsReturned) IPC_MESSAGE_HANDLER(ViewMsg_AutoFillFormDataFilled, OnAutoFillFormDataFilled) - IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisibilityChanged, - OnPopupNotificationVisibilityChanged) + IPC_MESSAGE_HANDLER(ViewMsg_AllowScriptToClose, + OnAllowScriptToClose) IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse) IPC_MESSAGE_HANDLER(ViewMsg_ExtensionMessageInvoke, @@ -1503,8 +1503,8 @@ void RenderView::OnAutoFillFormDataFilled(int query_id, form_manager_.FillForm(form); } -void RenderView::OnPopupNotificationVisibilityChanged(bool visible) { - popup_notification_visible_ = visible; +void RenderView::OnAllowScriptToClose(bool script_can_close) { + script_can_close_ = script_can_close; } uint32 RenderView::GetCPBrowsingContext() { @@ -1558,7 +1558,7 @@ WebView* RenderView::createView( // This window can't be closed from a window.close() call until we receive a // message from the Browser process explicitly allowing it. - popup_notification_visible_ = true; + script_can_close_ = false; int32 routing_id = MSG_ROUTING_NONE; bool user_gesture = creator->isProcessingUserGesture(); @@ -2073,7 +2073,7 @@ void RenderView::show(WebNavigationPolicy policy) { } void RenderView::closeWidgetSoon() { - if (!popup_notification_visible_) + if (script_can_close_) RenderWidget::closeWidgetSoon(); } diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 1eda03e..ab2b4a4 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -771,8 +771,8 @@ class RenderView : public RenderWidget, void OnAutoFillFormDataFilled(int query_id, const webkit_glue::FormData& form); - // Message that the popup notification has been shown or hidden. - void OnPopupNotificationVisibilityChanged(bool visible); + // Message that script may use window.close(). + void OnAllowScriptToClose(bool script_can_close); // Handles messages posted from automation. void OnMessageFromExternalHost(const std::string& message, @@ -1086,7 +1086,7 @@ class RenderView : public RenderWidget, // is being displayed. We instead assume that when we create a window off // this RenderView, that it is going to be blocked until we get a message // from the Browser process telling us otherwise. - bool popup_notification_visible_; + bool script_can_close_; // True if the browser is showing the spelling panel for us. bool spelling_panel_visible_; |