Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/extensions/ExtensionPolicyService.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*-  Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "mozilla/ExtensionPolicyService.h"
7
#include "mozilla/extensions/DocumentObserver.h"
8
#include "mozilla/extensions/WebExtensionContentScript.h"
9
#include "mozilla/extensions/WebExtensionPolicy.h"
10
11
#include "mozilla/ClearOnShutdown.h"
12
#include "mozilla/Preferences.h"
13
#include "mozilla/ResultExtensions.h"
14
#include "mozilla/Services.h"
15
#include "mozilla/SimpleEnumerator.h"
16
#include "mozilla/dom/ContentChild.h"
17
#include "mozilla/dom/ContentFrameMessageManager.h"
18
#include "mozilla/dom/ContentParent.h"
19
#include "mozilla/dom/Promise.h"
20
#include "mozilla/dom/Promise-inl.h"
21
#include "mozIExtensionProcessScript.h"
22
#include "nsEscape.h"
23
#include "nsGkAtoms.h"
24
#include "nsIChannel.h"
25
#include "nsIContentPolicy.h"
26
#include "nsIDocShell.h"
27
#include "nsIDocument.h"
28
#include "nsGlobalWindowOuter.h"
29
#include "nsILoadInfo.h"
30
#include "nsIXULRuntime.h"
31
#include "nsNetUtil.h"
32
#include "nsPIDOMWindow.h"
33
#include "nsXULAppAPI.h"
34
#include "nsQueryObject.h"
35
36
namespace mozilla {
37
38
using namespace extensions;
39
40
using dom::AutoJSAPI;
41
using dom::ContentFrameMessageManager;
42
using dom::Promise;
43
44
#define DEFAULT_BASE_CSP \
45
0
    "script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; " \
46
0
    "object-src 'self' https://* moz-extension: blob: filesystem:;"
47
48
#define DEFAULT_DEFAULT_CSP \
49
0
    "script-src 'self'; object-src 'self';"
50
51
52
#define OBS_TOPIC_PRELOAD_SCRIPT "web-extension-preload-content-script"
53
#define OBS_TOPIC_LOAD_SCRIPT "web-extension-load-content-script"
54
55
56
static mozIExtensionProcessScript&
57
ProcessScript()
58
0
{
59
0
  static nsCOMPtr<mozIExtensionProcessScript> sProcessScript;
60
0
61
0
  if (MOZ_UNLIKELY(!sProcessScript)) {
62
0
    sProcessScript = do_GetService("@mozilla.org/webextensions/extension-process-script;1");
63
0
    MOZ_RELEASE_ASSERT(sProcessScript);
64
0
    ClearOnShutdown(&sProcessScript);
65
0
  }
66
0
  return *sProcessScript;
67
0
}
68
69
/*****************************************************************************
70
 * ExtensionPolicyService
71
 *****************************************************************************/
72
73
/* static */ bool ExtensionPolicyService::sRemoteExtensions;
74
75
/* static */ ExtensionPolicyService&
76
ExtensionPolicyService::GetSingleton()
77
0
{
78
0
  static RefPtr<ExtensionPolicyService> sExtensionPolicyService;
79
0
80
0
  if (MOZ_UNLIKELY(!sExtensionPolicyService)) {
81
0
    sExtensionPolicyService = new ExtensionPolicyService();
82
0
    RegisterWeakMemoryReporter(sExtensionPolicyService);
83
0
    ClearOnShutdown(&sExtensionPolicyService);
84
0
  }
85
0
  return *sExtensionPolicyService.get();
86
0
}
87
88
ExtensionPolicyService::ExtensionPolicyService()
89
0
{
90
0
  mObs = services::GetObserverService();
91
0
  MOZ_RELEASE_ASSERT(mObs);
92
0
93
0
  Preferences::AddBoolVarCache(&sRemoteExtensions, "extensions.webextensions.remote", false);
94
0
95
0
  RegisterObservers();
96
0
}
97
98
ExtensionPolicyService::~ExtensionPolicyService()
99
0
{
100
0
  UnregisterWeakMemoryReporter(this);
101
0
}
102
103
bool
104
ExtensionPolicyService::UseRemoteExtensions() const
105
0
{
106
0
  return sRemoteExtensions && BrowserTabsRemoteAutostart();
107
0
}
108
109
bool
110
ExtensionPolicyService::IsExtensionProcess() const
111
0
{
112
0
  bool isRemote = UseRemoteExtensions();
113
0
114
0
  if (isRemote && XRE_IsContentProcess()) {
115
0
    auto& remoteType = dom::ContentChild::GetSingleton()->GetRemoteType();
116
0
    return remoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE);
117
0
  }
118
0
  return !isRemote && XRE_IsParentProcess();
119
0
}
120
121
122
WebExtensionPolicy*
123
ExtensionPolicyService::GetByURL(const URLInfo& aURL)
124
0
{
125
0
  if (aURL.Scheme() == nsGkAtoms::moz_extension) {
126
0
    return GetByHost(aURL.Host());
127
0
  }
128
0
  return nullptr;
129
0
}
130
131
void
132
ExtensionPolicyService::GetAll(nsTArray<RefPtr<WebExtensionPolicy>>& aResult)
133
0
{
134
0
  for (auto iter = mExtensions.Iter(); !iter.Done(); iter.Next()) {
135
0
    aResult.AppendElement(iter.Data());
136
0
  }
137
0
}
138
139
bool
140
ExtensionPolicyService::RegisterExtension(WebExtensionPolicy& aPolicy)
141
0
{
142
0
  bool ok = (!GetByID(aPolicy.Id()) &&
143
0
             !GetByHost(aPolicy.MozExtensionHostname()));
144
0
  MOZ_ASSERT(ok);
145
0
146
0
  if (!ok) {
147
0
    return false;
148
0
  }
149
0
150
0
  mExtensions.Put(aPolicy.Id(), &aPolicy);
151
0
  mExtensionHosts.Put(aPolicy.MozExtensionHostname(), &aPolicy);
152
0
  return true;
153
0
}
154
155
bool
156
ExtensionPolicyService::UnregisterExtension(WebExtensionPolicy& aPolicy)
157
0
{
158
0
  bool ok = (GetByID(aPolicy.Id()) == &aPolicy &&
159
0
             GetByHost(aPolicy.MozExtensionHostname()) == &aPolicy);
160
0
  MOZ_ASSERT(ok);
161
0
162
0
  if (!ok) {
163
0
    return false;
164
0
  }
165
0
166
0
  mExtensions.Remove(aPolicy.Id());
167
0
  mExtensionHosts.Remove(aPolicy.MozExtensionHostname());
168
0
  return true;
169
0
}
170
171
bool
172
ExtensionPolicyService::RegisterObserver(DocumentObserver& aObserver)
173
0
{
174
0
  if (mObservers.GetWeak(&aObserver)) {
175
0
    return false;
176
0
  }
177
0
178
0
  mObservers.Put(&aObserver, &aObserver);
179
0
  return true;
180
0
}
181
182
bool
183
ExtensionPolicyService::UnregisterObserver(DocumentObserver& aObserver)
184
0
{
185
0
  if (!mObservers.GetWeak(&aObserver)) {
186
0
    return false;
187
0
  }
188
0
189
0
  mObservers.Remove(&aObserver);
190
0
  return true;
191
0
}
192
193
194
void
195
ExtensionPolicyService::BaseCSP(nsAString& aBaseCSP) const
196
0
{
197
0
  nsresult rv;
198
0
199
0
  rv = Preferences::GetString("extensions.webextensions.base-content-security-policy", aBaseCSP);
200
0
  if (NS_FAILED(rv)) {
201
0
    aBaseCSP.AssignLiteral(DEFAULT_BASE_CSP);
202
0
  }
203
0
}
204
205
void
206
ExtensionPolicyService::DefaultCSP(nsAString& aDefaultCSP) const
207
0
{
208
0
  nsresult rv;
209
0
210
0
  rv = Preferences::GetString("extensions.webextensions.default-content-security-policy", aDefaultCSP);
211
0
  if (NS_FAILED(rv)) {
212
0
    aDefaultCSP.AssignLiteral(DEFAULT_DEFAULT_CSP);
213
0
  }
214
0
}
215
216
217
/*****************************************************************************
218
 * nsIMemoryReporter
219
 *****************************************************************************/
