Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 file,
5
* You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "PermissionRequestBase.h"
8
9
#include "MainThreadUtils.h"
10
#include "mozilla/Assertions.h"
11
#include "mozilla/Services.h"
12
#include "mozilla/dom/Element.h"
13
#include "nsIObserverService.h"
14
#include "nsIPrincipal.h"
15
#include "nsXULAppAPI.h"
16
17
namespace mozilla {
18
namespace dom {
19
namespace indexedDB {
20
21
using namespace mozilla::services;
22
23
namespace {
24
25
#define IDB_PREFIX "indexedDB"
26
#define TOPIC_PREFIX IDB_PREFIX "-permissions-"
27
28
const nsLiteralCString kPermissionString = NS_LITERAL_CSTRING(IDB_PREFIX);
29
30
const char kPermissionPromptTopic[] = TOPIC_PREFIX "prompt";
31
32
#ifdef DEBUG
33
const char kPermissionResponseTopic[] = TOPIC_PREFIX "response";
34
#endif
35
36
#undef TOPIC_PREFIX
37
#undef IDB_PREFIX
38
39
const uint32_t kPermissionDefault = nsIPermissionManager::UNKNOWN_ACTION;
40
41
void AssertSanity() {
42
MOZ_ASSERT(XRE_IsParentProcess());
43
MOZ_ASSERT(NS_IsMainThread());
44
}
45
46
} // namespace
47
48
PermissionRequestBase::PermissionRequestBase(Element* aOwnerElement,
49
nsIPrincipal* aPrincipal)
50
: mOwnerElement(aOwnerElement), mPrincipal(aPrincipal) {
51
AssertSanity();
52
MOZ_ASSERT(aOwnerElement);
53
MOZ_ASSERT(aPrincipal);
54
}
55
56
PermissionRequestBase::~PermissionRequestBase() { AssertSanity(); }
57
58
// static
59
nsresult PermissionRequestBase::GetCurrentPermission(
60
nsIPrincipal* aPrincipal, PermissionValue* aCurrentValue) {
61
AssertSanity();
62
MOZ_ASSERT(aPrincipal);
63
MOZ_ASSERT(aCurrentValue);
64
65
nsCOMPtr<nsIPermissionManager> permMan = GetPermissionManager();
66
if (NS_WARN_IF(!permMan)) {
67
return NS_ERROR_FAILURE;
68
}
69
70
uint32_t intPermission;
71
nsresult rv = permMan->TestExactPermissionFromPrincipal(
72
aPrincipal, kPermissionString, &intPermission);
73
if (NS_WARN_IF(NS_FAILED(rv))) {
74
return rv;
75
}
76
77
PermissionValue permission = PermissionValueForIntPermission(intPermission);
78
79
MOZ_ASSERT(permission == kPermissionAllowed ||
80
permission == kPermissionDenied ||
81
permission == kPermissionPrompt);
82
83
*aCurrentValue = permission;
84
return NS_OK;
85
}
86
87
// static
88
auto PermissionRequestBase::PermissionValueForIntPermission(
89
uint32_t aIntPermission) -> PermissionValue {
90
AssertSanity();
91
92
switch (aIntPermission) {
93
case kPermissionDefault:
94
return kPermissionPrompt;
95
case kPermissionAllowed:
96
return kPermissionAllowed;
97
case kPermissionDenied:
98
return kPermissionDenied;
99
default:
100
MOZ_CRASH("Bad permission!");
101
}
102
103
MOZ_CRASH("Should never get here!");
104
}
105
106
nsresult PermissionRequestBase::PromptIfNeeded(PermissionValue* aCurrentValue) {
107
AssertSanity();
108
MOZ_ASSERT(aCurrentValue);
109
MOZ_ASSERT(mPrincipal);
110
111
// Tricky, we want to release the window and principal in all cases except
112
// when we successfully prompt.
113
nsCOMPtr<Element> element;
114
mOwnerElement.swap(element);
115
116
nsCOMPtr<nsIPrincipal> principal;
117
mPrincipal.swap(principal);
118
119
PermissionValue currentValue;
120
nsresult rv = GetCurrentPermission(principal, &currentValue);
121
if (NS_WARN_IF(NS_FAILED(rv))) {
122
return rv;
123
}
124
125
MOZ_ASSERT(currentValue != kPermissionDefault);
126
127
if (currentValue == kPermissionPrompt) {
128
nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
129
if (NS_WARN_IF(!obsSvc)) {
130
return NS_ERROR_FAILURE;
131
}
132
133
// We're about to prompt so swap the members back.
134
element.swap(mOwnerElement);
135
principal.swap(mPrincipal);
136
137
rv = obsSvc->NotifyObservers(static_cast<nsIObserver*>(this),
138
kPermissionPromptTopic, nullptr);
139
if (NS_WARN_IF(NS_FAILED(rv))) {
140
// Finally release if we failed the prompt.
141
mOwnerElement = nullptr;
142
mPrincipal = nullptr;
143
return rv;
144
}
145
}
146
147
*aCurrentValue = currentValue;
148
return NS_OK;
149
}
150
151
void PermissionRequestBase::SetExplicitPermission(nsIPrincipal* aPrincipal,
152
uint32_t aIntPermission) {
153
AssertSanity();
154
MOZ_ASSERT(aPrincipal);
155
MOZ_ASSERT(aIntPermission == kPermissionAllowed ||
156
aIntPermission == kPermissionDenied);
157
158
nsCOMPtr<nsIPermissionManager> permMan = GetPermissionManager();
159
if (NS_WARN_IF(!permMan)) {
160
return;
161
}
162
163
nsresult rv =
164
permMan->AddFromPrincipal(aPrincipal, kPermissionString, aIntPermission,
165
nsIPermissionManager::EXPIRE_NEVER,
166
/* aExpireTime */ 0);
167
if (NS_WARN_IF(NS_FAILED(rv))) {
168
return;
169
}
170
}
171
172
NS_IMPL_ISUPPORTS(PermissionRequestBase, nsIObserver, nsIIDBPermissionsRequest)
173
174
NS_IMETHODIMP
175
PermissionRequestBase::GetBrowserElement(Element** aElement) {
176
AssertSanity();
177
*aElement = do_AddRef(mOwnerElement).take();
178
return NS_OK;
179
}
180
181
NS_IMETHODIMP
182
PermissionRequestBase::GetResponseObserver(nsIObserver** aObserver) {
183
AssertSanity();
184
*aObserver = do_AddRef(this).take();
185
return NS_OK;
186
}
187
188
NS_IMETHODIMP
189
PermissionRequestBase::Observe(nsISupports* aSubject, const char* aTopic,
190
const char16_t* aData) {
191
AssertSanity();
192
MOZ_ASSERT(!strcmp(aTopic, kPermissionResponseTopic));
193
MOZ_ASSERT(mOwnerElement);
194
MOZ_ASSERT(mPrincipal);
195
196
nsCOMPtr<Element> element;
197
element.swap(mOwnerElement);
198
199
nsCOMPtr<nsIPrincipal> principal;
200
mPrincipal.swap(principal);
201
202
nsresult rv;
203
uint32_t promptResult = nsDependentString(aData).ToInteger(&rv);
204
MOZ_ALWAYS_SUCCEEDS(rv);
205
206
// The UI prompt code will only return one of these three values. We have to
207
// transform it to our values.
208
MOZ_ASSERT(promptResult == kPermissionDefault ||
209
promptResult == kPermissionAllowed ||
210
promptResult == kPermissionDenied);
211
212
if (promptResult != kPermissionDefault) {
213
// Save explicitly allowed or denied permissions now.
214
SetExplicitPermission(principal, promptResult);
215
}
216
217
PermissionValue permission;
218
switch (promptResult) {
219
case kPermissionDefault:
220
permission = kPermissionPrompt;
221
break;
222
223
case kPermissionAllowed:
224
permission = kPermissionAllowed;
225
break;
226
227
case kPermissionDenied:
228
permission = kPermissionDenied;
229
break;
230
231
default:
232
MOZ_CRASH("Bad prompt result!");
233
}
234
235
OnPromptComplete(permission);
236
return NS_OK;
237
}
238
239
} // namespace indexedDB
240
} // namespace dom
241
} // namespace mozilla