Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/permission/PermissionObserver.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 "PermissionObserver.h"
8
9
#include "mozilla/dom/PermissionStatus.h"
10
#include "mozilla/Services.h"
11
#include "mozilla/UniquePtr.h"
12
#include "nsIObserverService.h"
13
#include "nsIPermission.h"
14
#include "PermissionUtils.h"
15
16
namespace mozilla {
17
namespace dom {
18
19
namespace {
20
PermissionObserver* gInstance = nullptr;
21
} // namespace
22
23
NS_IMPL_ISUPPORTS(PermissionObserver,
24
                  nsIObserver,
25
                  nsISupportsWeakReference)
26
27
PermissionObserver::PermissionObserver()
28
0
{
29
0
  MOZ_ASSERT(!gInstance);
30
0
}
31
32
PermissionObserver::~PermissionObserver()
33
0
{
34
0
  MOZ_ASSERT(mSinks.IsEmpty());
35
0
  MOZ_ASSERT(gInstance == this);
36
0
37
0
  gInstance = nullptr;
38
0
}
39
40
/* static */ already_AddRefed<PermissionObserver>
41
PermissionObserver::GetInstance()
42
0
{
43
0
  RefPtr<PermissionObserver> instance = gInstance;
44
0
  if (!instance) {
45
0
    instance = new PermissionObserver();
46
0
47
0
    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
48
0
    if (NS_WARN_IF(!obs)) {
49
0
      return nullptr;
50
0
    }
51
0
52
0
    nsresult rv = obs->AddObserver(instance, "perm-changed", true);
53
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
54
0
      return nullptr;
55
0
    }
56
0
57
0
    gInstance = instance;
58
0
  }
59
0
60
0
  return instance.forget();
61
0
}
62
63
void
64
PermissionObserver::AddSink(PermissionStatus* aSink)
65
0
{
66
0
  MOZ_ASSERT(aSink);
67
0
  MOZ_ASSERT(!mSinks.Contains(aSink));
68
0
69
0
  mSinks.AppendElement(aSink);
70
0
}
71
72
void
73
PermissionObserver::RemoveSink(PermissionStatus* aSink)
74
0
{
75
0
  MOZ_ASSERT(aSink);
76
0
  MOZ_ASSERT(mSinks.Contains(aSink));
77
0
78
0
  mSinks.RemoveElement(aSink);
79
0
}
80
81
void
82
PermissionObserver::Notify(PermissionName aName, nsIPrincipal& aPrincipal)
83
0
{
84
0
  for (auto* sink : mSinks) {
85
0
    if (sink->mName != aName) {
86
0
      continue;
87
0
    }
88
0
89
0
    nsCOMPtr<nsIPrincipal> sinkPrincipal = sink->GetPrincipal();
90
0
    if (NS_WARN_IF(!sinkPrincipal) || !aPrincipal.Equals(sinkPrincipal)) {
91
0
      continue;
92
0
    }
93
0
94
0
    sink->PermissionChanged();
95
0
  }
96
0
}
97
98
NS_IMETHODIMP
99
PermissionObserver::Observe(nsISupports* aSubject,
100
                            const char* aTopic,
101
                            const char16_t* aData)
102
0
{
103
0
  MOZ_ASSERT(!strcmp(aTopic, "perm-changed"));
104
0
105
0
  if (mSinks.IsEmpty()) {
106
0
    return NS_OK;
107
0
  }
108
0
109
0
  nsCOMPtr<nsIPermission> perm = do_QueryInterface(aSubject);
110
0
  if (!perm) {
111
0
    return NS_OK;
112
0
  }
113
0
114
0
  nsCOMPtr<nsIPrincipal> principal;
115
0
  perm->GetPrincipal(getter_AddRefs(principal));
116
0
  if (!principal) {
117
0
    return NS_OK;
118
0
  }
119
0
120
0
  nsAutoCString type;
121
0
  perm->GetType(type);
122
0
  Maybe<PermissionName> permission = TypeToPermissionName(type.get());
123
0
  if (permission) {
124
0
    Notify(permission.value(), *principal);
125
0
  }
126
0
127
0
  return NS_OK;
128
0
}
129
130
} // namespace dom
131
} // namespace mozilla