Home | History | Annotate | Download | only in push_messaging
      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.
      4 
      5 #include "chrome/browser/extensions/api/push_messaging/push_messaging_api.h"
      6 
      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.h"
     15 #include "chrome/browser/invalidation/invalidation_service_factory.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/common/chrome_switches.h"
     19 #include "chrome/test/base/ui_test_utils.h"
     20 #include "google/cacheinvalidation/types.pb.h"
     21 #include "sync/notifier/fake_invalidator.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 
     24 using ::testing::_;
     25 using ::testing::SaveArg;
     26 using ::testing::StrictMock;
     27 
     28 using invalidation::InvalidationServiceFactory;
     29 
     30 namespace extensions {
     31 
     32 namespace {
     33 
     34 invalidation::ObjectId ExtensionAndSubchannelToObjectId(
     35     const std::string& extension_id, int subchannel_id) {
     36   return invalidation::ObjectId(
     37       ipc::invalidation::ObjectSource::CHROME_PUSH_MESSAGING,
     38       base::StringPrintf("U/%s/%d", extension_id.c_str(), subchannel_id));
     39 }
     40 
     41 class MockInvalidationMapper : public PushMessagingInvalidationMapper {
     42  public:
     43   MockInvalidationMapper();
     44   ~MockInvalidationMapper();
     45 
     46   MOCK_METHOD1(SuppressInitialInvalidationsForExtension,
     47                void(const std::string&));
     48   MOCK_METHOD1(RegisterExtension, void(const std::string&));
     49   MOCK_METHOD1(UnregisterExtension, void(const std::string&));
     50 };
     51 
     52 MockInvalidationMapper::MockInvalidationMapper() {}
     53 MockInvalidationMapper::~MockInvalidationMapper() {}
     54 
     55 }  // namespace
     56 
     57 class PushMessagingApiTest : public ExtensionApiTest {
     58  public:
     59   PushMessagingApiTest()
     60       : fake_invalidation_service_(NULL) {
     61   }
     62 
     63   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     64     ExtensionApiTest::SetUpCommandLine(command_line);
     65   }
     66 
     67   virtual void SetUp() OVERRIDE {
     68     InvalidationServiceFactory::GetInstance()->
     69         SetBuildOnlyFakeInvalidatorsForTest(true);
     70     ExtensionApiTest::SetUp();
     71   }
     72 
     73   virtual void SetUpOnMainThread() OVERRIDE {
     74     ExtensionApiTest::SetUpOnMainThread();
     75     fake_invalidation_service_ =
     76         static_cast<invalidation::FakeInvalidationService*>(
     77             InvalidationServiceFactory::GetInstance()->GetForProfile(
     78                 profile()));
     79   }
     80 
     81   void EmitInvalidation(
     82       const invalidation::ObjectId& object_id,
     83       const std::string& payload) {
     84     fake_invalidation_service_->EmitInvalidationForTest(
     85         object_id,
     86         syncer::Invalidation::kUnknownVersion,
     87         payload);
     88   }
     89 
     90   PushMessagingAPI* GetAPI() {
     91     return PushMessagingAPI::Get(profile());
     92   }
     93 
     94   PushMessagingEventRouter* GetEventRouter() {
     95     return PushMessagingAPI::Get(profile())->GetEventRouterForTest();
     96   }
     97 
     98   invalidation::FakeInvalidationService* fake_invalidation_service_;
     99 };
    100 
    101 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, EventDispatch) {
    102   ResultCatcher catcher;
    103   catcher.RestrictToProfile(profile());
    104 
    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"));
    110 
    111   GetEventRouter()->TriggerMessageForTest(extension->id(), 1, "payload");
    112 
    113   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    114 }
    115 
    116 // Test that a push introduced into the sync code makes it to the extension
    117 // that we install.
    118 IN_PROC_BROWSER_TEST_F(PushMessagingApiTest, ReceivesPush) {
    119   ResultCatcher catcher;
    120   catcher.RestrictToProfile(profile());
    121 
    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"));
    127 
    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) {
    131     EmitInvalidation(
    132         ExtensionAndSubchannelToObjectId(extension->id(), i), std::string());
    133   }
    134 
    135   EmitInvalidation(
    136       ExtensionAndSubchannelToObjectId(extension->id(), 1), "payload");
    137   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    138 }
    139 
    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>());
    149 
    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());
    163 }
    164 
    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 */));
    174 }
    175 
    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());
    181 }
    182 
    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());
    187 
    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"));
    193 
    194   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    195 }
    196 
    197 }  // namespace extensions
    198