Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/extensions/cookie/nsPermissionManager.h
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
#ifndef nsPermissionManager_h__
8
#define nsPermissionManager_h__
9
10
#include "nsIPermissionManager.h"
11
#include "nsIObserver.h"
12
#include "nsWeakReference.h"
13
#include "nsCOMPtr.h"
14
#include "nsIInputStream.h"
15
#include "nsTHashtable.h"
16
#include "nsTArray.h"
17
#include "nsString.h"
18
#include "nsPermission.h"
19
#include "nsIPrefBranch.h"
20
#include "nsHashKeys.h"
21
#include "nsCOMArray.h"
22
#include "nsDataHashtable.h"
23
#include "nsIRunnable.h"
24
#include "nsRefPtrHashtable.h"
25
#include "mozilla/MozPromise.h"
26
27
namespace mozilla {
28
class OriginAttributesPattern;
29
}
30
31
class nsIPermission;
32
class mozIStorageConnection;
33
class mozIStorageAsyncStatement;
34
35
////////////////////////////////////////////////////////////////////////////////
36
37
class nsPermissionManager final : public nsIPermissionManager,
38
                                  public nsIObserver,
39
                                  public nsSupportsWeakReference
40
{
41
public:
42
  class PermissionEntry
43
  {
44
  public:
45
    PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission,
46
                    uint32_t aExpireType, int64_t aExpireTime,
47
                    int64_t aModificationTime)
48
     : mID(aID)
49
     , mType(aType)
50
     , mPermission(aPermission)
51
     , mExpireType(aExpireType)
52
     , mExpireTime(aExpireTime)
53
     , mModificationTime(aModificationTime)
54
     , mNonSessionPermission(aPermission)
55
     , mNonSessionExpireType(aExpireType)
56
     , mNonSessionExpireTime(aExpireTime)
57
0
    {}
58
59
    int64_t  mID;
60
    uint32_t mType;
61
    uint32_t mPermission;
62
    uint32_t mExpireType;
63
    int64_t  mExpireTime;
64
    int64_t  mModificationTime;
65
    uint32_t mNonSessionPermission;
66
    uint32_t mNonSessionExpireType;
67
    uint32_t mNonSessionExpireTime;
68
  };
69
70
  /**
71
   * PermissionKey is the key used by PermissionHashKey hash table.
72
   *
73
   * NOTE: It could be implementing nsIHashable but there is no reason to worry
74
   * with XPCOM interfaces while we don't need to.
75
   */
76
  class PermissionKey
77
  {
78
  public:
79
    static PermissionKey* CreateFromPrincipal(nsIPrincipal* aPrincipal,
80
                                              nsresult& aResult);
81
    static PermissionKey* CreateFromURI(nsIURI* aURI,
82
                                        nsresult& aResult);
83
84
    explicit PermissionKey(const nsACString& aOrigin)
85
      : mOrigin(aOrigin)
86
0
    {
87
0
    }
88
89
0
    bool operator==(const PermissionKey& aKey) const {
90
0
      return mOrigin.Equals(aKey.mOrigin);
91
0
    }
92
93
0
    PLDHashNumber GetHashCode() const {
94
0
      return mozilla::HashString(mOrigin);
95
0
    }
96
97
    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey)
98
99
    nsCString mOrigin;
100
101
  private:
102
    // Default ctor shouldn't be used.
103
    PermissionKey() = delete;
104
105
    // Dtor shouldn't be used outside of the class.
106
0
    ~PermissionKey() {};
107
  };
108
109
  class PermissionHashKey : public nsRefPtrHashKey<PermissionKey>