220
221
NS_IMETHODIMP
222
ExtensionPolicyService::CollectReports(nsIHandleReportCallback* aHandleReport,
223
                                       nsISupports* aData, bool aAnonymize)
224
0
{
225
0
  for (auto iter = mExtensions.Iter(); !iter.Done(); iter.Next()) {
226
0
    auto& ext = iter.Data();
227
0
228
0
    nsAtomCString id(ext->Id());
229
0
230
0
    NS_ConvertUTF16toUTF8 name(ext->Name());
231
0
    name.ReplaceSubstring("\"", "");
232
0
    name.ReplaceSubstring("\\", "");
233
0
234
0
    nsString url;
235
0
    MOZ_TRY_VAR(url, ext->GetURL(NS_LITERAL_STRING("")));
236
0
237
0
    nsPrintfCString desc("Extension(id=%s, name=\"%s\", baseURL=%s)",
238
0
                         id.get(), name.get(),
239
0
                         NS_ConvertUTF16toUTF8(url).get());
240
0
    desc.ReplaceChar('/', '\\');
241
0
242
0
    nsCString path("extensions/");
243
0
    path.Append(desc);
244
0
245
0
    aHandleReport->Callback(
246
0
      EmptyCString(), path,
247
0
      KIND_NONHEAP, UNITS_COUNT, 1,
248
0
      NS_LITERAL_CSTRING("WebExtensions that are active in this session"),
249
0
      aData);
250
0
  }
251
0
252
0
  return NS_OK;
253
0
}
254
255
256
/*****************************************************************************
257
 * Content script management
258
 *****************************************************************************/
