summaryrefslogtreecommitdiffstats
path: root/dom/localstorage/LocalStorageCommon.cpp
blob: a5b01e0146333cb480f90248355ea083c5bce900 (plain)
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
157
158
159
160
/* -*- 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/. */

#include "LocalStorageCommon.h"

#include <cstdint>
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Logging.h"
#include "mozilla/OriginAttributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/dom/StorageUtils.h"
#include "mozilla/dom/quota/ResultExtensions.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/net/MozURL.h"
#include "mozilla/net/WebSocketFrame.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsPrintfCString.h"
#include "nsString.h"
#include "nsStringFlags.h"
#include "nsXULAppAPI.h"

namespace mozilla::dom {

using namespace mozilla::net;

namespace {

StaticMutex gNextGenLocalStorageMutex;
Atomic<int32_t> gNextGenLocalStorageEnabled(-1);
LazyLogModule gLogger("LocalStorage");

}  // namespace

const char16_t* kLocalStorageType = u"localStorage";

bool NextGenLocalStorageEnabled() {
  if (XRE_IsParentProcess()) {
    StaticMutexAutoLock lock(gNextGenLocalStorageMutex);

    if (gNextGenLocalStorageEnabled == -1) {
      // Ideally all this Mutex stuff would be replaced with just using
      // an AtStartup StaticPref, but there are concerns about this causing
      // deadlocks if this access needs to init the AtStartup cache.
      bool enabled =
          !StaticPrefs::
              dom_storage_enable_unsupported_legacy_implementation_DoNotUseDirectly();

      gNextGenLocalStorageEnabled = enabled ? 1 : 0;
    }

    return !!gNextGenLocalStorageEnabled;
  }

  return CachedNextGenLocalStorageEnabled();
}

void RecvInitNextGenLocalStorageEnabled(const bool aEnabled) {
  MOZ_ASSERT(!XRE_IsParentProcess());
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(gNextGenLocalStorageEnabled == -1);

  gNextGenLocalStorageEnabled = aEnabled ? 1 : 0;
}

bool CachedNextGenLocalStorageEnabled() {
  MOZ_ASSERT(gNextGenLocalStorageEnabled != -1);

  return !!gNextGenLocalStorageEnabled;
}

Result<std::pair<nsCString, nsCString>, nsresult> GenerateOriginKey2(
    const mozilla::ipc::PrincipalInfo& aPrincipalInfo) {
  OriginAttributes attrs;
  nsCString spec;

  switch (aPrincipalInfo.type()) {
    case mozilla::ipc::PrincipalInfo::TNullPrincipalInfo: {
      const auto& info = aPrincipalInfo.get_NullPrincipalInfo();

      attrs = info.attrs();
      spec = info.spec();

      break;
    }

    case mozilla::ipc::PrincipalInfo::TContentPrincipalInfo: {
      const auto& info = aPrincipalInfo.get_ContentPrincipalInfo();

      attrs = info.attrs();
      spec = info.spec();

      break;
    }

    default: {
      spec.SetIsVoid(true);

      break;
    }
  }

  if (spec.IsVoid()) {
    return Err(NS_ERROR_UNEXPECTED);
  }

  nsCString originAttrSuffix;
  attrs.CreateSuffix(originAttrSuffix);

  RefPtr<MozURL> specURL;
  QM_TRY(MOZ_TO_RESULT(MozURL::Init(getter_AddRefs(specURL), spec)));

  nsCString host(specURL->Host());
  uint32_t length = host.Length();
  if (length > 0 && host.CharAt(0) == '[' && host.CharAt(length - 1) == ']') {
    host = Substring(host, 1, length - 2);
  }

  nsCString domainOrigin(host);

  if (domainOrigin.IsEmpty()) {
    // For the file:/// protocol use the exact directory as domain.
    if (specURL->Scheme().EqualsLiteral("file")) {
      domainOrigin.Assign(specURL->Directory());
    }
  }

  // Append reversed domain
  nsAutoCString reverseDomain;
  nsresult rv = StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
  if (NS_FAILED(rv)) {
    return Err(rv);
  }

  nsCString originKey = reverseDomain;

  // Append scheme
  originKey.Append(':');
  originKey.Append(specURL->Scheme());

  // Append port if any
  int32_t port = specURL->RealPort();
  if (port != -1) {
    originKey.AppendPrintf(":%d", port);
  }

  return std::make_pair(std::move(originAttrSuffix), std::move(originKey));
}

LogModule* GetLocalStorageLogger() { return gLogger; }

}  // namespace mozilla::dom