110
  {
111
  public:
112
    explicit PermissionHashKey(const PermissionKey* aPermissionKey)
113
      : nsRefPtrHashKey<PermissionKey>(aPermissionKey)
114
0
    {}
115
116
    PermissionHashKey(PermissionHashKey&& toCopy)
117
      : nsRefPtrHashKey<PermissionKey>(std::move(toCopy))
118
      , mPermissions(std::move(toCopy.mPermissions))
119
0
    {}
120
121
    bool KeyEquals(const PermissionKey* aKey) const
122
0
    {
123
0
      return *aKey == *GetKey();
124
0
    }
125
126
    static PLDHashNumber HashKey(const PermissionKey* aKey)
127
0
    {
128
0
      return aKey->GetHashCode();
129
0
    }
130
131
    // Force the hashtable to use the copy constructor when shuffling entries
132
    // around, otherwise the Auto part of our AutoTArray won't be happy!
133
    enum { ALLOW_MEMMOVE = false };
134
135
    inline nsTArray<PermissionEntry> & GetPermissions()
136
0
    {
137
0
      return mPermissions;
138
0
    }
139
140
    inline int32_t GetPermissionIndex(uint32_t aType) const
141
0
    {
142
0
      for (uint32_t i = 0; i < mPermissions.Length(); ++i)
143
0
        if (mPermissions[i].mType == aType)
144
0
          return i;
145
0
146
0
      return -1;
147
0
    }
148
149
    inline PermissionEntry GetPermission(uint32_t aType) const
150
0
    {
151
0
      for (uint32_t i = 0; i < mPermissions.Length(); ++i)
152
0
        if (mPermissions[i].mType == aType)
153
0
          return mPermissions[i];
154
0
155
0
      // unknown permission... return relevant data
156
0
      return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION,
157
0
                             nsIPermissionManager::EXPIRE_NEVER, 0, 0);
158
0
    }
159
160
  private:
161
    AutoTArray<PermissionEntry, 1> mPermissions;
162
  };
163
164
  // nsISupports
165
  NS_DECL_ISUPPORTS
166
  NS_DECL_NSIPERMISSIONMANAGER
167
  NS_DECL_NSIOBSERVER
168
169
  nsPermissionManager();
170
  static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
171
  nsresult Init();
172
173
  // enums for AddInternal()
174
  enum OperationType {
175
    eOperationNone,
176
    eOperationAdding,
177
    eOperationRemoving,
178
    eOperationChanging,
179
    eOperationReplacingDefault
180
  };
181
182
  enum DBOperationType {
183
    eNoDBOperation,
184
    eWriteToDB
185
  };
186
187
  enum NotifyOperationType {
188
    eDontNotify,
189
    eNotify
190
  };
191
192
  // A special value for a permission ID that indicates the ID was loaded as
193
  // a default value.  These will never be written to the database, but may
194
  // be overridden with an explicit permission (including UNKNOWN_ACTION)
195
  static const int64_t cIDPermissionIsDefault = -1;
196
197
  nsresult AddInternal(nsIPrincipal* aPrincipal,
198
                       const nsCString& aType,
199
                       uint32_t aPermission,
200
                       int64_t aID,
201
                       uint32_t aExpireType,
202
                       int64_t  aExpireTime,
203
                       int64_t aModificationTime,
204
                       NotifyOperationType aNotifyOperation,
205
                       DBOperationType aDBOperation,
206
                       const bool aIgnoreSessionPermissions = false);
207
208
  /**
209
   * Initialize the "clear-origin-attributes-data" observing.
210
   * Will create a nsPermissionManager instance if needed.
211
   * That way, we can prevent have nsPermissionManager created at startup just
212
   * to be able to clear data when an application is uninstalled.
213
   */
214
  static void ClearOriginDataObserverInit();
215
216
  nsresult
217
  RemovePermissionsWithAttributes(mozilla::OriginAttributesPattern& aAttrs);