259
260
void
261
ExtensionPolicyService::RegisterObservers()
262
0
{
263
0
  mObs->AddObserver(this, "content-document-global-created", false);
264
0
  mObs->AddObserver(this, "document-element-inserted", false);
265
0
  mObs->AddObserver(this, "tab-content-frameloader-created", false);
266
0
  if (XRE_IsContentProcess()) {
267
0
    mObs->AddObserver(this, "http-on-opening-request", false);
268
0
  }
269
0
}
270
271
void
272
ExtensionPolicyService::UnregisterObservers()
273
0
{
274
0
  mObs->RemoveObserver(this, "content-document-global-created");
275
0
  mObs->RemoveObserver(this, "document-element-inserted");
276
0
  mObs->RemoveObserver(this, "tab-content-frameloader-created");
277
0
  if (XRE_IsContentProcess()) {
278
0
    mObs->RemoveObserver(this, "http-on-opening-request");
279
0
  }
280
0
}
281
282
nsresult
283
ExtensionPolicyService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
284
0
{
285
0
  if (!strcmp(aTopic, "content-document-global-created")) {
286
0
    nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(aSubject);
287
0
    if (win) {
288
0
      CheckWindow(win);
289
0
    }
290
0
  } else if (!strcmp(aTopic, "document-element-inserted")) {
291
0
    nsCOMPtr<nsIDocument> doc = do_QueryInterface(aSubject);
292
0
    if (doc) {
293
0
      CheckDocument(doc);
294
0
    }
295
0
  } else if (!strcmp(aTopic, "http-on-opening-request")) {
296
0
    nsCOMPtr<nsIChannel> chan = do_QueryInterface(aSubject);
297
0
    if (chan) {
298
0
      CheckRequest(chan);
299
0
    }
300
0
  } else if (!strcmp(aTopic, "tab-content-frameloader-created")) {
301
0
    RefPtr<ContentFrameMessageManager> mm = do_QueryObject(aSubject);
302
0
    NS_ENSURE_TRUE(mm, NS_ERROR_UNEXPECTED);
303
0
304
0
    mMessageManagers.PutEntry(mm);
305
0
306
0
    mm->AddSystemEventListener(NS_LITERAL_STRING("unload"), this,
307
0
                               false, false);
308
0
  }
309
0
  return NS_OK;
310
0
}
311
312
nsresult
313
ExtensionPolicyService::HandleEvent(dom::Event* aEvent)
314
0
{
315
0
  RefPtr<ContentFrameMessageManager> mm = do_QueryObject(aEvent->GetTarget());
316
0
  MOZ_ASSERT(mm);
317
0
  if (mm) {
318
0
    mMessageManagers.RemoveEntry(mm);
319
0
  }
320
0
  return NS_OK;
321
0
}
322
323
nsresult
324
ForEachDocShell(nsIDocShell* aDocShell,
325
                const std::function<nsresult(nsIDocShell*)>& aCallback)
