summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.cc
blob: 20080f5a5c61fe9f64ccc1395c8ad4f75c7b3159 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.h"

#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/request.h"
#include "third_party/blink/renderer/core/fetch/response.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event_init.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetch.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_ui_options.h"
#include "third_party/blink/renderer/modules/event_modules_names.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"

namespace blink {

BackgroundFetchUpdateUIEvent::BackgroundFetchUpdateUIEvent(
    const AtomicString& type,
    const BackgroundFetchEventInit& initializer)
    : BackgroundFetchEvent(type, initializer, nullptr /* observer */) {}

BackgroundFetchUpdateUIEvent::BackgroundFetchUpdateUIEvent(
    const AtomicString& type,
    const BackgroundFetchEventInit& initializer,
    WaitUntilObserver* observer,
    ServiceWorkerRegistration* registration)
    : BackgroundFetchEvent(type, initializer, observer),
      service_worker_registration_(registration) {}

BackgroundFetchUpdateUIEvent::~BackgroundFetchUpdateUIEvent() = default;

void BackgroundFetchUpdateUIEvent::Trace(blink::Visitor* visitor) {
  visitor->Trace(service_worker_registration_);
  visitor->Trace(loader_);
  BackgroundFetchEvent::Trace(visitor);
}

ScriptPromise BackgroundFetchUpdateUIEvent::updateUI(
    ScriptState* script_state,
    const BackgroundFetchUIOptions& ui_options) {
  if (update_ui_called_) {
    // Return a rejected promise as this method should only be called once.
    return ScriptPromise::Reject(
        script_state,
        V8ThrowException::CreateTypeError(script_state->GetIsolate(),
                                          "updateUI may only be called once."));
  }

  update_ui_called_ = true;

  if (!service_worker_registration_) {
    // Return a Promise that will never settle when a developer calls this
    // method on a BackgroundFetchSuccessEvent instance they created themselves.
    // TODO(crbug.com/872768): Figure out if this is the right thing to do
    // vs reacting eagerly.
    return ScriptPromise();
  }
  DCHECK(!registration_->unique_id().IsEmpty());

  if (!ui_options.hasTitle() && ui_options.icons().IsEmpty()) {
    // Nothing to update, just return a resolved promise.
    return ScriptPromise::CastUndefined(script_state);
  }

  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  if (ui_options.icons().IsEmpty()) {
    DidGetIcon(resolver, ui_options.title(), SkBitmap());
  } else {
    DCHECK(!loader_);
    loader_ = new BackgroundFetchIconLoader();
    DCHECK(loader_);
    loader_->Start(BackgroundFetchBridge::From(service_worker_registration_),
                   ExecutionContext::From(script_state), ui_options.icons(),
                   WTF::Bind(&BackgroundFetchUpdateUIEvent::DidGetIcon,
                             WrapPersistent(this), WrapPersistent(resolver),
                             ui_options.title()));
  }

  return promise;
}

void BackgroundFetchUpdateUIEvent::DidGetIcon(ScriptPromiseResolver* resolver,
                                              const String& title,
                                              const SkBitmap& icon) {
  BackgroundFetchBridge::From(service_worker_registration_)
      ->UpdateUI(registration_->id(), registration_->unique_id(), title, icon,
                 WTF::Bind(&BackgroundFetchUpdateUIEvent::DidUpdateUI,
                           WrapPersistent(this), WrapPersistent(resolver)));
}

void BackgroundFetchUpdateUIEvent::DidUpdateUI(
    ScriptPromiseResolver* resolver,
    mojom::blink::BackgroundFetchError error) {
  switch (error) {
    case mojom::blink::BackgroundFetchError::NONE:
    case mojom::blink::BackgroundFetchError::INVALID_ID:
      resolver->Resolve();
      return;
    case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
      resolver->Reject(
          DOMException::Create(DOMExceptionCode::kAbortError,
                               "Failed to update UI due to I/O error."));
      return;
    case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
    case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
    case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
    case mojom::blink::BackgroundFetchError::PERMISSION_DENIED:
    case mojom::blink::BackgroundFetchError::QUOTA_EXCEEDED:
      // Not applicable for this callback.
      break;
  }

  NOTREACHED();
}

}  // namespace blink