1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "StorageAccessPermissionRequest.h"
8 #include "nsGlobalWindowInner.h"
9 #include "mozilla/StaticPrefs_dom.h"
12 namespace mozilla::dom
{
14 NS_IMPL_CYCLE_COLLECTION_INHERITED(StorageAccessPermissionRequest
,
15 ContentPermissionRequestBase
)
17 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(StorageAccessPermissionRequest
,
18 ContentPermissionRequestBase
)
20 StorageAccessPermissionRequest::StorageAccessPermissionRequest(
21 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aNodePrincipal
,
22 const Maybe
<nsCString
>& aTopLevelBaseDomain
, AllowCallback
&& aAllowCallback
,
23 CancelCallback
&& aCancelCallback
)
24 : ContentPermissionRequestBase(aNodePrincipal
, aWindow
,
25 "dom.storage_access"_ns
,
27 mAllowCallback(std::move(aAllowCallback
)),
28 mCancelCallback(std::move(aCancelCallback
)),
29 mCallbackCalled(false) {
30 if (aTopLevelBaseDomain
.isSome()) {
31 mOptions
.AppendElement(NS_ConvertUTF8toUTF16(aTopLevelBaseDomain
.value()));
33 mPermissionRequests
.AppendElement(PermissionRequest(mType
, mOptions
));
37 StorageAccessPermissionRequest::Cancel() {
38 if (!mCallbackCalled
) {
39 mCallbackCalled
= true;
46 StorageAccessPermissionRequest::Allow(JS::Handle
<JS::Value
> aChoices
) {
47 nsTArray
<PermissionChoice
> choices
;
48 nsresult rv
= TranslateChoices(aChoices
, mPermissionRequests
, choices
);
53 // There is no support to allow grants automatically from the prompting code
56 if (!mCallbackCalled
) {
57 mCallbackCalled
= true;
58 if (choices
.Length() == 1 && choices
[0].choice().EqualsLiteral("allow")) {
66 StorageAccessPermissionRequest::GetTypes(nsIArray
** aTypes
) {
67 return nsContentPermissionUtils::CreatePermissionArray(mType
, mOptions
,
71 RefPtr
<StorageAccessPermissionRequest::AutoGrantDelayPromise
>
72 StorageAccessPermissionRequest::MaybeDelayAutomaticGrants() {
73 RefPtr
<AutoGrantDelayPromise::Private
> p
=
74 new AutoGrantDelayPromise::Private(__func__
);
76 unsigned simulatedDelay
= CalculateSimulatedDelay();
78 nsCOMPtr
<nsITimer
> timer
;
79 RefPtr
<AutoGrantDelayPromise::Private
> promise
= p
;
80 nsresult rv
= NS_NewTimerWithFuncCallback(
81 getter_AddRefs(timer
),
82 [](nsITimer
* aTimer
, void* aClosure
) -> void {
84 static_cast<AutoGrantDelayPromise::Private
*>(aClosure
);
85 promise
->Resolve(true, __func__
);
89 promise
, simulatedDelay
, nsITimer::TYPE_ONE_SHOT
,
90 "DelayedAllowAutoGrantCallback");
91 if (NS_WARN_IF(NS_FAILED(rv
))) {
92 p
->Reject(false, __func__
);
94 // Leak the references here! We'll release them inside the callback.
95 Unused
<< timer
.forget();
96 Unused
<< promise
.forget();
99 p
->Resolve(false, __func__
);
104 already_AddRefed
<StorageAccessPermissionRequest
>
105 StorageAccessPermissionRequest::Create(nsPIDOMWindowInner
* aWindow
,
106 AllowCallback
&& aAllowCallback
,
107 CancelCallback
&& aCancelCallback
) {
111 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(aWindow
);
113 return Create(aWindow
, win
->GetPrincipal(), std::move(aAllowCallback
),
114 std::move(aCancelCallback
));
117 already_AddRefed
<StorageAccessPermissionRequest
>
118 StorageAccessPermissionRequest::Create(nsPIDOMWindowInner
* aWindow
,
119 nsIPrincipal
* aPrincipal
,
120 AllowCallback
&& aAllowCallback
,
121 CancelCallback
&& aCancelCallback
) {
122 return Create(aWindow
, aPrincipal
, Nothing(), std::move(aAllowCallback
),
123 std::move(aCancelCallback
));
126 already_AddRefed
<StorageAccessPermissionRequest
>
127 StorageAccessPermissionRequest::Create(
128 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aPrincipal
,
129 const Maybe
<nsCString
>& aTopLevelBaseDomain
, AllowCallback
&& aAllowCallback
,
130 CancelCallback
&& aCancelCallback
) {
139 RefPtr
<StorageAccessPermissionRequest
> request
=
140 new StorageAccessPermissionRequest(
141 aWindow
, aPrincipal
, aTopLevelBaseDomain
, std::move(aAllowCallback
),
142 std::move(aCancelCallback
));
143 return request
.forget();
146 unsigned StorageAccessPermissionRequest::CalculateSimulatedDelay() {
147 if (!StaticPrefs::dom_storage_access_auto_grants_delayed()) {
151 // Generate a random time value that is at least 0 and and most 3 seconds.
152 std::srand(static_cast<unsigned>(PR_Now()));
154 const unsigned kMin
= 0;
155 const unsigned kMax
= 3000;
156 const unsigned random
= std::abs(std::rand());
158 return kMin
+ random
% (kMax
- kMin
);
161 } // namespace mozilla::dom