326
0
{
327
0
  nsCOMPtr<nsISimpleEnumerator> iter;
328
0
  MOZ_TRY(aDocShell->GetDocShellEnumerator(nsIDocShell::typeContent,
329
0
                                           nsIDocShell::ENUMERATE_FORWARDS,
330
0
                                           getter_AddRefs(iter)));
331
0
332
0
  for (auto& docShell : SimpleEnumerator<nsIDocShell>(iter)) {
333
0
    MOZ_TRY(aCallback(docShell));
334
0
  }
335
0
  return NS_OK;
336
0
}
337
338
339
already_AddRefed<Promise>
340
ExtensionPolicyService::ExecuteContentScript(nsPIDOMWindowInner* aWindow,
341
                                             WebExtensionContentScript& aScript)
342
0
{
343
0
  if (!aWindow->IsCurrentInnerWindow()) {
344
0
    return nullptr;
345
0
  }
346
0
347
0
  RefPtr<Promise> promise;
348
0
  ProcessScript().LoadContentScript(&aScript, aWindow, getter_AddRefs(promise));
349
0
  return promise.forget();
350
0
}
351
352
RefPtr<Promise>
353
ExtensionPolicyService::ExecuteContentScripts(JSContext* aCx, nsPIDOMWindowInner* aWindow,
354
                                              const nsTArray<RefPtr<WebExtensionContentScript>>& aScripts)
355
0
{
356
0
  AutoTArray<RefPtr<Promise>, 8> promises;
357
0
358
0
  for (auto& script : aScripts) {
359
0
    if (RefPtr<Promise> promise = ExecuteContentScript(aWindow, *script)) {
360
0
      promises.AppendElement(std::move(promise));
361
0
    }
362
0
  }
363
0
364
0
  RefPtr<Promise> promise = Promise::All(aCx, promises, IgnoreErrors());
365
0
  MOZ_RELEASE_ASSERT(promise);
366
0
  return promise;
367
0
}
368
369
nsresult
370
ExtensionPolicyService::InjectContentScripts(WebExtensionPolicy* aExtension)
371
0
{
372
0
  AutoJSAPI jsapi;
373
0
  MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
374
0
375
0
  for (auto iter = mMessageManagers.ConstIter(); !iter.Done(); iter.Next()) {
376
0
    ContentFrameMessageManager* mm = iter.Get()->GetKey();
377
0
378
0
    nsCOMPtr<nsIDocShell> docShell = mm->GetDocShell(IgnoreErrors());
379
0
    NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED);
380
0
381
0
    auto result = ForEachDocShell(docShell, [&](nsIDocShell* aDocShell) -> nsresult {
382
0
      nsCOMPtr<nsPIDOMWindowOuter> win = aDocShell->GetWindow();
383
0
      if (!win->GetDocumentURI()) {
384
0
        return NS_OK;
385
0
      }
386
0
      DocInfo docInfo(win);
387
0
388
0
      using RunAt = dom::ContentScriptRunAt;
389
0
      using Scripts = AutoTArray<RefPtr<WebExtensionContentScript>, 8>;
390
0
391
0
      constexpr uint8_t n = uint8_t(RunAt::EndGuard_);
392
0
      Scripts scripts[n];
393
0
394
0
      auto GetScripts = [&](RunAt aRunAt) -> Scripts&& {
395
0
        return std::move(scripts[uint8_t(aRunAt)]);
396
0
      };
397
0
398
0
      for (const auto& script : aExtension->ContentScripts()) {
399
0
        if (script->Matches(docInfo)) {
400
0
          GetScripts(script->RunAt()).AppendElement(script);
401
0
        }
402
0
      }
403
0
404
0
      nsCOMPtr<nsPIDOMWindowInner> inner = win->GetCurrentInnerWindow();
405
0
406
0
      MOZ_TRY(ExecuteContentScripts(jsapi.cx(), inner, GetScripts(RunAt::Document_start))
407
0
        ->ThenWithCycleCollectedArgs([](JSContext* aCx, JS::HandleValue aValue,
408
0
                                        ExtensionPolicyService* aSelf,
409
0
                                        nsPIDOMWindowInner* aInner,
410
0
                                        Scripts&& aScripts) {
411
0
          return aSelf->ExecuteContentScripts(aCx, aInner, aScripts).forget();
412
0
        },
413
0
        this, inner, GetScripts(RunAt::Document_end))
414
0
        .andThen([&](auto aPromise) {
415
0
          return aPromise->ThenWithCycleCollectedArgs([](JSContext* aCx,
416
0
                                                         JS::HandleValue aValue,
417
0
                                                         ExtensionPolicyService* aSelf,
418
0
                                                         nsPIDOMWindowInner* aInner,
419
0
                                                         Scripts&& aScripts) {
420
0
            return aSelf->ExecuteContentScripts(aCx, aInner, aScripts).forget();
421
0
          },
422
0
          this, inner, GetScripts(RunAt::Document_idle));
423
0
        }));
424
0
425
0
      return NS_OK;
426
0
    });
427
0
    MOZ_TRY(result);
428
0
  }