218
219
  /**
220
   * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
221
   * permission keys.
222
   *
223
   * Get the permission key corresponding to the given Principal. This method is
224
   * intentionally infallible, as we want to provide an permission key to every
225
   * principal. Principals which don't have meaningful URIs with http://,
226
   * https://, or ftp:// schemes are given the default "" Permission Key.
227
   *
228
   * @param aPrincipal  The Principal which the key is to be extracted from.
229
   * @param aPermissionKey  A string which will be filled with the permission key.
230
   */
231
  static void GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aPermissionKey);
232
233
  /**
234
   * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
235
   * permission keys.
236
   *
237
   * Get the permission key corresponding to the given Origin. This method is
238
   * like GetKeyForPrincipal, except that it avoids creating a nsIPrincipal
239
   * object when you already have access to an origin string.
240
   *
241
   * If this method is passed a nonsensical origin string it may produce a
242
   * nonsensical permission key result.
243
   *
244
   * @param aOrigin  The origin which the key is to be extracted from.
245
   * @param aPermissionKey  A string which will be filled with the permission key.
246
   */
247
  static void GetKeyForOrigin(const nsACString& aOrigin, nsACString& aPermissionKey);
248
249
  /**
250
   * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
251
   * permission keys.
252
   *
253
   * Get the permission key corresponding to the given Principal and type. This
254
   * method is intentionally infallible, as we want to provide an permission key
255
   * to every principal. Principals which don't have meaningful URIs with
256
   * http://, https://, or ftp:// schemes are given the default "" Permission
257
   * Key.
258
   *
259
   * This method is different from GetKeyForPrincipal in that it also takes
260
   * permissions which must be sent down before loading a document into account.
261
   *
262
   * @param aPrincipal  The Principal which the key is to be extracted from.
263
   * @param aType  The type of the permission to get the key for.
264
   * @param aPermissionKey  A string which will be filled with the permission key.
265
   */
266
  static void GetKeyForPermission(nsIPrincipal* aPrincipal,
267
                                  const char* aType,
268
                                  nsACString& aPermissionKey);
269
270
  /**
271
   * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
272
   * permission keys.
273
   *
274
   * Get all permissions keys which could correspond to the given principal.
275
   * This method, like GetKeyForPrincipal, is infallible and should always
276
   * produce at least one key.
277
   *
278
   * Unlike GetKeyForPrincipal, this method also gets the keys for base domains
279
   * of the given principal. All keys returned by this method must be available
280
   * in the content process for a given URL to successfully have its permissions
281
   * checked in the `aExactHostMatch = false` situation.
282
   *
283
   * @param aPrincipal  The Principal which the key is to be extracted from.
284
   */
285
  static nsTArray<nsCString> GetAllKeysForPrincipal(nsIPrincipal* aPrincipal);
286
287
  // From ContentChild.
288
  nsresult RemoveAllFromIPC();
289
290
private:
291
  virtual ~nsPermissionManager();
292
293
  int32_t GetTypeIndex(const char *aTypeString,
294
                       bool        aAdd);
295
296
  PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal,
297
                                          uint32_t      aType,
298
                                          bool          aExactHostMatch);
299
  PermissionHashKey* GetPermissionHashKey(nsIURI*       aURI,
300
                                          uint32_t      aType,
301
                                          bool          aExactHostMatch);
302
303
  nsresult CommonTestPermission(nsIPrincipal* aPrincipal,
304
                                const char  * aType,
305
                                uint32_t    * aPermission,
306
                                bool          aExactHostMatch,
307
                                bool          aIncludingSession)
308
0
  {
309
0
    return CommonTestPermissionInternal(aPrincipal, nullptr, aType,
310
0
                                        aPermission, aExactHostMatch,
311
0
                                        aIncludingSession);
312
0
  }
313
  nsresult CommonTestPermission(nsIURI    * aURI,
314
                                const char* aType,
315
                                uint32_t  * aPermission,
316
                                bool        aExactHostMatch,
317
                                bool        aIncludingSession)
318
0
  {
319
0
    return CommonTestPermissionInternal(nullptr, aURI, aType, aPermission,
320
0
                                        aExactHostMatch, aIncludingSession);
321
0
  }
