summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
blob: c3a49868a4aafff59453b189169f2940c50c885b (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
125
126
127
128
129
// Copyright 2015 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/app_banner/before_install_prompt_event.h"

#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/app_banner/before_install_prompt_event_init.h"

namespace blink {

BeforeInstallPromptEvent::BeforeInstallPromptEvent(
    const AtomicString& name,
    LocalFrame& frame,
    mojom::blink::AppBannerServicePtr service_ptr,
    mojom::blink::AppBannerEventRequest event_request,
    const Vector<String>& platforms)
    : Event(name, Bubbles::kNo, Cancelable::kYes),
      ContextClient(&frame),
      banner_service_(std::move(service_ptr)),
      binding_(this, std::move(event_request)),
      platforms_(platforms),
      user_choice_(new UserChoiceProperty(frame.GetDocument(),
                                          this,
                                          UserChoiceProperty::kUserChoice)),
      prompt_called_(false) {
  DCHECK(banner_service_);
  DCHECK(binding_.is_bound());
  UseCounter::Count(&frame, WebFeature::kBeforeInstallPromptEvent);
}

BeforeInstallPromptEvent::BeforeInstallPromptEvent(
    ExecutionContext* execution_context,
    const AtomicString& name,
    const BeforeInstallPromptEventInit& init)
    : Event(name, init),
      ContextClient(execution_context),
      binding_(this),
      prompt_called_(false) {
  if (init.hasPlatforms())
    platforms_ = init.platforms();
}

BeforeInstallPromptEvent::~BeforeInstallPromptEvent() = default;

void BeforeInstallPromptEvent::Dispose() {
  banner_service_.reset();
  binding_.Close();
}

Vector<String> BeforeInstallPromptEvent::platforms() const {
  return platforms_;
}

ScriptPromise BeforeInstallPromptEvent::userChoice(ScriptState* script_state) {
  UseCounter::Count(ExecutionContext::From(script_state),
                    WebFeature::kBeforeInstallPromptEventUserChoice);
  // |m_binding| must be bound to allow the AppBannerService to resolve the
  // userChoice promise.
  if (user_choice_ && binding_.is_bound())
    return user_choice_->Promise(script_state->World());
  return ScriptPromise::RejectWithDOMException(
      script_state,
      DOMException::Create(kInvalidStateError,
                           "userChoice cannot be accessed on this event."));
}

ScriptPromise BeforeInstallPromptEvent::prompt(ScriptState* script_state) {
  // |m_bannerService| must be bound to allow us to inform the AppBannerService
  // to display the banner now.
  if (prompt_called_ || !banner_service_.is_bound()) {
    return ScriptPromise::RejectWithDOMException(
        script_state,
        DOMException::Create(kInvalidStateError,
                             "The prompt() method may only be called once."));
  }

  ExecutionContext* context = ExecutionContext::From(script_state);
  UseCounter::Count(context, WebFeature::kBeforeInstallPromptEventPrompt);

  Document* doc = ToDocumentOrNull(context);
  prompt_called_ = true;
  banner_service_->DisplayAppBanner(
      Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr));
  return ScriptPromise::CastUndefined(script_state);
}

const AtomicString& BeforeInstallPromptEvent::InterfaceName() const {
  return EventNames::BeforeInstallPromptEvent;
}

void BeforeInstallPromptEvent::preventDefault() {
  Event::preventDefault();
  if (target()) {
    UseCounter::Count(target()->GetExecutionContext(),
                      WebFeature::kBeforeInstallPromptEventPreventDefault);
  }
}

bool BeforeInstallPromptEvent::HasPendingActivity() const {
  return user_choice_ &&
         user_choice_->GetState() == ScriptPromisePropertyBase::kPending;
}

void BeforeInstallPromptEvent::BannerAccepted(const String& platform) {
  AppBannerPromptResult result;
  result.setPlatform(platform);
  result.setOutcome("accepted");
  user_choice_->Resolve(result);
}

void BeforeInstallPromptEvent::BannerDismissed() {
  AppBannerPromptResult result;
  result.setPlatform(g_empty_atom);
  result.setOutcome("dismissed");
  user_choice_->Resolve(result);
}

void BeforeInstallPromptEvent::Trace(blink::Visitor* visitor) {
  visitor->Trace(user_choice_);
  Event::Trace(visitor);
  ContextClient::Trace(visitor);
}

}  // namespace blink