429
0
  return NS_OK;
430
0
}
431
432
// Checks a request for matching content scripts, and begins pre-loading them
433
// if necessary.
434
void
435
ExtensionPolicyService::CheckRequest(nsIChannel* aChannel)
436
0
{
437
0
  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
438
0
  if (!loadInfo) {
439
0
    return;
440
0
  }
441
0
442
0
  auto loadType = loadInfo->GetExternalContentPolicyType();
443
0
  if (loadType != nsIContentPolicy::TYPE_DOCUMENT &&
444
0
      loadType != nsIContentPolicy::TYPE_SUBDOCUMENT) {
445
0
    return;
446
0
  }
447
0
448
0
  nsCOMPtr<nsIURI> uri;
449
0
  if (NS_FAILED(aChannel->GetURI(getter_AddRefs(uri)))) {
450
0
    return;
451
0
  }
452
0
453
0
  CheckContentScripts({uri.get(), loadInfo}, true);
454
0
}
455
456
static bool
457
CheckParentFrames(nsPIDOMWindowOuter* aWindow, WebExtensionPolicy& aPolicy)
458
0
{
459
0
  nsCOMPtr<nsIURI> aboutAddons;
460
0
  if (NS_FAILED(NS_NewURI(getter_AddRefs(aboutAddons), "about:addons"))) {
461
0
    return false;
462
0
  }
463
0
464
0
  auto* piWin = aWindow;
465
0
  while ((piWin = piWin->GetScriptableParentOrNull())) {
466
0
    auto* win = nsGlobalWindowOuter::Cast(piWin);
467
0
468
0
    auto* principal = BasePrincipal::Cast(win->GetPrincipal());
469
0
    if (nsContentUtils::IsSystemPrincipal(principal)) {
470
0
      // The add-on manager is a special case, since it contains extension
471
0
      // options pages in same-type <browser> frames.
472
0
      bool equals;
473
0
      if (NS_SUCCEEDED(win->GetDocumentURI()->Equals(aboutAddons, &equals)) &&
474
0
          equals) {
475
0
        return true;
476
0
      }
477
0
    }
478
0
479
0
    if (principal->AddonPolicy() != &aPolicy) {
480
0
      return false;
481
0
    }
482
0
  }
483
0
484
0
  return true;
485
0
}
486
487
// Checks a document, just after the document element has been inserted, for
488
// matching content scripts or extension principals, and loads them if
489
// necessary.
490
void
491
ExtensionPolicyService::CheckDocument(nsIDocument* aDocument)
492
0
{
493
0
  nsCOMPtr<nsPIDOMWindowOuter> win = aDocument->GetWindow();
494
0
  if (win) {
495
0
    nsIDocShell* docShell = win->GetDocShell();
496
0
    RefPtr<ContentFrameMessageManager> mm = docShell->GetMessageManager();
497
0
    if (!mm || !mMessageManagers.Contains(mm)) {
498
0
      return;
499
0
    }
500
0
501
0
    if (win->GetDocumentURI()) {
502
0
      CheckContentScripts(win.get(), false);
503
0
    }
504
0
505
0
    nsIPrincipal* principal = aDocument->NodePrincipal();
506
0
507
0
    RefPtr<WebExtensionPolicy> policy = BasePrincipal::Cast(principal)->AddonPolicy();
508
0
    if (policy) {
509
0
      bool privileged = IsExtensionProcess() && CheckParentFrames(win, *policy);
510
0
511
0
      ProcessScript().InitExtensionDocument(policy, aDocument, privileged);
512
0
    }
513
0
  }
514
0
}
515
516
// Checks for loads of about:blank into new window globals, and loads any
517
// matching content scripts. about:blank loads do not trigger document element
518
// inserted events, so they're the only load type that are special cased this
519
// way.
520
void
521
ExtensionPolicyService::CheckWindow(nsPIDOMWindowOuter* aWindow)
522
0
{
523
0
  // We only care about non-initial document loads here. The initial
524
0
  // about:blank document will usually be re-used to load another document.
525
0
  nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
526
0
  if (!doc || doc->IsInitialDocument() ||
527
0
      doc->GetReadyStateEnum() == nsIDocument::READYSTATE_UNINITIALIZED) {
528
0
    return;
529
0
  }
530
0
531
0
  nsCOMPtr<nsIURI> docUri = doc->GetDocumentURI();
532
0
  nsCOMPtr<nsIURI> uri;
533
0
  if (!docUri || NS_FAILED(NS_GetURIWithoutRef(docUri, getter_AddRefs(uri))) ||
534
0
      !NS_IsAboutBlank(uri)) {
535
0
    return;
536
0
  }
537
0
538
0
  nsIDocShell* docShell = aWindow->GetDocShell();
539
0
  if (RefPtr<ContentFrameMessageManager> mm = docShell->GetMessageManager()) {
540
0
    if (mMessageManagers.Contains(mm)) {
541
0
      CheckContentScripts(aWindow, false);
542
0
    }
543
0
  }
544
0
}
545
546
void
547
ExtensionPolicyService::CheckContentScripts(const DocInfo& aDocInfo, bool aIsPreload)
548
0
{
549
0
  nsCOMPtr<nsPIDOMWindowInner> win;
550
0
  if (!aIsPreload) {
551
0
    win = aDocInfo.GetWindow()->GetCurrentInnerWindow();
552
0
  }
553
0
554
0
  for (auto iter = mExtensions.Iter(); !iter.Done(); iter.Next()) {
555
0
    RefPtr<WebExtensionPolicy> policy = iter.Data();
556
0
557
0
    for (auto& script : policy->ContentScripts()) {
558
0
      if (script->Matches(aDocInfo)) {
559
0
        if (aIsPreload) {
560
0
          ProcessScript().PreloadContentScript(script);
561
0
        } else {
562
0
          if (!win->IsCurrentInnerWindow()) {
563
0
            break;
564
0
          }
565
0
          RefPtr<Promise> promise;
566
0
          ProcessScript().LoadContentScript(script, win, getter_AddRefs(promise));
567
0
        }
568
0
      }
569
0
    }
570
0
  }
571
0
572
0
  for (auto iter = mObservers.Iter(); !iter.Done(); iter.Next()) {
573
0
    RefPtr<DocumentObserver> observer = iter.Data();
574
0
575
0
    for (auto& matcher : observer->Matchers()) {
576
0
      if (matcher->Matches(aDocInfo)) {
577
0
        if (aIsPreload) {
578
0
          observer->NotifyMatch(*matcher, aDocInfo.GetLoadInfo());
579
0
        } else {
580
0
          observer->NotifyMatch(*matcher, aDocInfo.GetWindow());
581
0
        }
582
0
      }
583
0
    }
584
0
  }
585
0
}
586
587
588
/*****************************************************************************
589
 * nsIAddonPolicyService
590
 *****************************************************************************/