322
  // Only one of aPrincipal or aURI is allowed to be passed in.
323
  nsresult CommonTestPermissionInternal(nsIPrincipal* aPrincipal,
324
                                        nsIURI      * aURI,
325
                                        const char  * aType,
326
                                        uint32_t    * aPermission,
327
                                        bool          aExactHostMatch,
328
                                        bool          aIncludingSession);
329
330
  nsresult OpenDatabase(nsIFile* permissionsFile);
331
  nsresult InitDB(bool aRemoveFile);
332
  nsresult CreateTable();
333
  nsresult Import();
334
  nsresult ImportDefaults();
335
  nsresult _DoImport(nsIInputStream *inputStream, mozIStorageConnection *aConn);
336
  nsresult Read();
337
  void     NotifyObserversWithPermission(nsIPrincipal*     aPrincipal,
338
                                         const nsCString  &aType,
339
                                         uint32_t          aPermission,
340
                                         uint32_t          aExpireType,
341
                                         int64_t           aExpireTime,
342
                                         const char16_t  *aData);
343
  void     NotifyObservers(nsIPermission *aPermission, const char16_t *aData);
344
345
  // Finalize all statements, close the DB and null it.
346
  // if aRebuildOnSuccess, reinitialize database
347
  void     CloseDB(bool aRebuildOnSuccess = false);
348
349
  nsresult RemoveAllInternal(bool aNotifyObservers);
350
  nsresult RemoveAllFromMemory();
351
  static void UpdateDB(OperationType aOp,
352
                       mozIStorageAsyncStatement* aStmt,
353
                       int64_t aID,
354
                       const nsACString& aOrigin,
355
                       const nsACString& aType,
356
                       uint32_t aPermission,
357
                       uint32_t aExpireType,
358
                       int64_t aExpireTime,
359
                       int64_t aModificationTime);
360
361
  /**
362
   * This method removes all permissions modified after the specified time.
363
   */
364
  nsresult
365
  RemoveAllModifiedSince(int64_t aModificationTime);
366
367
  template<class T>
368
  nsresult
369
  RemovePermissionEntries(T aCondition);
370
371
  /**
372
   * Returns false if this permission manager wouldn't have the permission
373
   * requested available.
374
   *
375
   * If aType is nullptr, checks that the permission manager would have all
376
   * permissions available for the given principal.
377
   */
378
  bool PermissionAvailable(nsIPrincipal* aPrincipal, const char* aType);
379
380
  nsRefPtrHashtable<nsCStringHashKey, mozilla::GenericPromise::Private> mPermissionKeyPromiseMap;
381
382
  nsCOMPtr<mozIStorageConnection> mDBConn;
383
  nsCOMPtr<mozIStorageAsyncStatement> mStmtInsert;
384
  nsCOMPtr<mozIStorageAsyncStatement> mStmtDelete;
385
  nsCOMPtr<mozIStorageAsyncStatement> mStmtUpdate;
386
387
  bool mMemoryOnlyDB;
388
389
  nsTHashtable<PermissionHashKey> mPermissionTable;
390
  // a unique, monotonically increasing id used to identify each database entry
391
  int64_t                      mLargestID;
392
393
  // An array to store the strings identifying the different types.
394
  nsTArray<nsCString>          mTypeArray;
395
396
  // Initially, |false|. Set to |true| once shutdown has started, to avoid
397
  // reopening the database.
398
  bool mIsShuttingDown;
399
400
  nsCOMPtr<nsIPrefBranch> mDefaultPrefBranch;
401
402
  friend class DeleteFromMozHostListener;
403
  friend class CloseDatabaseListener;
404
};
405
406
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}
407
#define NS_PERMISSIONMANAGER_CID \
408
{ 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } }
409
410
#endif /* nsPermissionManager_h__ */