Source code

Revision control

Other Tools

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 "nsIURL.h"
8
#include "StorageUtils.h"
9
10
#include "mozilla/OriginAttributes.h"
11
#include "nsDebug.h"
12
#include "nsIPrincipal.h"
13
#include "nsIURI.h"
14
#include "nsIURL.h"
15
#include "nsNetUtil.h"
16
#include "nsPrintfCString.h"
17
18
namespace mozilla {
19
namespace dom {
20
namespace StorageUtils {
21
22
nsresult GenerateOriginKey(nsIPrincipal* aPrincipal,
23
nsACString& aOriginAttrSuffix,
24
nsACString& aOriginKey) {
25
if (NS_WARN_IF(!aPrincipal)) {
26
return NS_ERROR_UNEXPECTED;
27
}
28
29
aPrincipal->OriginAttributesRef().CreateSuffix(aOriginAttrSuffix);
30
31
nsCOMPtr<nsIURI> uri;
32
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
33
NS_ENSURE_SUCCESS(rv, rv);
34
if (!uri) {
35
return NS_ERROR_UNEXPECTED;
36
}
37
38
nsAutoCString domainOrigin;
39
rv = uri->GetAsciiHost(domainOrigin);
40
NS_ENSURE_SUCCESS(rv, rv);
41
42
if (domainOrigin.IsEmpty()) {
43
// For the file:/// protocol use the exact directory as domain.
44
if (uri->SchemeIs("file")) {
45
nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
46
NS_ENSURE_SUCCESS(rv, rv);
47
rv = url->GetDirectory(domainOrigin);
48
NS_ENSURE_SUCCESS(rv, rv);
49
}
50
}
51
52
// Append reversed domain
53
nsAutoCString reverseDomain;
54
rv = CreateReversedDomain(domainOrigin, reverseDomain);
55
if (NS_FAILED(rv)) {
56
return rv;
57
}
58
59
aOriginKey.Append(reverseDomain);
60
61
// Append scheme
62
nsAutoCString scheme;
63
rv = uri->GetScheme(scheme);
64
NS_ENSURE_SUCCESS(rv, rv);
65
66
aOriginKey.Append(':');
67
aOriginKey.Append(scheme);
68
69
// Append port if any
70
int32_t port = NS_GetRealPort(uri);
71
if (port != -1) {
72
aOriginKey.Append(nsPrintfCString(":%d", port));
73
}
74
75
return NS_OK;
76
}
77
78
bool PrincipalsEqual(nsIPrincipal* aObjectPrincipal,
79
nsIPrincipal* aSubjectPrincipal) {
80
if (!aSubjectPrincipal) {
81
return true;
82
}
83
84
if (!aObjectPrincipal) {
85
return false;
86
}
87
88
return aSubjectPrincipal->Equals(aObjectPrincipal);
89
}
90
91
void ReverseString(const nsACString& aSource, nsACString& aResult) {
92
nsACString::const_iterator sourceBegin, sourceEnd;
93
aSource.BeginReading(sourceBegin);
94
aSource.EndReading(sourceEnd);
95
96
aResult.SetLength(aSource.Length());
97
auto destEnd = aResult.EndWriting();
98
99
while (sourceBegin != sourceEnd) {
100
*(--destEnd) = *sourceBegin;
101
++sourceBegin;
102
}
103
}
104
105
nsresult CreateReversedDomain(const nsACString& aAsciiDomain,
106
nsACString& aKey) {
107
if (aAsciiDomain.IsEmpty()) {
108
return NS_ERROR_NOT_AVAILABLE;
109
}
110
111
ReverseString(aAsciiDomain, aKey);
112
113
aKey.Append('.');
114
return NS_OK;
115
}
116
117
// This is only a compatibility code for schema version 0. Returns the 'scope'
118
// key in the schema version 0 format for the scope column.
119
nsCString Scheme0Scope(const nsACString& aOriginSuffix,
120
const nsACString& aOriginNoSuffix) {
121
nsCString result;
122
123
OriginAttributes oa;
124
if (!aOriginSuffix.IsEmpty()) {
125
DebugOnly<bool> success = oa.PopulateFromSuffix(aOriginSuffix);
126
MOZ_ASSERT(success);
127
}
128
129
if (oa.mInIsolatedMozBrowser) {
130
result.AppendInt(0); // This is the appId to be removed.
131
result.Append(':');
132
result.Append(oa.mInIsolatedMozBrowser ? 't' : 'f');
133
result.Append(':');
134
}
135
136
// If there is more than just appid and/or inbrowser stored in origin
137
// attributes, put it to the schema 0 scope as well. We must do that
138
// to keep the scope column unique (same resolution as schema 1 has
139
// with originAttributes and originKey columns) so that switch between
140
// schema 1 and 0 always works in both ways.
141
nsAutoCString remaining;
142
oa.mInIsolatedMozBrowser = false;
143
oa.CreateSuffix(remaining);
144
if (!remaining.IsEmpty()) {
145
MOZ_ASSERT(!aOriginSuffix.IsEmpty());
146
147
if (result.IsEmpty()) {
148
// Must contain the old prefix, otherwise we won't search for the whole
149
// origin attributes suffix.
150
result.AppendLiteral("0:f:");
151
}
152
153
// Append the whole origin attributes suffix despite we have already stored
154
// appid and inbrowser. We are only looking for it when the scope string
155
// starts with "$appid:$inbrowser:" (with whatever valid values).
156
//
157
// The OriginAttributes suffix is a string in a form like:
158
// "^addonId=101&userContextId=5" and it's ensured it always starts with '^'
159
// and never contains ':'. See OriginAttributes::CreateSuffix.
160
result.Append(aOriginSuffix);
161
result.Append(':');
162
}
163
164
result.Append(aOriginNoSuffix);
165
166
return result;
167
}
168
169
} // namespace StorageUtils
170
} // namespace dom
171
} // namespace mozilla