591
592
nsresult
593
ExtensionPolicyService::GetBaseCSP(nsAString& aBaseCSP)
594
0
{
595
0
  BaseCSP(aBaseCSP);
596
0
  return NS_OK;
597
0
}
598
599
nsresult
600
ExtensionPolicyService::GetDefaultCSP(nsAString& aDefaultCSP)
601
0
{
602
0
  DefaultCSP(aDefaultCSP);
603
0
  return NS_OK;
604
0
}
605
606
nsresult
607
ExtensionPolicyService::GetAddonCSP(const nsAString& aAddonId,
608
                                    nsAString& aResult)
609
0
{
610
0
  if (WebExtensionPolicy* policy = GetByID(aAddonId)) {
611
0
    policy->GetContentSecurityPolicy(aResult);
612
0
    return NS_OK;
613
0
  }
614
0
  return NS_ERROR_INVALID_ARG;
615
0
}
616
617
nsresult
618
ExtensionPolicyService::GetGeneratedBackgroundPageUrl(const nsACString& aHostname,
619
                                                      nsACString& aResult)
620
0
{
621
0
  if (WebExtensionPolicy* policy = GetByHost(aHostname)) {
622
0
    nsAutoCString url("data:text/html,");
623
0
624
0
    nsCString html = policy->BackgroundPageHTML();
625
0
    nsAutoCString escaped;
626
0
627
0
    url.Append(NS_EscapeURL(html, esc_Minimal, escaped));
628
0
629
0
    aResult = url;
630
0
    return NS_OK;
631
0
  }
632
0
  return NS_ERROR_INVALID_ARG;
633
0
}
634
635
nsresult
636
ExtensionPolicyService::AddonHasPermission(const nsAString& aAddonId,
637
                                           const nsAString& aPerm,
638
                                           bool* aResult)
