1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/push_messaging/push_messaging_api.h"
7 #include "apps/launcher.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler.h"
10 #include "chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_mapper.h"
11 #include "chrome/browser/extensions/extension_apitest.h"
12 #include "chrome/browser/extensions/extension_test_message_listener.h"
13 #include "chrome/browser/invalidation/fake_invalidation_service.h"
14 #include "chrome/browser/invalidation/invalidation_service_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "components/invalidation/invalidation_service.h"
20 #include "google/cacheinvalidation/types.pb.h"
21 #include "sync/internal_api/public/base/invalidation.h"
22 #include "sync/notifier/fake_invalidator.h"
23 #include "testing/gmock/include/gmock/gmock.h"
25 using ::testing::SaveArg;
26 using ::testing::StrictMock;
29 using invalidation::InvalidationServiceFactory;
31 namespace extensions {
35 invalidation::ObjectId ExtensionAndSubchannelToObjectId(
36 const std::string& extension_id, int subchannel_id) {
37 return invalidation::ObjectId(
38 ipc::invalidation::ObjectSource::CHROME_PUSH_MESSAGING,
39 base::StringPrintf("U/%s/%d", extension_id.c_str(), subchannel_id));
42 class MockInvalidationMapper : public PushMessagingInvalidationMapper {
44 MockInvalidationMapper();
45 ~MockInvalidationMapper();
47 MOCK_METHOD1(SuppressInitialInvalidationsForExtension,
48 void(const std::string&));
49 MOCK_METHOD1(RegisterExtension, void(const std::string&));
50 MOCK_METHOD1(UnregisterExtension, void(const std::string&));
53 MockInvalidationMapper::MockInvalidationMapper() {}
54 MockInvalidationMapper::~MockInvalidationMapper() {}
58 class PushMessagingApiTest : public ExtensionApiTest {
60 PushMessagingApiTest()
61 : fake_invalidation_service_(NULL) {
64 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
65 ExtensionApiTest::SetUpCommandLine(command_line);
68 virtual void SetUp() OVERRIDE {
69 InvalidationServiceFactory::GetInstance()->RegisterTestingFactory(
70 invalidation::FakeInvalidationService::Build);
71 ExtensionApiTest::SetUp();
74 virtual void SetUpOnMainThread() OVERRIDE {
75 ExtensionApiTest::SetUpOnMainThread();
76 fake_invalidation_service_ =
77 static_cast<invalidation::FakeInvalidationService*>(
78 InvalidationServiceFactory::GetInstance()->GetForProfile(
82 void EmitInvalidation(
83 const invalidation::ObjectId& object_id,
85 const std::string& payload) {
86 fake_invalidation_service_->EmitInvalidationForTest(
87 syncer::Invalidation::Init(object_id, version, payload));
90 PushMessagingAPI* GetAPI() {
91 return PushMessagingAPI::Get(profile());
94 PushMessagingEventRouter* GetEventRouter() {
95 return PushMessagingAPI::Get(profile())->GetEventRouterForTest();
98 invalidation::FakeInvalidationService* fake_invalidation_service_;
101 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, EventDispatch) {
102 ResultCatcher catcher;
103 catcher.RestrictToProfile(profile());
105 const extensions::Extension* extension =
106 LoadExtension(test_data_dir_.AppendASCII("push_messaging"));
107 ASSERT_TRUE(extension);
108 ui_test_utils::NavigateToURL(
109 browser(), extension->GetResourceURL("event_dispatch.html"));
111 GetEventRouter()->TriggerMessageForTest(extension->id(), 1, "payload");
113 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
116 // Test that a push introduced into the sync code makes it to the extension
118 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, ReceivesPush) {
119 ResultCatcher catcher;
120 catcher.RestrictToProfile(profile());
122 const extensions::Extension* extension =
123 LoadExtension(test_data_dir_.AppendASCII("push_messaging"));
124 ASSERT_TRUE(extension);
125 ui_test_utils::NavigateToURL(
126 browser(), extension->GetResourceURL("event_dispatch.html"));
128 // PushMessagingInvalidationHandler suppresses the initial invalidation on
129 // each subchannel at install, so trigger the suppressions first.
130 for (int i = 0; i < 3; ++i) {
132 ExtensionAndSubchannelToObjectId(extension->id(), i), i, std::string());
136 ExtensionAndSubchannelToObjectId(extension->id(), 1), 5, "payload");
137 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
140 // Checks that an extension with the pushMessaging permission gets automatically
141 // registered for invalidations when it is loaded.
142 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, AutoRegistration) {
143 scoped_ptr<StrictMock<MockInvalidationMapper> > mapper(
144 new StrictMock<MockInvalidationMapper>);
145 StrictMock<MockInvalidationMapper>* unsafe_mapper = mapper.get();
146 // PushMessagingEventRouter owns the mapper now.
147 GetAPI()->SetMapperForTest(
148 mapper.PassAs<PushMessagingInvalidationMapper>());
150 std::string extension_id1;
151 std::string extension_id2;
152 EXPECT_CALL(*unsafe_mapper, SuppressInitialInvalidationsForExtension(_))
153 .WillOnce(SaveArg<0>(&extension_id1));
154 EXPECT_CALL(*unsafe_mapper, RegisterExtension(_))
155 .WillOnce(SaveArg<0>(&extension_id2));
156 const extensions::Extension* extension =
157 LoadExtension(test_data_dir_.AppendASCII("push_messaging"));
158 ASSERT_TRUE(extension);
159 EXPECT_EQ(extension->id(), extension_id1);
160 EXPECT_EQ(extension->id(), extension_id2);
161 EXPECT_CALL(*unsafe_mapper, UnregisterExtension(extension->id()));
162 UnloadExtension(extension->id());
165 // Tests that we re-register for invalidations on restart for extensions that
166 // are already installed.
167 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, PRE_Restart) {
168 PushMessagingInvalidationHandler* handler =
169 static_cast<PushMessagingInvalidationHandler*>(
170 GetAPI()->GetMapperForTest());
171 EXPECT_TRUE(handler->GetRegisteredExtensionsForTest().empty());
172 ASSERT_TRUE(InstallExtension(test_data_dir_.AppendASCII("push_messaging"),
173 1 /* new install */));
176 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, Restart) {
177 PushMessagingInvalidationHandler* handler =
178 static_cast<PushMessagingInvalidationHandler*>(
179 GetAPI()->GetMapperForTest());
180 EXPECT_EQ(1U, handler->GetRegisteredExtensionsForTest().size());
183 // Test that GetChannelId fails if no user is signed in.
184 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, GetChannelId) {
185 ResultCatcher catcher;
186 catcher.RestrictToProfile(profile());
188 const extensions::Extension* extension =
189 LoadExtension(test_data_dir_.AppendASCII("push_messaging"));
190 ASSERT_TRUE(extension);
191 ui_test_utils::NavigateToURL(
192 browser(), extension->GetResourceURL("get_channel_id.html"));
194 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
197 } // namespace extensions