Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/permission/Permissions.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
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "mozilla/dom/Permissions.h"
8
9
#include "mozilla/dom/ContentChild.h"
10
#include "mozilla/dom/PermissionsBinding.h"
11
#include "mozilla/dom/Promise.h"
12
#include "mozilla/Services.h"
13
#include "nsIPermissionManager.h"
14
#include "PermissionUtils.h"
15
16
namespace mozilla {
17
namespace dom {
18
19
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Permissions)
20
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
21
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
22
0
NS_INTERFACE_MAP_END
23
24
NS_IMPL_CYCLE_COLLECTING_ADDREF(Permissions)
25
NS_IMPL_CYCLE_COLLECTING_RELEASE(Permissions)
26
27
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Permissions, mWindow)
28
29
Permissions::Permissions(nsPIDOMWindowInner* aWindow)
30
  : mWindow(aWindow)
31
0
{
32
0
}
33
34
Permissions::~Permissions()
35
0
{
36
0
}
37
38
JSObject*
39
Permissions::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
40
0
{
41
0
  return Permissions_Binding::Wrap(aCx, this, aGivenProto);
42
0
}
43
44
namespace {
45
46
already_AddRefed<PermissionStatus>
47
CreatePermissionStatus(JSContext* aCx,
48
                       JS::Handle<JSObject*> aPermission,
49
                       nsPIDOMWindowInner* aWindow,
50
                       ErrorResult& aRv)
51
0
{
52
0
  PermissionDescriptor permission;
53
0
  JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission));
54
0
  if (NS_WARN_IF(!permission.Init(aCx, value))) {
55
0
    aRv.NoteJSContextException(aCx);
56
0
    return nullptr;
57
0
  }
58
0
59
0
  switch (permission.mName) {
60
0
    case PermissionName::Geolocation:
61
0
    case PermissionName::Notifications:
62
0
    case PermissionName::Push:
63
0
    case PermissionName::Persistent_storage:
64
0
      return PermissionStatus::Create(aWindow, permission.mName, aRv);
65
0
66
0
    default:
67
0
      MOZ_ASSERT_UNREACHABLE("Unhandled type");
68
0
      aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
69
0
      return nullptr;
70
0
  }
71
0
}
72
73
} // namespace
74
75
already_AddRefed<Promise>
76
Permissions::Query(JSContext* aCx,
77
                   JS::Handle<JSObject*> aPermission,
78
                   ErrorResult& aRv)
79
0
{
80
0
  if (!mWindow) {
81
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
82
0
    return nullptr;
83
0
  }
84
0
85
0
  RefPtr<PermissionStatus> status =
86
0
    CreatePermissionStatus(aCx, aPermission, mWindow, aRv);
87
0
  if (NS_WARN_IF(aRv.Failed())) {
88
0
    MOZ_ASSERT(!status);
89
0
    return nullptr;
90
0
  }
91
0
92
0
  MOZ_ASSERT(status);
93
0
  RefPtr<Promise> promise = Promise::Create(mWindow->AsGlobal(), aRv);
94
0
  if (NS_WARN_IF(aRv.Failed())) {
95
0
    return nullptr;
96
0
  }
97
0
98
0
  promise->MaybeResolve(status);
99
0
  return promise.forget();
100
0
}
101
102
/* static */ nsresult
103
Permissions::RemovePermission(nsIPrincipal* aPrincipal, const char* aPermissionType)
104
0
{
105
0
  MOZ_ASSERT(XRE_IsParentProcess());
106
0
107
0
  nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
108
0
  if (NS_WARN_IF(!permMgr)) {
109
0
    return NS_ERROR_FAILURE;
110
0
  }
111
0
112
0
  return permMgr->RemoveFromPrincipal(aPrincipal, aPermissionType);
113
0
}
114
115
already_AddRefed<Promise>
116
Permissions::Revoke(JSContext* aCx,
117
                    JS::Handle<JSObject*> aPermission,
118
                    ErrorResult& aRv)
119
0
{
120
0
  if (!mWindow) {
121
0
    aRv.Throw(NS_ERROR_UNEXPECTED);
122
0
    return nullptr;
123
0
  }
124
0
125
0
  PermissionDescriptor permission;
126
0
  JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission));
127
0
  if (NS_WARN_IF(!permission.Init(aCx, value))) {
128
0
    aRv.NoteJSContextException(aCx);
129
0
    return nullptr;
130
0
  }
131
0
132
0
  RefPtr<Promise> promise = Promise::Create(mWindow->AsGlobal(), aRv);
133
0
  if (NS_WARN_IF(aRv.Failed())) {
134
0
    return nullptr;
135
0
  }
136
0
137
0
  nsCOMPtr<nsIDocument> document = mWindow->GetExtantDoc();
138
0
  if (!document) {
139
0
    promise->MaybeReject(NS_ERROR_UNEXPECTED);
140
0
    return promise.forget();
141
0
  }
142
0
143
0
  nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
144
0
  if (NS_WARN_IF(!permMgr)) {
145
0
    promise->MaybeReject(NS_ERROR_FAILURE);
146
0
    return promise.forget();
147
0
  }
148
0
149
0
  const char* permissionType = PermissionNameToType(permission.mName);
150
0
151
0
  nsresult rv;
152
0
  if (XRE_IsParentProcess()) {
153
0
    rv = RemovePermission(document->NodePrincipal(), permissionType);
154
0
  } else {
155
0
    // Permissions can't be removed from the content process. Send a message
156
0
    // to the parent; `ContentParent::RecvRemovePermission` will call
157
0
    // `RemovePermission`.
158
0
    ContentChild::GetSingleton()->SendRemovePermission(
159
0
      IPC::Principal(document->NodePrincipal()), nsDependentCString(permissionType), &rv);
160
0
  }
161
0
162
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
163
0
    promise->MaybeReject(rv);
164
0
    return promise.forget();
165
0
  }
166
0
167
0
  RefPtr<PermissionStatus> status =
168
0
    CreatePermissionStatus(aCx, aPermission, mWindow, aRv);
169
0
  if (NS_WARN_IF(aRv.Failed())) {
170
0
    MOZ_ASSERT(!status);
171
0
    return nullptr;
172
0
  }
173
0
174
0
  MOZ_ASSERT(status);
175
0
  promise->MaybeResolve(status);
176
0
  return promise.forget();
177
0
}
178
179
} // namespace dom
180
} // namespace mozilla