639
0
{
640
0
  if (WebExtensionPolicy* policy = GetByID(aAddonId)) {
641
0
    *aResult = policy->HasPermission(aPerm);
642
0
    return NS_OK;
643
0
  }
644
0
  return NS_ERROR_INVALID_ARG;
645
0
}
646
647
nsresult
648
ExtensionPolicyService::AddonMayLoadURI(const nsAString& aAddonId,
649
                                        nsIURI* aURI,
650
                                        bool aExplicit,
651
                                        bool* aResult)
652
0
{
653
0
  if (WebExtensionPolicy* policy = GetByID(aAddonId)) {
654
0
    *aResult = policy->CanAccessURI(aURI, aExplicit);
655
0
    return NS_OK;
656
0
  }
657
0
  return NS_ERROR_INVALID_ARG;
658
0
}
659
660
nsresult
661
ExtensionPolicyService::GetExtensionName(const nsAString& aAddonId,
662
                                         nsAString& aName)
663
0
{
664
0
  if (WebExtensionPolicy* policy = GetByID(aAddonId)) {
665
0
    aName.Assign(policy->Name());
666
0
    return NS_OK;
667
0
  }
668
0
  return NS_ERROR_INVALID_ARG;
669
0
}
670
671
nsresult
672
ExtensionPolicyService::ExtensionURILoadableByAnyone(nsIURI* aURI, bool* aResult)
673
0
{
674
0
  URLInfo url(aURI);
675
0
  if (WebExtensionPolicy* policy = GetByURL(url)) {
676
0
    *aResult = policy->IsPathWebAccessible(url.FilePath());
677
0
    return NS_OK;
678
0
  }
679
0
  return NS_ERROR_INVALID_ARG;
680
0
}
681
682
nsresult
683
ExtensionPolicyService::ExtensionURIToAddonId(nsIURI* aURI, nsAString& aResult)
684
0
{
685
0
  if (WebExtensionPolicy* policy = GetByURL(aURI)) {
686
0
    policy->GetId(aResult);
687
0
  } else {
688
0
    aResult.SetIsVoid(true);
689
0
  }
690
0
  return NS_OK;
691
0
}
692
693
694
NS_IMPL_CYCLE_COLLECTION(ExtensionPolicyService, mExtensions, mExtensionHosts,
695
                         mObservers)
696
697
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionPolicyService)
698
0
  NS_INTERFACE_MAP_ENTRY(nsIAddonPolicyService)
699
0
  NS_INTERFACE_MAP_ENTRY(nsIObserver)
700
0
  NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
701
0
  NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
702
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAddonPolicyService)
703
0
NS_INTERFACE_MAP_END
704
705
NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionPolicyService)
706
NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionPolicyService)
707
708
} // namespace mozilla