DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (7067896c7696)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_net_CookieSettings_h
#define mozilla_net_CookieSettings_h

#include "nsICookieSettings.h"
#include "nsDataHashtable.h"

class nsIPermission;

namespace mozilla {
namespace net {

class CookieSettingsArgs;

/**
 * CookieSettings
 * ~~~~~~~~~~~~~~
 *
 * CookieSettings is a snapshot of cookie policy and cookie permissions in a
 * precise moment of time. This object is used by top-level documents to have a
 * consistent cookie configuration also in case the user changes it. New cookie
 * configurations will apply only to new top-level documents.
 *
 * CookieSettings creation
 * ~~~~~~~~~~~~~~~~~~~~~~~
 *
 * CookieSettings is created when the top-level document's nsIChannel's
 * nsILoadInfo is constructed. Any sub-resource and any sub-document inherits it
 * from that nsILoadInfo. Also dedicated workers and their resources inherit it
 * from the parent document.
 *
 * SharedWorkers and ServiceWorkers have their own CookieSettings because they
 * don't have a single parent document (SharedWorkers could have more than one,
 * ServiceWorkers have none).
 *
 * In Chrome code, we have a new CookieSettings when we download resources via
 * 'Save-as...' and we also have a new CookieSettings for favicon downloading.
 *
 * Content-scripts WebExtensions also have their own CookieSettings because they
 * don't have a direct access to the document they are running into.
 *
 * Anything else will have a special CookieSettings which blocks everything
 * (CookieSettings::CreateBlockingAll()) by forcing BEHAVIOR_REJECT as policy.
 * When this happens, that context will not have access to the cookie jar and no
 * cookies are sent or received.
 *
 * Propagation of CookieSettings
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * CookieSettings are shared inside the same top-level document via its
 * nsIChannel's nsILoadInfo.  This is done automatically if you pass a nsINode
 * to NS_NewChannel(), and it must be done manually if you use a different
 * channel constructor. For instance, this happens for any worker networking
 * operation.
 *
 * We use the same CookieSettings for any resource belonging to the top-level
 * document even if cross-origin. This makes the browser behave consistently a
 * scenario where A loads B which loads A again, and cookie policy/permission
 * changes in the meantime.
 *
 * Cookie Permissions propagation
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * CookieSettings populates the known cookie permissions only when required.
 * Initially the list is empty, but when CookieSettings::CookiePermission() is
 * called, the requested permission is stored in the internal list if it doesn't
 * exist yet.
 *
 * This is actually nice because it relies on the permission propagation from
 * parent to content process. No extra IPC is required.
 *
 * Note that we store permissions with UNKNOWN_ACTION values too because they
 * can be set after the loading of the top-level document and we don't want to
 * return a different value when this happens.
 *
 * Use of CookieSettings
 * ~~~~~~~~~~~~~~~~~~~~~
 *
 * In theory, there should not be direct access to cookie permissions or
 * cookieBehavior pref. Everything should pass through CookieSettings.
 *
 * A reference to CookieSettings can be obtained from
 * nsILoadInfo::GetCookieSettings(), from Document::CookieSettings() and from
 * the WorkerPrivate::CookieSettings().
 *
 * CookieSettings is thread-safe, but the permission list must be touched only
 * on the main-thread.
 *
 * Testing
 * ~~~~~~~
 *
 * If you need to test the changing of cookie policy or a cookie permission, you
 * need to workaround CookieSettings. This can be done opening a new window and
 * running the test into that new global.
 */

/**
 * Class that provides an nsICookieSettings implementation.
 */
class CookieSettings final : public nsICookieSettings {
 public:
  typedef nsTArray<RefPtr<nsIPermission>> CookiePermissionList;

  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSICOOKIESETTINGS

  static already_AddRefed<nsICookieSettings> CreateBlockingAll();

  static already_AddRefed<nsICookieSettings> Create();

  static CookieSettings* Cast(nsICookieSettings* aCS) {
    return static_cast<CookieSettings*>(aCS);
  }

  void Serialize(CookieSettingsArgs& aData);

  static void Deserialize(const CookieSettingsArgs& aData,
                          nsICookieSettings** aCookieSettings);

  void Merge(const CookieSettingsArgs& aData);

  // We don't want to send this object from parent to child process if there are
  // no reasons. HasBeenChanged() returns true if the object has changed its
  // internal state and it must be sent beck to the content process.
  bool HasBeenChanged() const { return mToBeMerged; }

 private:
  enum State {
    // No cookie permissions are allowed to be stored in this object.
    eFixed,

    // Cookie permissions can be stored in case they are unknown when they are
    // asked or when they are sent from the parent process.
    eProgressive,
  };

  CookieSettings(uint32_t aCookieBehavior, State aState);
  ~CookieSettings();

  uint32_t mCookieBehavior;
  CookiePermissionList mCookiePermissions;

  State mState;

  bool mToBeMerged;
};

}  // namespace net
}  // namespace mozilla

#endif  // mozilla_net_CookieSettings_h