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
, bool aFrameOnly
,
23 AllowCallback
&& aAllowCallback
, 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 mOptions
.SetLength(2);
31 if (aTopLevelBaseDomain
.isSome()) {
32 nsCString option
= aTopLevelBaseDomain
.value();
33 mOptions
.ElementAt(0) = NS_ConvertUTF8toUTF16(option
);
36 mOptions
.ElementAt(1) = u
"1"_ns
;
38 mPermissionRequests
.AppendElement(PermissionRequest(mType
, mOptions
));
42 StorageAccessPermissionRequest::Cancel() {
43 if (!mCallbackCalled
) {
44 mCallbackCalled
= true;
51 StorageAccessPermissionRequest::Allow(JS::Handle
<JS::Value
> aChoices
) {
52 nsTArray
<PermissionChoice
> choices
;
53 nsresult rv
= TranslateChoices(aChoices
, mPermissionRequests
, choices
);
58 // There is no support to allow grants automatically from the prompting code
61 if (!mCallbackCalled
) {
62 mCallbackCalled
= true;
63 if (choices
.Length() == 1 && choices
[0].choice().EqualsLiteral("allow")) {
71 StorageAccessPermissionRequest::GetTypes(nsIArray
** aTypes
) {
72 return nsContentPermissionUtils::CreatePermissionArray(mType
, mOptions
,
76 RefPtr
<StorageAccessPermissionRequest::AutoGrantDelayPromise
>
77 StorageAccessPermissionRequest::MaybeDelayAutomaticGrants() {
78 RefPtr
<AutoGrantDelayPromise::Private
> p
=
79 new AutoGrantDelayPromise::Private(__func__
);
81 unsigned simulatedDelay
= CalculateSimulatedDelay();
83 nsCOMPtr
<nsITimer
> timer
;
84 RefPtr
<AutoGrantDelayPromise::Private
> promise
= p
;
85 nsresult rv
= NS_NewTimerWithFuncCallback(
86 getter_AddRefs(timer
),
87 [](nsITimer
* aTimer
, void* aClosure
) -> void {
89 static_cast<AutoGrantDelayPromise::Private
*>(aClosure
);
90 promise
->Resolve(true, __func__
);
94 promise
, simulatedDelay
, nsITimer::TYPE_ONE_SHOT
,
95 "DelayedAllowAutoGrantCallback");
96 if (NS_WARN_IF(NS_FAILED(rv
))) {
97 p
->Reject(false, __func__
);
99 // Leak the references here! We'll release them inside the callback.
100 Unused
<< timer
.forget();
101 Unused
<< promise
.forget();
104 p
->Resolve(false, __func__
);
109 already_AddRefed
<StorageAccessPermissionRequest
>
110 StorageAccessPermissionRequest::Create(nsPIDOMWindowInner
* aWindow
,
111 AllowCallback
&& aAllowCallback
,
112 CancelCallback
&& aCancelCallback
) {
116 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(aWindow
);
118 return Create(aWindow
, win
->GetPrincipal(), std::move(aAllowCallback
),
119 std::move(aCancelCallback
));
122 already_AddRefed
<StorageAccessPermissionRequest
>
123 StorageAccessPermissionRequest::Create(nsPIDOMWindowInner
* aWindow
,
124 nsIPrincipal
* aPrincipal
,
125 AllowCallback
&& aAllowCallback
,
126 CancelCallback
&& aCancelCallback
) {
127 return Create(aWindow
, aPrincipal
, Nothing(), true, std::move(aAllowCallback
),
128 std::move(aCancelCallback
));
131 already_AddRefed
<StorageAccessPermissionRequest
>
132 StorageAccessPermissionRequest::Create(
133 nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aPrincipal
,
134 const Maybe
<nsCString
>& aTopLevelBaseDomain
, bool aFrameOnly
,
135 AllowCallback
&& aAllowCallback
, CancelCallback
&& aCancelCallback
) {
144 RefPtr
<StorageAccessPermissionRequest
> request
=
145 new StorageAccessPermissionRequest(
146 aWindow
, aPrincipal
, aTopLevelBaseDomain
, aFrameOnly
,
147 std::move(aAllowCallback
), std::move(aCancelCallback
));
148 return request
.forget();
151 unsigned StorageAccessPermissionRequest::CalculateSimulatedDelay() {
152 if (!StaticPrefs::dom_storage_access_auto_grants_delayed()) {
156 // Generate a random time value that is at least 0 and and most 3 seconds.
157 std::srand(static_cast<unsigned>(PR_Now()));
159 const unsigned kMin
= 0;
160 const unsigned kMax
= 3000;
161 const unsigned random
= std::abs(std::rand());
163 return kMin
+ random
% (kMax
- kMin
);
166 } // namespace mozilla::dom