| // Copyright (c) 2012 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 "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/extensions/api/notifications/notifications_api.h" |
| #include "chrome/browser/extensions/extension_apitest.h" |
| #include "chrome/browser/extensions/extension_function_test_utils.h" |
| #include "chrome/browser/notifications/notification.h" |
| #include "chrome/browser/notifications/notification_ui_manager.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/test/test_utils.h" |
| #include "extensions/browser/api/test/test_api.h" |
| #include "extensions/browser/notification_types.h" |
| #include "extensions/common/features/feature.h" |
| #include "ui/message_center/message_center.h" |
| #include "ui/message_center/notification_list.h" |
| #include "ui/message_center/notifier_settings.h" |
| |
| using extensions::Extension; |
| |
| namespace utils = extension_function_test_utils; |
| |
| namespace { |
| |
| // A class that waits for a |chrome.test.sendMessage| call, ignores the message, |
| // and writes down the user gesture status of the message. |
| class UserGestureCatcher : public content::NotificationObserver { |
| public: |
| UserGestureCatcher() : waiting_(false) { |
| registrar_.Add(this, |
| extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE, |
| content::NotificationService::AllSources()); |
| } |
| |
| virtual ~UserGestureCatcher() {} |
| |
| bool GetNextResult() { |
| if (results_.empty()) { |
| waiting_ = true; |
| content::RunMessageLoop(); |
| waiting_ = false; |
| } |
| |
| if (!results_.empty()) { |
| bool ret = results_.front(); |
| results_.pop_front(); |
| return ret; |
| } |
| NOTREACHED(); |
| return false; |
| } |
| |
| private: |
| virtual void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) OVERRIDE { |
| results_.push_back( |
| static_cast<content::Source<extensions::TestSendMessageFunction> >( |
| source) |
| .ptr() |
| ->user_gesture()); |
| if (waiting_) |
| base::MessageLoopForUI::current()->Quit(); |
| } |
| |
| content::NotificationRegistrar registrar_; |
| |
| // A sequential list of user gesture notifications from the test extension(s). |
| std::deque<bool> results_; |
| |
| // True if we're in a nested message loop waiting for results from |
| // the extension. |
| bool waiting_; |
| }; |
| |
| class NotificationsApiTest : public ExtensionApiTest { |
| public: |
| const extensions::Extension* LoadExtensionAndWait( |
| const std::string& test_name) { |
| base::FilePath extdir = test_data_dir_.AppendASCII(test_name); |
| content::WindowedNotificationObserver page_created( |
| extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, |
| content::NotificationService::AllSources()); |
| const extensions::Extension* extension = LoadExtension(extdir); |
| if (extension) { |
| page_created.Wait(); |
| } |
| return extension; |
| } |
| }; |
| |
| } // namespace |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestBasicUsage) { |
| ASSERT_TRUE(RunExtensionTest("notifications/api/basic_usage")) << message_; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestEvents) { |
| ASSERT_TRUE(RunExtensionTest("notifications/api/events")) << message_; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestCSP) { |
| ASSERT_TRUE(RunExtensionTest("notifications/api/csp")) << message_; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) { |
| const extensions::Extension* extension = |
| LoadExtensionAndWait("notifications/api/by_user"); |
| ASSERT_TRUE(extension) << message_; |
| |
| { |
| ResultCatcher catcher; |
| g_browser_process->message_center()->RemoveNotification( |
| extension->id() + "-FOO", |
| false); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| { |
| ResultCatcher catcher; |
| g_browser_process->message_center()->RemoveNotification( |
| extension->id() + "-BAR", |
| true); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| { |
| ResultCatcher catcher; |
| g_browser_process->message_center()->RemoveAllNotifications(false); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| { |
| ResultCatcher catcher; |
| g_browser_process->message_center()->RemoveAllNotifications(true); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestPartialUpdate) { |
| ASSERT_TRUE(RunExtensionTest("notifications/api/partial_update")) << message_; |
| const extensions::Extension* extension = GetSingleLoadedExtension(); |
| ASSERT_TRUE(extension) << message_; |
| |
| const char kNewTitle[] = "Changed!"; |
| const char kNewMessage[] = "Too late! The show ended yesterday"; |
| int kNewPriority = 2; |
| |
| const message_center::NotificationList::Notifications& notifications = |
| g_browser_process->message_center()->GetVisibleNotifications(); |
| ASSERT_EQ(1u, notifications.size()); |
| message_center::Notification* notification = *(notifications.begin()); |
| LOG(INFO) << "Notification ID: " << notification->id(); |
| |
| EXPECT_EQ(base::ASCIIToUTF16(kNewTitle), notification->title()); |
| EXPECT_EQ(base::ASCIIToUTF16(kNewMessage), notification->message()); |
| EXPECT_EQ(kNewPriority, notification->priority()); |
| EXPECT_EQ(0u, notification->buttons().size()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestGetPermissionLevel) { |
| scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); |
| |
| // Get permission level for the extension whose notifications are enabled. |
| { |
| scoped_refptr<extensions::NotificationsGetPermissionLevelFunction> |
| notification_function( |
| new extensions::NotificationsGetPermissionLevelFunction()); |
| |
| notification_function->set_extension(empty_extension.get()); |
| notification_function->set_has_callback(true); |
| |
| scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( |
| notification_function.get(), |
| "[]", |
| browser(), |
| utils::NONE)); |
| |
| EXPECT_EQ(base::Value::TYPE_STRING, result->GetType()); |
| std::string permission_level; |
| EXPECT_TRUE(result->GetAsString(&permission_level)); |
| EXPECT_EQ("granted", permission_level); |
| } |
| |
| // Get permission level for the extension whose notifications are disabled. |
| { |
| scoped_refptr<extensions::NotificationsGetPermissionLevelFunction> |
| notification_function( |
| new extensions::NotificationsGetPermissionLevelFunction()); |
| |
| notification_function->set_extension(empty_extension.get()); |
| notification_function->set_has_callback(true); |
| |
| message_center::NotifierId notifier_id( |
| message_center::NotifierId::APPLICATION, |
| empty_extension->id()); |
| message_center::Notifier notifier(notifier_id, base::string16(), true); |
| g_browser_process->message_center()->GetNotifierSettingsProvider()-> |
| SetNotifierEnabled(notifier, false); |
| |
| scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( |
| notification_function.get(), |
| "[]", |
| browser(), |
| utils::NONE)); |
| |
| EXPECT_EQ(base::Value::TYPE_STRING, result->GetType()); |
| std::string permission_level; |
| EXPECT_TRUE(result->GetAsString(&permission_level)); |
| EXPECT_EQ("denied", permission_level); |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestOnPermissionLevelChanged) { |
| const extensions::Extension* extension = |
| LoadExtensionAndWait("notifications/api/permission"); |
| ASSERT_TRUE(extension) << message_; |
| |
| // Test permission level changing from granted to denied. |
| { |
| ResultCatcher catcher; |
| |
| message_center::NotifierId notifier_id( |
| message_center::NotifierId::APPLICATION, |
| extension->id()); |
| message_center::Notifier notifier(notifier_id, base::string16(), true); |
| g_browser_process->message_center()->GetNotifierSettingsProvider()-> |
| SetNotifierEnabled(notifier, false); |
| |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| // Test permission level changing from denied to granted. |
| { |
| ResultCatcher catcher; |
| |
| message_center::NotifierId notifier_id( |
| message_center::NotifierId::APPLICATION, |
| extension->id()); |
| message_center::Notifier notifier(notifier_id, base::string16(), false); |
| g_browser_process->message_center()->GetNotifierSettingsProvider()-> |
| SetNotifierEnabled(notifier, true); |
| |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestUserGesture) { |
| const extensions::Extension* extension = |
| LoadExtensionAndWait("notifications/api/user_gesture"); |
| ASSERT_TRUE(extension) << message_; |
| |
| const message_center::NotificationList::Notifications& notifications = |
| g_browser_process->message_center()->GetVisibleNotifications(); |
| ASSERT_EQ(1u, notifications.size()); |
| message_center::Notification* notification = *(notifications.begin()); |
| |
| { |
| UserGestureCatcher catcher; |
| notification->ButtonClick(0); |
| EXPECT_TRUE(catcher.GetNextResult()); |
| notification->Click(); |
| EXPECT_TRUE(catcher.GetNextResult()); |
| notification->Close(true); |
| EXPECT_TRUE(catcher.GetNextResult()); |
| notification->Close(false); |
| EXPECT_FALSE(catcher.GetNextResult()); |
| } |
| } |