Home | History | Annotate | Download | only in service_worker
      1 // Copyright 2014 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 "base/basictypes.h"
      6 #include "base/memory/weak_ptr.h"
      7 #include "content/browser/service_worker/service_worker_context_core.h"
      8 #include "content/browser/service_worker/service_worker_provider_host.h"
      9 #include "content/browser/service_worker/service_worker_register_job.h"
     10 #include "content/browser/service_worker/service_worker_registration.h"
     11 #include "content/browser/service_worker/service_worker_version.h"
     12 #include "content/public/test/test_browser_thread_bundle.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace content {
     16 
     17 static const int kRenderProcessId = 33;  // Dummy process ID for testing.
     18 
     19 class ServiceWorkerProviderHostTest : public testing::Test {
     20  protected:
     21   ServiceWorkerProviderHostTest()
     22       : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
     23   virtual ~ServiceWorkerProviderHostTest() {}
     24 
     25   virtual void SetUp() OVERRIDE {
     26     context_.reset(
     27         new ServiceWorkerContextCore(base::FilePath(),
     28                                      base::MessageLoopProxy::current(),
     29                                      base::MessageLoopProxy::current(),
     30                                      NULL,
     31                                      NULL,
     32                                      NULL));
     33 
     34     scope_ = GURL("http://www.example.com/*");
     35     script_url_ = GURL("http://www.example.com/service_worker.js");
     36     registration_ = new ServiceWorkerRegistration(
     37         scope_, script_url_, 1L, context_->AsWeakPtr());
     38     version_ = new ServiceWorkerVersion(
     39         registration_,
     40         1L, context_->AsWeakPtr());
     41 
     42     // Prepare provider hosts (for the same process).
     43     scoped_ptr<ServiceWorkerProviderHost> host1(new ServiceWorkerProviderHost(
     44         kRenderProcessId, 1 /* provider_id */,
     45         context_->AsWeakPtr(), NULL));
     46     scoped_ptr<ServiceWorkerProviderHost> host2(new ServiceWorkerProviderHost(
     47         kRenderProcessId, 2 /* provider_id */,
     48         context_->AsWeakPtr(), NULL));
     49     scoped_ptr<ServiceWorkerProviderHost> host3(new ServiceWorkerProviderHost(
     50         kRenderProcessId, 3 /* provider_id */,
     51         context_->AsWeakPtr(), NULL));
     52     provider_host1_ = host1->AsWeakPtr();
     53     provider_host2_ = host2->AsWeakPtr();
     54     provider_host3_ = host3->AsWeakPtr();
     55     context_->AddProviderHost(make_scoped_ptr(host1.release()));
     56     context_->AddProviderHost(make_scoped_ptr(host2.release()));
     57     context_->AddProviderHost(make_scoped_ptr(host3.release()));
     58   }
     59 
     60   virtual void TearDown() OVERRIDE {
     61     version_ = 0;
     62     registration_ = 0;
     63     context_.reset();
     64   }
     65 
     66   content::TestBrowserThreadBundle thread_bundle_;
     67   scoped_ptr<ServiceWorkerContextCore> context_;
     68   scoped_refptr<ServiceWorkerRegistration> registration_;
     69   scoped_refptr<ServiceWorkerVersion> version_;
     70   base::WeakPtr<ServiceWorkerProviderHost> provider_host1_;
     71   base::WeakPtr<ServiceWorkerProviderHost> provider_host2_;
     72   base::WeakPtr<ServiceWorkerProviderHost> provider_host3_;
     73   GURL scope_;
     74   GURL script_url_;
     75 
     76  private:
     77   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostTest);
     78 };
     79 
     80 TEST_F(ServiceWorkerProviderHostTest, SetActiveVersion_ProcessStatus) {
     81   ASSERT_FALSE(version_->HasProcessToRun());
     82 
     83   // Associating version_ to a provider_host's active version will internally
     84   // add the provider_host's process ref to the version.
     85   provider_host1_->SetActiveVersion(version_);
     86   ASSERT_TRUE(version_->HasProcessToRun());
     87 
     88   // Re-associating the same version and provider_host should just work too.
     89   provider_host1_->SetActiveVersion(version_);
     90   ASSERT_TRUE(version_->HasProcessToRun());
     91 
     92   // Resetting the provider_host's active version should remove process refs
     93   // from the version.
     94   provider_host1_->SetActiveVersion(NULL);
     95   ASSERT_FALSE(version_->HasProcessToRun());
     96 }
     97 
     98 TEST_F(ServiceWorkerProviderHostTest,
     99        SetActiveVersion_MultipleHostsForSameProcess) {
    100   ASSERT_FALSE(version_->HasProcessToRun());
    101 
    102   // Associating version_ to two providers as active version.
    103   provider_host1_->SetActiveVersion(version_);
    104   provider_host2_->SetActiveVersion(version_);
    105   ASSERT_TRUE(version_->HasProcessToRun());
    106 
    107   // Disassociating one provider_host shouldn't remove all process refs
    108   // from the version yet.
    109   provider_host1_->SetActiveVersion(NULL);
    110   ASSERT_TRUE(version_->HasProcessToRun());
    111 
    112   // Disassociating the other provider_host will remove all process refs.
    113   provider_host2_->SetActiveVersion(NULL);
    114   ASSERT_FALSE(version_->HasProcessToRun());
    115 }
    116 
    117 TEST_F(ServiceWorkerProviderHostTest, SetWaitingVersion_ProcessStatus) {
    118   ASSERT_FALSE(version_->HasProcessToRun());
    119 
    120   // Associating version_ to a provider_host's waiting version will internally
    121   // add the provider_host's process ref to the version.
    122   provider_host1_->SetWaitingVersion(version_);
    123   ASSERT_TRUE(version_->HasProcessToRun());
    124 
    125   // Re-associating the same version and provider_host should just work too.
    126   provider_host1_->SetWaitingVersion(version_);
    127   ASSERT_TRUE(version_->HasProcessToRun());
    128 
    129   // Resetting the provider_host's waiting version should remove process refs
    130   // from the version.
    131   provider_host1_->SetWaitingVersion(NULL);
    132   ASSERT_FALSE(version_->HasProcessToRun());
    133 }
    134 
    135 TEST_F(ServiceWorkerProviderHostTest,
    136        SetWaitingVersion_MultipleHostsForSameProcess) {
    137   ASSERT_FALSE(version_->HasProcessToRun());
    138 
    139   // Associating version_ to two providers as active version.
    140   provider_host1_->SetWaitingVersion(version_);
    141   provider_host2_->SetWaitingVersion(version_);
    142   ASSERT_TRUE(version_->HasProcessToRun());
    143 
    144   // Disassociating one provider_host shouldn't remove all process refs
    145   // from the version yet.
    146   provider_host1_->SetWaitingVersion(NULL);
    147   ASSERT_TRUE(version_->HasProcessToRun());
    148 
    149   // Disassociating the other provider_host will remove all process refs.
    150   provider_host2_->SetWaitingVersion(NULL);
    151   ASSERT_FALSE(version_->HasProcessToRun());
    152 }
    153 
    154 class ServiceWorkerProviderHostWaitingVersionTest : public testing::Test {
    155  protected:
    156   ServiceWorkerProviderHostWaitingVersionTest()
    157       : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
    158         next_provider_id_(1L) {}
    159   virtual ~ServiceWorkerProviderHostWaitingVersionTest() {}
    160 
    161   virtual void SetUp() OVERRIDE {
    162     context_.reset(
    163         new ServiceWorkerContextCore(base::FilePath(),
    164                                      base::MessageLoopProxy::current(),
    165                                      base::MessageLoopProxy::current(),
    166                                      NULL,
    167                                      NULL,
    168                                      NULL));
    169 
    170     // Prepare provider hosts (for the same process).
    171     provider_host1_ = CreateProviderHost(GURL("http://www.example.com/foo"));
    172     provider_host2_ = CreateProviderHost(GURL("http://www.example.com/bar"));
    173     provider_host3_ = CreateProviderHost(GURL("http://www.example.ca/foo"));
    174   }
    175 
    176   base::WeakPtr<ServiceWorkerProviderHost> CreateProviderHost(
    177       const GURL& document_url) {
    178     scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
    179         kRenderProcessId, next_provider_id_++, context_->AsWeakPtr(), NULL));
    180     host->SetDocumentUrl(document_url);
    181     base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
    182     context_->AddProviderHost(host.Pass());
    183     return provider_host;
    184   }
    185 
    186   virtual void TearDown() OVERRIDE {
    187     context_.reset();
    188   }
    189 
    190   content::TestBrowserThreadBundle thread_bundle_;
    191   scoped_ptr<ServiceWorkerContextCore> context_;
    192   base::WeakPtr<ServiceWorkerProviderHost> provider_host1_;
    193   base::WeakPtr<ServiceWorkerProviderHost> provider_host2_;
    194   base::WeakPtr<ServiceWorkerProviderHost> provider_host3_;
    195 
    196  private:
    197   int64 next_provider_id_;
    198 
    199   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostWaitingVersionTest);
    200 };
    201 
    202 TEST_F(ServiceWorkerProviderHostWaitingVersionTest,
    203        AssociateWaitingVersionToDocuments) {
    204   const GURL scope1("http://www.example.com/*");
    205   const GURL script_url1("http://www.example.com/service_worker1.js");
    206   scoped_refptr<ServiceWorkerRegistration> registration1(
    207       new ServiceWorkerRegistration(
    208           scope1, script_url1, 1L, context_->AsWeakPtr()));
    209   scoped_refptr<ServiceWorkerVersion> version1(
    210       new ServiceWorkerVersion(registration1, 1L, context_->AsWeakPtr()));
    211 
    212   ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
    213       context_->AsWeakPtr(), version1.get());
    214   EXPECT_EQ(version1.get(), provider_host1_->waiting_version());
    215   EXPECT_EQ(version1.get(), provider_host2_->waiting_version());
    216   EXPECT_EQ(NULL, provider_host3_->waiting_version());
    217 
    218   // Version2 is associated with the same registration as version1, so the
    219   // waiting version of host1 and host2 should be replaced.
    220   scoped_refptr<ServiceWorkerVersion> version2(
    221       new ServiceWorkerVersion(registration1, 2L, context_->AsWeakPtr()));
    222   ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
    223       context_->AsWeakPtr(), version2.get());
    224   EXPECT_EQ(version2.get(), provider_host1_->waiting_version());
    225   EXPECT_EQ(version2.get(), provider_host2_->waiting_version());
    226   EXPECT_EQ(NULL, provider_host3_->waiting_version());
    227 
    228   const GURL scope3(provider_host1_->document_url());
    229   const GURL script_url3("http://www.example.com/service_worker3.js");
    230   scoped_refptr<ServiceWorkerRegistration> registration3(
    231       new ServiceWorkerRegistration(
    232           scope3, script_url3, 3L, context_->AsWeakPtr()));
    233   scoped_refptr<ServiceWorkerVersion> version3(
    234       new ServiceWorkerVersion(registration3, 3L, context_->AsWeakPtr()));
    235 
    236   // Although version3 can match longer than version2 for host1, it should be
    237   // ignored because version3 is associated with a different registration from
    238   // version2.
    239   ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
    240       context_->AsWeakPtr(), version3.get());
    241   EXPECT_EQ(version2.get(), provider_host1_->waiting_version());
    242   EXPECT_EQ(version2.get(), provider_host2_->waiting_version());
    243   EXPECT_EQ(NULL, provider_host3_->waiting_version());
    244 }
    245 
    246 TEST_F(ServiceWorkerProviderHostWaitingVersionTest,
    247        DisassociateWaitingVersionFromDocuments) {
    248   const GURL scope1("http://www.example.com/*");
    249   const GURL script_url1("http://www.example.com/service_worker.js");
    250   scoped_refptr<ServiceWorkerRegistration> registration1(
    251       new ServiceWorkerRegistration(
    252           scope1, script_url1, 1L, context_->AsWeakPtr()));
    253   scoped_refptr<ServiceWorkerVersion> version1(
    254       new ServiceWorkerVersion(registration1, 1L, context_->AsWeakPtr()));
    255 
    256   const GURL scope2("http://www.example.ca/*");
    257   const GURL script_url2("http://www.example.ca/service_worker.js");
    258   scoped_refptr<ServiceWorkerRegistration> registration2(
    259       new ServiceWorkerRegistration(
    260           scope2, script_url2, 2L, context_->AsWeakPtr()));
    261   scoped_refptr<ServiceWorkerVersion> version2(
    262       new ServiceWorkerVersion(registration2, 2L, context_->AsWeakPtr()));
    263 
    264   ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
    265       context_->AsWeakPtr(), version1.get());
    266   ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
    267       context_->AsWeakPtr(), version2.get());
    268 
    269   // Host1 and host2 are associated with version1 as a waiting version, whereas
    270   // host3 is associated with version2.
    271   EXPECT_EQ(version1.get(), provider_host1_->waiting_version());
    272   EXPECT_EQ(version1.get(), provider_host2_->waiting_version());
    273   EXPECT_EQ(version2.get(), provider_host3_->waiting_version());
    274 
    275   // Disassociate version1 from host1 and host2.
    276   ServiceWorkerRegisterJob::DisassociateWaitingVersionFromDocuments(
    277       context_->AsWeakPtr(), version1->version_id());
    278   EXPECT_EQ(NULL, provider_host1_->waiting_version());
    279   EXPECT_EQ(NULL, provider_host2_->waiting_version());
    280   EXPECT_EQ(version2.get(), provider_host3_->waiting_version());
    281 }
    282 
    283 }  // namespace content
    284