f293237f780dfb87e9759bc9b155a0173e8ed379
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_register_job.cc
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_register_job.h"
6
7 #include <vector>
8
9 #include "content/browser/service_worker/service_worker_job_coordinator.h"
10 #include "content/browser/service_worker/service_worker_registration.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "url/gurl.h"
13
14 namespace content {
15
16 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
17     ServiceWorkerStorage* storage,
18     ServiceWorkerJobCoordinator* coordinator,
19     const GURL& pattern,
20     const GURL& script_url,
21     RegistrationType type)
22     : storage_(storage),
23       coordinator_(coordinator),
24       pattern_(pattern),
25       script_url_(script_url),
26       type_(type),
27       weak_factory_(this) {}
28
29 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {}
30
31 void ServiceWorkerRegisterJob::AddCallback(
32     const RegistrationCallback& callback) {
33   callbacks_.push_back(callback);
34 }
35
36 void ServiceWorkerRegisterJob::Start() {
37   if (type_ == REGISTER)
38     StartRegister();
39   else
40     StartUnregister();
41 }
42
43 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJob* job) {
44   return job->type_ == type_ &&
45          (type_ == ServiceWorkerRegisterJob::UNREGISTER ||
46           job->script_url_ == script_url_);
47 }
48
49 void ServiceWorkerRegisterJob::StartRegister() {
50   // Set up a chain of callbacks, in reverse order. Each of these
51   // callbacks may be called asynchronously by the previous callback.
52   RegistrationCallback finish_registration(base::Bind(
53       &ServiceWorkerRegisterJob::RegisterComplete, weak_factory_.GetWeakPtr()));
54
55   UnregistrationCallback register_new(
56       base::Bind(&ServiceWorkerRegisterJob::RegisterPatternAndContinue,
57                  weak_factory_.GetWeakPtr(),
58                  finish_registration));
59
60   ServiceWorkerStorage::FindRegistrationCallback unregister_old(
61       base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue,
62                  weak_factory_.GetWeakPtr(),
63                  register_new));
64
65   storage_->FindRegistrationForPattern(pattern_, unregister_old);
66 }
67
68 void ServiceWorkerRegisterJob::StartUnregister() {
69   // Set up a chain of callbacks, in reverse order. Each of these
70   // callbacks may be called asynchronously by the previous callback.
71   UnregistrationCallback finish_unregistration(
72       base::Bind(&ServiceWorkerRegisterJob::UnregisterComplete,
73                  weak_factory_.GetWeakPtr()));
74
75   ServiceWorkerStorage::FindRegistrationCallback unregister(
76       base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue,
77                  weak_factory_.GetWeakPtr(),
78                  finish_unregistration));
79
80   storage_->FindRegistrationForPattern(pattern_, unregister);
81 }
82
83 void ServiceWorkerRegisterJob::RegisterPatternAndContinue(
84     const RegistrationCallback& callback,
85     ServiceWorkerStatusCode previous_status) {
86   if (previous_status != SERVICE_WORKER_OK) {
87     BrowserThread::PostTask(
88         BrowserThread::IO,
89         FROM_HERE,
90         base::Bind(callback,
91                    previous_status,
92                    scoped_refptr<ServiceWorkerRegistration>()));
93     return;
94   }
95
96   // TODO: Eventually RegisterInternal will be replaced by an asynchronous
97   // operation. Pass its resulting status through 'callback'.
98   scoped_refptr<ServiceWorkerRegistration> registration =
99       storage_->RegisterInternal(pattern_, script_url_);
100   BrowserThread::PostTask(BrowserThread::IO,
101                           FROM_HERE,
102                           base::Bind(callback, SERVICE_WORKER_OK,
103                                      registration));
104 }
105
106 void ServiceWorkerRegisterJob::UnregisterPatternAndContinue(
107     const UnregistrationCallback& callback,
108     bool found,
109     ServiceWorkerStatusCode previous_status,
110     const scoped_refptr<ServiceWorkerRegistration>& previous_registration) {
111
112   // The previous registration may not exist, which is ok.
113   if (previous_status == SERVICE_WORKER_OK && found &&
114       (script_url_.is_empty() ||
115        previous_registration->script_url() != script_url_)) {
116     // TODO: Eventually UnregisterInternal will be replaced by an
117     // asynchronous operation. Pass its resulting status though
118     // 'callback'.
119     storage_->UnregisterInternal(pattern_);
120     DCHECK(previous_registration->is_shutdown());
121   }
122   BrowserThread::PostTask(
123       BrowserThread::IO, FROM_HERE, base::Bind(callback, previous_status));
124 }
125
126 void ServiceWorkerRegisterJob::RunCallbacks(
127     ServiceWorkerStatusCode status,
128     const scoped_refptr<ServiceWorkerRegistration>& registration) {
129   for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
130        it != callbacks_.end();
131        ++it) {
132     it->Run(status, registration);
133   }
134 }
135 void ServiceWorkerRegisterJob::RegisterComplete(
136     ServiceWorkerStatusCode status,
137     const scoped_refptr<ServiceWorkerRegistration>& registration) {
138   RunCallbacks(status, registration);
139   coordinator_->FinishJob(pattern_, this);
140 }
141
142 void ServiceWorkerRegisterJob::UnregisterComplete(
143     ServiceWorkerStatusCode status) {
144   RunCallbacks(status, NULL);
145   coordinator_->FinishJob(pattern_, this);
146 }
147
148 }  // namespace content