1// Copyright 2013 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 "content/browser/service_worker/service_worker_registration.h"
6
7#include "base/files/scoped_temp_dir.h"
8#include "base/logging.h"
9#include "base/message_loop/message_loop.h"
10#include "base/run_loop.h"
11#include "base/thread_task_runner_handle.h"
12#include "content/browser/browser_thread_impl.h"
13#include "content/browser/service_worker/service_worker_context_core.h"
14#include "content/browser/service_worker/service_worker_registration_handle.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "url/gurl.h"
17
18namespace content {
19
20class ServiceWorkerRegistrationTest : public testing::Test {
21 public:
22  ServiceWorkerRegistrationTest()
23      : io_thread_(BrowserThread::IO, &message_loop_) {}
24
25  virtual void SetUp() OVERRIDE {
26    context_.reset(
27        new ServiceWorkerContextCore(base::FilePath(),
28                                     base::ThreadTaskRunnerHandle::Get(),
29                                     base::ThreadTaskRunnerHandle::Get(),
30                                     base::ThreadTaskRunnerHandle::Get(),
31                                     NULL,
32                                     NULL,
33                                     NULL));
34    context_ptr_ = context_->AsWeakPtr();
35  }
36
37  virtual void TearDown() OVERRIDE {
38    context_.reset();
39    base::RunLoop().RunUntilIdle();
40  }
41
42  class RegistrationListener : public ServiceWorkerRegistration::Listener {
43   public:
44    RegistrationListener() {}
45    ~RegistrationListener() {
46      if (observed_registration_.get())
47        observed_registration_->RemoveListener(this);
48    }
49
50    virtual void OnVersionAttributesChanged(
51        ServiceWorkerRegistration* registration,
52        ChangedVersionAttributesMask changed_mask,
53        const ServiceWorkerRegistrationInfo& info) OVERRIDE {
54      observed_registration_ = registration;
55      observed_changed_mask_ = changed_mask;
56      observed_info_ = info;
57    }
58
59    virtual void OnRegistrationFailed(
60        ServiceWorkerRegistration* registration) OVERRIDE {
61      NOTREACHED();
62    }
63
64    virtual void OnRegistrationFinishedUninstalling(
65        ServiceWorkerRegistration* registration) OVERRIDE {
66      NOTREACHED();
67    }
68
69    virtual void OnUpdateFound(
70        ServiceWorkerRegistration* registration) OVERRIDE {
71      NOTREACHED();
72    }
73
74    void Reset() {
75      observed_registration_ = NULL;
76      observed_changed_mask_ = ChangedVersionAttributesMask();
77      observed_info_ = ServiceWorkerRegistrationInfo();
78    }
79
80    scoped_refptr<ServiceWorkerRegistration> observed_registration_;
81    ChangedVersionAttributesMask observed_changed_mask_;
82    ServiceWorkerRegistrationInfo observed_info_;
83  };
84
85 protected:
86  scoped_ptr<ServiceWorkerContextCore> context_;
87  base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
88  base::MessageLoopForIO message_loop_;
89  BrowserThreadImpl io_thread_;
90};
91
92TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
93  const GURL kScope("http://www.example.not/");
94  const GURL kScript("http://www.example.not/service_worker.js");
95  int64 kRegistrationId = 1L;
96  scoped_refptr<ServiceWorkerRegistration> registration =
97      new ServiceWorkerRegistration(
98          kScope,
99          kRegistrationId,
100          context_ptr_);
101
102  const int64 version_1_id = 1L;
103  const int64 version_2_id = 2L;
104  scoped_refptr<ServiceWorkerVersion> version_1 = new ServiceWorkerVersion(
105      registration.get(), kScript, version_1_id, context_ptr_);
106  scoped_refptr<ServiceWorkerVersion> version_2 = new ServiceWorkerVersion(
107      registration.get(), kScript, version_2_id, context_ptr_);
108
109  RegistrationListener listener;
110  registration->AddListener(&listener);
111  registration->SetActiveVersion(version_1.get());
112
113  EXPECT_EQ(version_1.get(), registration->active_version());
114  EXPECT_EQ(registration, listener.observed_registration_);
115  EXPECT_EQ(ChangedVersionAttributesMask::ACTIVE_VERSION,
116            listener.observed_changed_mask_.changed());
117  EXPECT_EQ(kScope, listener.observed_info_.pattern);
118  EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
119  EXPECT_EQ(kScript, listener.observed_info_.active_version.script_url);
120  EXPECT_TRUE(listener.observed_info_.installing_version.is_null);
121  EXPECT_TRUE(listener.observed_info_.waiting_version.is_null);
122  EXPECT_TRUE(listener.observed_info_.controlling_version.is_null);
123  listener.Reset();
124
125  registration->SetInstallingVersion(version_2.get());
126
127  EXPECT_EQ(version_2.get(), registration->installing_version());
128  EXPECT_EQ(ChangedVersionAttributesMask::INSTALLING_VERSION,
129            listener.observed_changed_mask_.changed());
130  EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
131  EXPECT_EQ(version_2_id,
132            listener.observed_info_.installing_version.version_id);
133  EXPECT_TRUE(listener.observed_info_.waiting_version.is_null);
134  EXPECT_TRUE(listener.observed_info_.controlling_version.is_null);
135  listener.Reset();
136
137  registration->SetWaitingVersion(version_2.get());
138
139  EXPECT_EQ(version_2.get(), registration->waiting_version());
140  EXPECT_FALSE(registration->installing_version());
141  EXPECT_TRUE(listener.observed_changed_mask_.waiting_changed());
142  EXPECT_TRUE(listener.observed_changed_mask_.installing_changed());
143  EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
144  EXPECT_EQ(version_2_id, listener.observed_info_.waiting_version.version_id);
145  EXPECT_TRUE(listener.observed_info_.installing_version.is_null);
146  EXPECT_TRUE(listener.observed_info_.controlling_version.is_null);
147  listener.Reset();
148
149  registration->UnsetVersion(version_2.get());
150
151  EXPECT_FALSE(registration->waiting_version());
152  EXPECT_EQ(ChangedVersionAttributesMask::WAITING_VERSION,
153            listener.observed_changed_mask_.changed());
154  EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
155  EXPECT_TRUE(listener.observed_info_.waiting_version.is_null);
156  EXPECT_TRUE(listener.observed_info_.installing_version.is_null);
157  EXPECT_TRUE(listener.observed_info_.controlling_version.is_null);
158}
159
160TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
161  const GURL kScope("http://www.example.not/");
162  int64 kRegistrationId = 1L;
163  int kProviderId = 1;
164  scoped_refptr<ServiceWorkerRegistration> registration =
165      new ServiceWorkerRegistration(
166          kScope,
167          kRegistrationId,
168          context_ptr_);
169  scoped_ptr<ServiceWorkerRegistrationHandle> handle(
170      new ServiceWorkerRegistrationHandle(context_ptr_,
171                                          NULL,
172                                          kProviderId,
173                                          registration.get()));
174  registration->NotifyRegistrationFailed();
175  // Don't crash when handle gets destructed.
176}
177
178}  // namespace content
179