Coverage Report

Created: 2018-09-25 14:53

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