summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
blob: 9d993b04db85107fd8747b2532c033de0ff25ebc (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
// 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/wake_lock/wake_lock.h"

#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/abort_signal.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/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

namespace {

Document* GetDocument(ScriptState* script_state) {
  ExecutionContext* execution_context = ExecutionContext::From(script_state);
  return To<Document>(execution_context);
}

}  // namespace

// static
ScriptPromise WakeLock::request(ScriptState* script_state,
                                const String& type,
                                WakeLockRequestOptions* options) {
  // https://w3c.github.io/wake-lock/#request-static-method
  // We only support [Exposed=Window] for now.
  DCHECK(ExecutionContext::From(script_state)->IsDocument());

  // 2. Let document be the responsible document of the current settings object.
  auto* document = GetDocument(script_state);

  // 3. If the current global object is the DedicatedWorkerGlobalScope object:
  // 3.1. If the current global object's owner set is empty, reject promise with
  //      a "NotAllowedError" DOMException and return promise.
  // 3.2. If type is "screen", reject promise with a "NotAllowedError"
  //      DOMException, and return promise.

  // 4. Otherwise, if the current global object is the Window object:
  // 4.1. If the document's browsing context is null, reject promise with a
  //      "NotAllowedError" DOMException and return promise.
  if (!document) {
    return ScriptPromise::RejectWithDOMException(
        script_state, MakeGarbageCollected<DOMException>(
                          DOMExceptionCode::kNotAllowedError,
                          "The document has no associated browsing context"));
  }

  // 2.1. If document is not allowed to use the policy-controlled feature named
  //      "wake-lock", reject promise with a "NotAllowedError" DOMException and
  //      return promise.
  // 2.2. If the user agent denies the wake lock of this type for document,
  //      reject promise with a "NotAllowedError" DOMException and return
  //      promise.
  if (!document->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWakeLock,
                                  ReportOptions::kReportOnFailure)) {
    return ScriptPromise::RejectWithDOMException(
        script_state,
        MakeGarbageCollected<DOMException>(
            DOMExceptionCode::kNotAllowedError,
            "Access to WakeLock features is disallowed by feature policy"));
  }

  // 4.2. If document is not fully active, reject promise with a
  //      "NotAllowedError" DOMException, and return promise.
  if (!document->IsActive()) {
    return ScriptPromise::RejectWithDOMException(
        script_state,
        MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotAllowedError,
                                           "The document is not active"));
  }
  // 4.3. If type is "screen" and the Document of the top-level browsing context
  //      is hidden, reject promise with a "NotAllowedError" DOMException, and
  //      return promise.
  if (type == "screen" &&
      !(document->GetPage() && document->GetPage()->IsPageVisible())) {
    return ScriptPromise::RejectWithDOMException(
        script_state, MakeGarbageCollected<DOMException>(
                          DOMExceptionCode::kNotAllowedError,
                          "The requesting page is not visible"));
  }

  // 5. If options' signal member is present, then run the following steps:
  // 5.1. Let signal be options's signal member.
  // 5.2. If signal’s aborted flag is set, then reject promise with an
  //      "AbortError" DOMException and return promise.
  if (options->hasSignal() && options->signal()->aborted()) {
    return ScriptPromise::RejectWithDOMException(
        script_state,
        MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
  }

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();

  WakeLockType wake_lock_type = ToWakeLockType(type);
  WakeLockController& controller = WakeLockController::From(*document);

  // 5.3. Otherwise, add to signal:
  // 5.3.1. Run release a wake lock with promise and type.
  if (options->hasSignal()) {
    options->signal()->AddAlgorithm(WTF::Bind(
        &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
        wake_lock_type, WrapPersistent(resolver)));
  }

  // 6. Run the following steps in parallel, but abort when options' signal
  // member is present and its aborted flag is set:
  // [...]
  // 6.2. Let success be the result of awaiting acquire a wake lock with promise
  //      and type:
  // 6.2.1. If success is false then reject promise with a "NotAllowedError"
  //        DOMException, and abort these steps.
  controller.AcquireWakeLock(wake_lock_type, resolver);

  // 7. Return promise.
  return promise;
}

}  // namespace blink