Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/storage/Storage.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 "Storage.h"
8
#include "StorageNotifierService.h"
9
10
#include "mozilla/dom/StorageBinding.h"
11
#include "nsIPrincipal.h"
12
#include "nsPIDOMWindow.h"
13
14
namespace mozilla {
15
namespace dom {
16
17
static const char kStorageEnabled[] = "dom.storage.enabled";
18
19
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mWindow, mPrincipal)
20
21
NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage)
22
NS_IMPL_CYCLE_COLLECTING_RELEASE(Storage)
23
24
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Storage)
25
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
26
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
27
0
NS_INTERFACE_MAP_END
28
29
Storage::Storage(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal)
30
  : mWindow(aWindow)
31
  , mPrincipal(aPrincipal)
32
  , mIsSessionOnly(false)
33
0
{
34
0
  MOZ_ASSERT(aPrincipal);
35
0
}
36
37
Storage::~Storage()
38
0
{}
39
40
/* static */ bool
41
Storage::StoragePrefIsEnabled()
42
0
{
43
0
  return mozilla::Preferences::GetBool(kStorageEnabled);
44
0
}
45
46
bool
47
Storage::CanUseStorage(nsIPrincipal& aSubjectPrincipal)
48
0
{
49
0
  // This method is responsible for correct setting of mIsSessionOnly.
50
0
  if (!StoragePrefIsEnabled()) {
51
0
    return false;
52
0
  }
53
0
54
0
  nsContentUtils::StorageAccess access =
55
0
    nsContentUtils::StorageAllowedForPrincipal(Principal());
56
0
57
0
  if (access == nsContentUtils::StorageAccess::eDeny) {
58
0
    return false;
59
0
  }
60
0
61
0
  mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
62
0
63
0
  return aSubjectPrincipal.Subsumes(mPrincipal);
64
0
}
65
66
/* virtual */ JSObject*
67
Storage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
68
0
{
69
0
  return Storage_Binding::Wrap(aCx, this, aGivenProto);
70
0
}
71
72
namespace {
73
74
class StorageNotifierRunnable : public Runnable
75
{
76
public:
77
  StorageNotifierRunnable(nsISupports* aSubject, const char16_t *aStorageType,
78
                          bool aPrivateBrowsing)
79
    : Runnable("StorageNotifierRunnable")
80
    , mSubject(aSubject)
81
    , mStorageType(aStorageType)
82
    , mPrivateBrowsing(aPrivateBrowsing)
83
0
  {}
84
85
  NS_IMETHOD
86
  Run() override
87
0
  {
88
0
    nsCOMPtr<nsIObserverService> observerService =
89
0
      mozilla::services::GetObserverService();
90
0
    if (observerService) {
91
0
      observerService->NotifyObservers(mSubject,
92
0
                                       mPrivateBrowsing
93
0
                                         ? "dom-private-storage2-changed"
94
0
                                         : "dom-storage2-changed",
95
0
                                       mStorageType);
96
0
    }
97
0
    return NS_OK;
98
0
  }
99
100
private:
101
  nsCOMPtr<nsISupports> mSubject;
102
  const char16_t* mStorageType;
103
  const bool mPrivateBrowsing;
104
};
105
106
} // namespace
107
108
/* static */ void
109
Storage::NotifyChange(Storage* aStorage, nsIPrincipal* aPrincipal,
110
                      const nsAString& aKey,
111
                      const nsAString& aOldValue, const nsAString& aNewValue,
112
                      const char16_t* aStorageType,
113
                      const nsAString& aDocumentURI, bool aIsPrivate,
114
                      bool aImmediateDispatch)
115
0
{
116
0
  StorageEventInit dict;
117
0
  dict.mBubbles = false;
118
0
  dict.mCancelable = false;
119
0
  dict.mKey = aKey;
120
0
  dict.mNewValue = aNewValue;
121
0
  dict.mOldValue = aOldValue;
122
0
  dict.mStorageArea = aStorage;
123
0
  dict.mUrl = aDocumentURI;
124
0
125
0
  // Note, this DOM event should never reach JS. It is cloned later in
126
0
  // nsGlobalWindow.
127
0
  RefPtr<StorageEvent> event =
128
0
    StorageEvent::Constructor(nullptr, NS_LITERAL_STRING("storage"), dict);
129
0
130
0
  event->SetPrincipal(aPrincipal);
131
0
132
0
  // This will send the event to any registered window.
133
0
  StorageNotifierService::Broadcast(event, aStorageType, aIsPrivate,
134
0
                                    aImmediateDispatch);
135
0
136
0
  // This runnable is mainly used by devtools. Windows receive notification by
137
0
  // StorageNotifierService.
138
0
139
0
  RefPtr<StorageNotifierRunnable> r =
140
0
    new StorageNotifierRunnable(event, aStorageType, aIsPrivate);
141
0
142
0
  if (aImmediateDispatch) {
143
0
    Unused << r->Run();
144
0
  } else {
145
0
    SystemGroup::Dispatch(TaskCategory::Other, r.forget());
146
0
  }
147
0
}
148
149
} // namespace dom
150
} // namespace mozilla