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 "content/browser/service_worker/service_worker_fetch_dispatcher.h"
6
7#include "base/bind.h"
8#include "base/debug/trace_event.h"
9#include "content/browser/service_worker/service_worker_version.h"
10
11namespace content {
12
13ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
14    scoped_ptr<ServiceWorkerFetchRequest> request,
15    ServiceWorkerVersion* version,
16    const base::Closure& prepare_callback,
17    const FetchCallback& fetch_callback)
18    : version_(version),
19      prepare_callback_(prepare_callback),
20      fetch_callback_(fetch_callback),
21      request_(request.Pass()),
22      weak_factory_(this) {
23}
24
25ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {}
26
27void ServiceWorkerFetchDispatcher::Run() {
28  DCHECK(version_->status() == ServiceWorkerVersion::ACTIVATING ||
29         version_->status() == ServiceWorkerVersion::ACTIVATED)
30      << version_->status();
31
32  if (version_->status() == ServiceWorkerVersion::ACTIVATING) {
33    version_->RegisterStatusChangeCallback(
34        base::Bind(&ServiceWorkerFetchDispatcher::DidWaitActivation,
35                   weak_factory_.GetWeakPtr()));
36    return;
37  }
38  DispatchFetchEvent();
39}
40
41void ServiceWorkerFetchDispatcher::DidWaitActivation() {
42  if (version_->status() != ServiceWorkerVersion::ACTIVATED) {
43    DCHECK_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
44    DidFailActivation();
45    return;
46  }
47  DispatchFetchEvent();
48}
49
50void ServiceWorkerFetchDispatcher::DidFailActivation() {
51  // The previous activation seems to have failed, abort the step
52  // with activate error. (The error should be separately reported
53  // to the associated documents and association must be dropped
54  // at this point)
55  DidFinish(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED,
56            SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
57            ServiceWorkerResponse());
58}
59
60void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
61  TRACE_EVENT_ASYNC_BEGIN0(
62      "ServiceWorker",
63      "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
64      request_.get());
65  version_->DispatchFetchEvent(
66      *request_.get(),
67      base::Bind(&ServiceWorkerFetchDispatcher::DidPrepare,
68                 weak_factory_.GetWeakPtr()),
69      base::Bind(&ServiceWorkerFetchDispatcher::DidFinish,
70                 weak_factory_.GetWeakPtr()));
71}
72
73void ServiceWorkerFetchDispatcher::DidPrepare() {
74  DCHECK(!prepare_callback_.is_null());
75  base::Closure prepare_callback = prepare_callback_;
76  prepare_callback.Run();
77}
78
79void ServiceWorkerFetchDispatcher::DidFinish(
80    ServiceWorkerStatusCode status,
81    ServiceWorkerFetchEventResult fetch_result,
82    const ServiceWorkerResponse& response) {
83  TRACE_EVENT_ASYNC_END0(
84      "ServiceWorker",
85      "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
86      request_.get());
87  DCHECK(!fetch_callback_.is_null());
88  FetchCallback fetch_callback = fetch_callback_;
89  fetch_callback.Run(status, fetch_result, response);
90}
91
92}  // namespace content
93