diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-25 21:15:02 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-25 21:15:02 +0000 |
commit | a91afcbaed24615861a2c2ddb61ce51827c17e6e (patch) | |
tree | 5f6b6d31e3a929559eaa7841501f9f2798b66e85 /chrome | |
parent | 02dc409419c556ab9feb505788d02dd21c472101 (diff) | |
download | chromium_src-a91afcbaed24615861a2c2ddb61ce51827c17e6e.zip chromium_src-a91afcbaed24615861a2c2ddb61ce51827c17e6e.tar.gz chromium_src-a91afcbaed24615861a2c2ddb61ce51827c17e6e.tar.bz2 |
Re-land 42631: The problem was that notifications aren't implemented on linux/views yet.
TBR=rafaelw@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42671 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
18 files changed, 176 insertions, 26 deletions
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc index 7ee7339..7d8d15d 100644 --- a/chrome/browser/extensions/extension_dom_ui.cc +++ b/chrome/browser/extensions/extension_dom_ui.cc @@ -67,7 +67,8 @@ void ExtensionDOMUI::ResetExtensionFunctionDispatcher( NavigationController& controller = tab_contents()->controller(); const GURL& url = controller.GetActiveEntry()->url(); extension_function_dispatcher_.reset( - new ExtensionFunctionDispatcher(render_view_host, this, url)); + ExtensionFunctionDispatcher::Create(render_view_host, this, url)); + DCHECK(extension_function_dispatcher_.get()); } void ExtensionDOMUI::ResetExtensionBookmarkManagerEventRouter() { diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index f436d27..76a2300 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -263,9 +263,26 @@ std::set<ExtensionFunctionDispatcher*>* return &instances; } +ExtensionFunctionDispatcher* ExtensionFunctionDispatcher::Create( + RenderViewHost* render_view_host, + Delegate* delegate, + const GURL& url) { + ExtensionsService* service = + render_view_host->process()->profile()->GetExtensionsService(); + DCHECK(service); + + Extension* extension = service->GetExtensionByURL(url); + if (extension) + return new ExtensionFunctionDispatcher(render_view_host, delegate, + extension, url); + else + return NULL; +} + ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( RenderViewHost* render_view_host, Delegate* delegate, + Extension* extension, const GURL& url) : profile_(render_view_host->process()->profile()), render_view_host_(render_view_host), @@ -274,9 +291,6 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( ALLOW_THIS_IN_INITIALIZER_LIST(peer_(new Peer(this))) { // TODO(erikkay) should we do something for these errors in Release? DCHECK(url.SchemeIs(chrome::kExtensionScheme)); - - Extension* extension = - profile()->GetExtensionsService()->GetExtensionByURL(url); DCHECK(extension); all_instances()->insert(this); diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h index 18cce3b..86342cc 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.h +++ b/chrome/browser/extensions/extension_function_dispatcher.h @@ -77,12 +77,15 @@ class ExtensionFunctionDispatcher { // Resets all functions to their initial implementation. static void ResetFunctions(); + // Creates an instance for the specified RenderViewHost and URL. If the URL + // does not contain a valid extension, returns NULL. + static ExtensionFunctionDispatcher* Create(RenderViewHost* render_view_host, + Delegate* delegate, + const GURL& url); + // Retrieves a vector of all EFD instances. static std::set<ExtensionFunctionDispatcher*>* all_instances(); - ExtensionFunctionDispatcher(RenderViewHost* render_view_host, - Delegate* delegate, - const GURL& url); ~ExtensionFunctionDispatcher(); Delegate* delegate() { return delegate_; } @@ -123,6 +126,11 @@ class ExtensionFunctionDispatcher { RenderViewHost* render_view_host() { return render_view_host_; } private: + ExtensionFunctionDispatcher(RenderViewHost* render_view_host, + Delegate* delegate, + Extension* extension, + const GURL& url); + // We need to keep a pointer to the profile because we use it in the dtor // in sending EXTENSION_FUNCTION_DISPATCHER_DESTROYED, but by that point // the render_view_host_ has been deleted. diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index a57780b..b8baf39 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -324,7 +324,7 @@ void ExtensionHost::DidNavigate(RenderViewHost* render_view_host, << extension_->name(); url_ = params.url; extension_function_dispatcher_.reset( - new ExtensionFunctionDispatcher(render_view_host_, this, url_)); + ExtensionFunctionDispatcher::Create(render_view_host_, this, url_)); } void ExtensionHost::InsertInfobarCSS() { @@ -676,7 +676,7 @@ void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { LOG(INFO) << "(RenderViewCreated) Resetting EFD to " << url_.spec() << " for " << extension_->name(); extension_function_dispatcher_.reset( - new ExtensionFunctionDispatcher(render_view_host, this, url_)); + ExtensionFunctionDispatcher::Create(render_view_host, this, url_)); if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || extension_host_type_ == ViewType::EXTENSION_MOLE || diff --git a/chrome/browser/extensions/fragment_navigation_apitest.cc b/chrome/browser/extensions/fragment_navigation_apitest.cc index 7524c91..00bc536 100644 --- a/chrome/browser/extensions/fragment_navigation_apitest.cc +++ b/chrome/browser/extensions/fragment_navigation_apitest.cc @@ -16,4 +16,3 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ExecuteScriptFragmentNavigation) { const char* extension_name = "executescript/fragment"; ASSERT_TRUE(RunExtensionTest(extension_name)) << message_; } - diff --git a/chrome/browser/extensions/notifications_apitest.cc b/chrome/browser/extensions/notifications_apitest.cc new file mode 100644 index 0000000..2fd86fa --- /dev/null +++ b/chrome/browser/extensions/notifications_apitest.cc @@ -0,0 +1,15 @@ +// 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/extensions/extension_apitest.h" + + +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Notifications) { +#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS) + // Notifications not supported on linux/views yet. +#else + ASSERT_TRUE(RunExtensionTest("notifications/has_permission")) << message_; + ASSERT_TRUE(RunExtensionTest("notifications/has_not_permission")) << message_; +#endif +} diff --git a/chrome/browser/gtk/notifications/balloon_view_gtk.cc b/chrome/browser/gtk/notifications/balloon_view_gtk.cc index 3775b5b..b73d6a5 100644 --- a/chrome/browser/gtk/notifications/balloon_view_gtk.cc +++ b/chrome/browser/gtk/notifications/balloon_view_gtk.cc @@ -92,7 +92,6 @@ BalloonViewImpl::BalloonViewImpl(BalloonCollection* collection) : balloon_(NULL), frame_container_(NULL), html_container_(NULL), - html_contents_(NULL), method_factory_(this), close_button_(NULL), animation_(NULL) { @@ -221,7 +220,7 @@ void BalloonViewImpl::Show(Balloon* balloon) { options_menu_.reset(new MenuGtk(this, options_menu_model_.get())); // Create a BalloonViewHost to host the HTML contents of this balloon. - html_contents_ = new BalloonViewHost(balloon); + html_contents_.reset(new BalloonViewHost(balloon)); html_contents_->Init(); gfx::NativeView contents = html_contents_->native_view(); diff --git a/chrome/browser/gtk/notifications/balloon_view_gtk.h b/chrome/browser/gtk/notifications/balloon_view_gtk.h index 9412cad..289354a 100644 --- a/chrome/browser/gtk/notifications/balloon_view_gtk.h +++ b/chrome/browser/gtk/notifications/balloon_view_gtk.h @@ -113,8 +113,8 @@ class BalloonViewImpl : public BalloonView, // The window that contains the contents of the notification. GtkWidget* html_container_; - // The renderer of the HTML contents. Pointer owned by the views hierarchy. - BalloonViewHost* html_contents_; + // The renderer of the HTML contents. + scoped_ptr<BalloonViewHost> html_contents_; // The following factory is used to call methods at a later time. ScopedRunnableMethodFactory<BalloonViewImpl> method_factory_; diff --git a/chrome/browser/gtk/notifications/balloon_view_host_gtk.h b/chrome/browser/gtk/notifications/balloon_view_host_gtk.h index 833a78c..f51b875 100644 --- a/chrome/browser/gtk/notifications/balloon_view_host_gtk.h +++ b/chrome/browser/gtk/notifications/balloon_view_host_gtk.h @@ -19,7 +19,7 @@ class BalloonViewHost : public BalloonHost { explicit BalloonViewHost(Balloon* balloon); ~BalloonViewHost() { - Shutdown(); + Shutdown(); } // Changes the size of the balloon. diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc index 3b4a832..9e9ba28 100644 --- a/chrome/browser/notifications/balloon_host.cc +++ b/chrome/browser/notifications/balloon_host.cc @@ -23,8 +23,7 @@ BalloonHost::BalloonHost(Balloon* balloon) : render_view_host_(NULL), balloon_(balloon), initialized_(false), - should_notify_on_disconnect_(false), - is_extension_page_(false) { + should_notify_on_disconnect_(false) { DCHECK(balloon_); // If the notification is for an extension URL, make sure to use the extension @@ -32,7 +31,6 @@ BalloonHost::BalloonHost(Balloon* balloon) // extension. const GURL& balloon_url = balloon_->notification().content_url(); if (balloon_url.SchemeIs(chrome::kExtensionScheme)) { - is_extension_page_ = true; site_instance_ = balloon_->profile()->GetExtensionProcessManager()->GetSiteInstanceForURL( balloon_url); @@ -81,6 +79,16 @@ void BalloonHost::RendererGone(RenderViewHost* render_view_host) { Source<Balloon>(balloon_), NotificationService::NoDetails()); } +void BalloonHost::ProcessDOMUIMessage(const std::string& message, + const Value* content, + int request_id, + bool has_callback) { + if (extension_function_dispatcher_.get()) { + extension_function_dispatcher_->HandleRequest( + message, content, request_id, has_callback); + } +} + // RenderViewHostDelegate::View methods implemented to allow links to // open pages in new tabs. void BalloonHost::CreateNewWindow(int route_id) { @@ -90,9 +98,9 @@ void BalloonHost::CreateNewWindow(int route_id) { } void BalloonHost::ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { // Don't allow pop-ups from notifications. if (disposition == NEW_POPUP) return; @@ -115,7 +123,10 @@ void BalloonHost::Init() { RenderViewHost* rvh = new RenderViewHost(site_instance_.get(), this, MSG_ROUTING_NONE, session_storage_namespace_id); - if (is_extension_page_) + extension_function_dispatcher_.reset( + ExtensionFunctionDispatcher::Create( + rvh, this, balloon_->notification().content_url())); + if (extension_function_dispatcher_.get()) rvh->AllowBindings(BindingsPolicy::EXTENSION); // Do platform-specific initialization. diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h index b42ea46..b1f47a2 100644 --- a/chrome/browser/notifications/balloon_host.h +++ b/chrome/browser/notifications/balloon_host.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_NOTIFICATIONS_BALLOON_HOST_H_ #define CHROME_BROWSER_NOTIFICATIONS_BALLOON_HOST_H_ +#include "chrome/browser/extensions/extension_function_dispatcher.h" #include "chrome/browser/notifications/balloon.h" #include "chrome/browser/notifications/notification.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" @@ -13,10 +14,12 @@ #include "chrome/common/renderer_preferences.h" #include "webkit/glue/webpreferences.h" +class Browser; class Profile; class BalloonHost : public RenderViewHostDelegate, - public RenderViewHostDelegate::View { + public RenderViewHostDelegate::View, + public ExtensionFunctionDispatcher::Delegate { public: explicit BalloonHost(Balloon* balloon); @@ -26,6 +29,16 @@ class BalloonHost : public RenderViewHostDelegate, // Stops showing the balloon. void Shutdown(); + // ExtensionFunctionDispatcher::Delegate overrides. + virtual Browser* GetBrowser() const { + // Notifications aren't associated with a particular browser. + return NULL; + } + virtual gfx::NativeView GetNativeViewOfHost() { + // TODO(aa): Should this return the native view of the BalloonView*? + return NULL; + } + RenderViewHost* render_view_host() const { return render_view_host_; } // RenderViewHostDelegate overrides. @@ -50,6 +63,10 @@ class BalloonHost : public RenderViewHostDelegate, virtual RenderViewHostDelegate::View* GetViewDelegate() { return this; } + virtual void ProcessDOMUIMessage(const std::string& message, + const Value* content, + int request_id, + bool has_callback); // RenderViewHostDelegate::View methods. Only the ones for opening new // windows are currently implemented. @@ -103,14 +120,15 @@ class BalloonHost : public RenderViewHostDelegate, // a connection notification has happened and that they happen only once. bool should_notify_on_disconnect_; - // Whether the page we are rendering is from an extension. - bool is_extension_page_; - // Site instance for the balloon/profile, to be used for opening new links. scoped_refptr<SiteInstance> site_instance_; // Common implementations of some RenderViewHostDelegate::View methods. RenderViewHostDelegateViewHelper delegate_view_helper_; + + // Handles requests to extension APIs. Will only be non-NULL if we are + // rendering a page from an extension. + scoped_ptr<ExtensionFunctionDispatcher> extension_function_dispatcher_; }; #endif // CHROME_BROWSER_NOTIFICATIONS_BALLOON_HOST_H_ diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 44c726c..b8db1cb 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1258,6 +1258,7 @@ 'browser/extensions/extension_websocket_apitest.cc', 'browser/extensions/fragment_navigation_apitest.cc', 'browser/extensions/isolated_world_apitest.cc', + 'browser/extensions/notifications_apitest.cc', 'browser/extensions/page_action_apitest.cc', 'browser/extensions/permissions_apitest.cc', 'browser/extensions/stubs_apitest.cc', diff --git a/chrome/test/data/extensions/api_test/notifications/has_not_permission/background.html b/chrome/test/data/extensions/api_test/notifications/has_not_permission/background.html new file mode 100644 index 0000000..f9e23d4b --- /dev/null +++ b/chrome/test/data/extensions/api_test/notifications/has_not_permission/background.html @@ -0,0 +1,20 @@ +<script> +chrome.test.runTests([ + function hasPermission() { + chrome.test.assertEq(1, // permission not allowed + webkitNotifications.checkPermission()); + chrome.test.succeed(); + }, + function showNotification() { + try { + window.webkitNotifications.createHTMLNotification( + chrome.extension.getURL("notification.html")).show(); + } catch (e) { + chrome.test.assertTrue(e.message.indexOf("SECURITY_ERR") == 0); + chrome.test.succeed(); + return; + } + chrome.test.fail("Expected access denied error."); + } +]); +</script> diff --git a/chrome/test/data/extensions/api_test/notifications/has_not_permission/manifest.json b/chrome/test/data/extensions/api_test/notifications/has_not_permission/manifest.json new file mode 100644 index 0000000..4f7ed68 --- /dev/null +++ b/chrome/test/data/extensions/api_test/notifications/has_not_permission/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "notifications test", + "version": "1", + "permissions": [ "tabs" ], + "background_page": "background.html" +} diff --git a/chrome/test/data/extensions/api_test/notifications/has_not_permission/notification.html b/chrome/test/data/extensions/api_test/notifications/has_not_permission/notification.html new file mode 100644 index 0000000..77cf46f --- /dev/null +++ b/chrome/test/data/extensions/api_test/notifications/has_not_permission/notification.html @@ -0,0 +1,3 @@ +<html> +Why hello there. +</html> diff --git a/chrome/test/data/extensions/api_test/notifications/has_permission/background.html b/chrome/test/data/extensions/api_test/notifications/has_permission/background.html new file mode 100644 index 0000000..4b43004 --- /dev/null +++ b/chrome/test/data/extensions/api_test/notifications/has_permission/background.html @@ -0,0 +1,37 @@ +<script> +var notification = null; + +// Shows the notification window using the specified URL. +// Control continues at onNotificationDone(). +function showNotification(url) { + notification = window.webkitNotifications.createHTMLNotification(url); + notification.onerror = function() { + chrome.test.fail("Failed to show notification."); + }; + notification.show(); +} + +// Called by the notification when it is done with its tests. +function onNotificationDone() { + var views = chrome.extension.getViews(); + chrome.test.assertEq(2, views.length); + notification.cancel(); + chrome.test.succeed(); +} + +chrome.test.runTests([ + function hasPermission() { + chrome.test.assertEq(0, // allowed + webkitNotifications.checkPermission()); + chrome.test.succeed(); + }, + function absoluteURL() { + showNotification(chrome.extension.getURL("notification.html")); + }, + function relativeURL() { + // TODO(aa): Relative URLs don't work for some reason. + // BUG: http://crbug.com/39216 + chrome.test.succeed(); + } +]); +</script> diff --git a/chrome/test/data/extensions/api_test/notifications/has_permission/manifest.json b/chrome/test/data/extensions/api_test/notifications/has_permission/manifest.json new file mode 100644 index 0000000..a2fa64f --- /dev/null +++ b/chrome/test/data/extensions/api_test/notifications/has_permission/manifest.json @@ -0,0 +1,6 @@ +{ + "name": "notifications test", + "version": "1", + "permissions": [ "notifications", "tabs" ], + "background_page": "background.html" +} diff --git a/chrome/test/data/extensions/api_test/notifications/has_permission/notification.html b/chrome/test/data/extensions/api_test/notifications/has_permission/notification.html new file mode 100644 index 0000000..8a78703 --- /dev/null +++ b/chrome/test/data/extensions/api_test/notifications/has_permission/notification.html @@ -0,0 +1,12 @@ +<html> +<script> +// Test that we can call the tabs API. We don't care what the result is; tabs +// are tested elsewhere. We just care that we can call it without a +// permissions error. +chrome.windows.getAll(null, function() { + chrome.test.assertNoLastError(); + chrome.extension.getBackgroundPage().onNotificationDone(); +}); +</script> +Why hello there. +</html> |