1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "gtest/gtest.h"
7
8 #include "nsCOMPtr.h"
9 #include "nsContentUtils.h"
10 #include "nsIChannel.h"
11 #include "nsIContentPolicy.h"
12 #include "nsICookieJarSettings.h"
13 #include "nsILoadInfo.h"
14 #include "nsIURI.h"
15 #include "nsNetUtil.h"
16 #include "nsStringFwd.h"
17
18 #include "mozilla/NullPrincipal.h"
19 #include "mozilla/Preferences.h"
20 #include "mozilla/RefPtr.h"
21 #include "mozilla/StoragePrincipalHelper.h"
22
23 using mozilla::Preferences;
24 using namespace mozilla;
25
26 /**
27 * Creates a test channel with CookieJarSettings which have a partitionKey set.
28 */
CreateMockChannel(nsIPrincipal * aPrincipal,bool isThirdParty,const nsACString & aPartitionKey,nsIChannel ** aChannel,nsICookieJarSettings ** aCookieJarSettings)29 nsresult CreateMockChannel(nsIPrincipal* aPrincipal, bool isThirdParty,
30 const nsACString& aPartitionKey,
31 nsIChannel** aChannel,
32 nsICookieJarSettings** aCookieJarSettings) {
33 nsCOMPtr<nsIURI> mockUri;
34 nsresult rv = NS_NewURI(getter_AddRefs(mockUri), "http://example.com"_ns);
35 NS_ENSURE_SUCCESS(rv, rv);
36
37 nsCOMPtr<nsIChannel> mockChannel;
38 nsCOMPtr<nsIIOService> service = do_GetIOService(&rv);
39 NS_ENSURE_SUCCESS(rv, rv);
40
41 rv = service->NewChannelFromURI(mockUri, nullptr, aPrincipal, aPrincipal, 0,
42 nsContentPolicyType::TYPE_OTHER,
43 getter_AddRefs(mockChannel));
44 NS_ENSURE_SUCCESS(rv, rv);
45
46 nsCOMPtr<nsILoadInfo> mockLoadInfo = mockChannel->LoadInfo();
47 rv = mockLoadInfo->SetIsThirdPartyContextToTopWindow(isThirdParty);
48 NS_ENSURE_SUCCESS(rv, rv);
49
50 nsCOMPtr<nsICookieJarSettings> cjs;
51 rv = mockLoadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
52 NS_ENSURE_SUCCESS(rv, rv);
53
54 nsCOMPtr<nsIURI> partitionKeyUri;
55 rv = NS_NewURI(getter_AddRefs(partitionKeyUri), aPartitionKey);
56 NS_ENSURE_SUCCESS(rv, rv);
57
58 rv = cjs->InitWithURI(partitionKeyUri, false);
59 NS_ENSURE_SUCCESS(rv, rv);
60
61 cjs.forget(aCookieJarSettings);
62 mockChannel.forget(aChannel);
63 return NS_OK;
64 }
65
TEST(TestStoragePrincipalHelper,TestCreateContentPrincipal)66 TEST(TestStoragePrincipalHelper, TestCreateContentPrincipal)
67 {
68 nsCOMPtr<nsIPrincipal> contentPrincipal =
69 BasePrincipal::CreateContentPrincipal("https://example.com"_ns);
70 EXPECT_TRUE(contentPrincipal);
71
72 nsCOMPtr<nsIChannel> mockChannel;
73 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
74 nsresult rv = CreateMockChannel(
75 contentPrincipal, false, "https://example.org"_ns,
76 getter_AddRefs(mockChannel), getter_AddRefs(cookieJarSettings));
77 ASSERT_EQ(rv, NS_OK) << "Could not create a mock channel";
78
79 nsCOMPtr<nsIPrincipal> storagePrincipal;
80 rv = StoragePrincipalHelper::Create(mockChannel, contentPrincipal, true,
81 getter_AddRefs(storagePrincipal));
82 ASSERT_EQ(rv, NS_OK) << "Should not fail for ContentPrincipal";
83 EXPECT_TRUE(storagePrincipal);
84
85 nsCOMPtr<nsIPrincipal> storagePrincipalSW;
86 rv = StoragePrincipalHelper::CreatePartitionedPrincipalForServiceWorker(
87 contentPrincipal, cookieJarSettings, getter_AddRefs(storagePrincipalSW));
88 ASSERT_EQ(rv, NS_OK) << "Should not fail for ContentPrincipal";
89 EXPECT_TRUE(storagePrincipalSW);
90 }
91
TEST(TestStoragePrincipalHelper,TestCreateNullPrincipal)92 TEST(TestStoragePrincipalHelper, TestCreateNullPrincipal)
93 {
94 RefPtr<NullPrincipal> nullPrincipal =
95 NullPrincipal::CreateWithoutOriginAttributes();
96 EXPECT_TRUE(nullPrincipal);
97
98 nsCOMPtr<nsIChannel> mockChannel;
99 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
100 nsresult rv = CreateMockChannel(
101 nullPrincipal, false, "https://example.org"_ns,
102 getter_AddRefs(mockChannel), getter_AddRefs(cookieJarSettings));
103 ASSERT_EQ(rv, NS_OK) << "Could not create a mock channel";
104
105 nsCOMPtr<nsIPrincipal> storagePrincipal;
106 rv = StoragePrincipalHelper::Create(mockChannel, nullPrincipal, true,
107 getter_AddRefs(storagePrincipal));
108 EXPECT_TRUE(NS_FAILED(rv)) << "Should fail for NullPrincipal";
109 EXPECT_FALSE(storagePrincipal);
110
111 nsCOMPtr<nsIPrincipal> storagePrincipalSW;
112 rv = StoragePrincipalHelper::CreatePartitionedPrincipalForServiceWorker(
113 nullPrincipal, cookieJarSettings, getter_AddRefs(storagePrincipalSW));
114 EXPECT_TRUE(NS_FAILED(rv)) << "Should fail for NullPrincipal";
115 EXPECT_FALSE(storagePrincipal);
116 }
117
TEST(TestStoragePrincipalHelper,TestGetPrincipalCookieBehavior4)118 TEST(TestStoragePrincipalHelper, TestGetPrincipalCookieBehavior4)
119 {
120 Preferences::SetInt("network.cookie.cookieBehavior", 4);
121
122 nsCOMPtr<nsIPrincipal> contentPrincipal =
123 BasePrincipal::CreateContentPrincipal("https://example.com"_ns);
124 EXPECT_TRUE(contentPrincipal);
125
126 for (auto isThirdParty : {false, true}) {
127 nsCOMPtr<nsIChannel> mockChannel;
128 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
129 nsresult rv = CreateMockChannel(
130 contentPrincipal, isThirdParty, "https://example.org"_ns,
131 getter_AddRefs(mockChannel), getter_AddRefs(cookieJarSettings));
132 ASSERT_EQ(rv, NS_OK) << "Could not create a mock channel";
133
134 nsCOMPtr<nsIPrincipal> testPrincipal;
135 rv = StoragePrincipalHelper::GetPrincipal(
136 mockChannel, StoragePrincipalHelper::eRegularPrincipal,
137 getter_AddRefs(testPrincipal));
138 ASSERT_EQ(rv, NS_OK) << "Could not get regular principal";
139 EXPECT_TRUE(testPrincipal);
140 EXPECT_TRUE(testPrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
141
142 rv = StoragePrincipalHelper::GetPrincipal(
143 mockChannel, StoragePrincipalHelper::ePartitionedPrincipal,
144 getter_AddRefs(testPrincipal));
145 ASSERT_EQ(rv, NS_OK) << "Could not get partitioned principal";
146 EXPECT_TRUE(testPrincipal);
147 EXPECT_TRUE(
148 testPrincipal->OriginAttributesRef().mPartitionKey.EqualsLiteral(
149 "(https,example.org)"));
150
151 // We should always get regular principal if the dFPI is disabled.
152 rv = StoragePrincipalHelper::GetPrincipal(
153 mockChannel, StoragePrincipalHelper::eForeignPartitionedPrincipal,
154 getter_AddRefs(testPrincipal));
155 ASSERT_EQ(rv, NS_OK) << "Could not get foreign partitioned principal";
156 EXPECT_TRUE(testPrincipal);
157 EXPECT_TRUE(testPrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
158
159 // Note that we don't test eStorageAccessPrincipal here because it's hard to
160 // setup the right state for the storage access in gTest.
161 }
162 }
163
TEST(TestStoragePrincipalHelper,TestGetPrincipalCookieBehavior5)164 TEST(TestStoragePrincipalHelper, TestGetPrincipalCookieBehavior5)
165 {
166 Preferences::SetInt("network.cookie.cookieBehavior", 5);
167
168 nsCOMPtr<nsIPrincipal> contentPrincipal =
169 BasePrincipal::CreateContentPrincipal("https://example.com"_ns);
170 EXPECT_TRUE(contentPrincipal);
171
172 for (auto isThirdParty : {false, true}) {
173 nsCOMPtr<nsIChannel> mockChannel;
174 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
175 nsresult rv = CreateMockChannel(
176 contentPrincipal, isThirdParty, "https://example.org"_ns,
177 getter_AddRefs(mockChannel), getter_AddRefs(cookieJarSettings));
178 ASSERT_EQ(rv, NS_OK) << "Could not create a mock channel";
179
180 nsCOMPtr<nsIPrincipal> testPrincipal;
181 rv = StoragePrincipalHelper::GetPrincipal(
182 mockChannel, StoragePrincipalHelper::eRegularPrincipal,
183 getter_AddRefs(testPrincipal));
184 ASSERT_EQ(rv, NS_OK) << "Could not get regular principal";
185 EXPECT_TRUE(testPrincipal);
186 EXPECT_TRUE(testPrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
187
188 rv = StoragePrincipalHelper::GetPrincipal(
189 mockChannel, StoragePrincipalHelper::ePartitionedPrincipal,
190 getter_AddRefs(testPrincipal));
191 ASSERT_EQ(rv, NS_OK) << "Could not get partitioned principal";
192 EXPECT_TRUE(testPrincipal);
193 EXPECT_TRUE(
194 testPrincipal->OriginAttributesRef().mPartitionKey.EqualsLiteral(
195 "(https,example.org)"));
196
197 // We should always get regular principal if the dFPI is disabled.
198 rv = StoragePrincipalHelper::GetPrincipal(
199 mockChannel, StoragePrincipalHelper::eForeignPartitionedPrincipal,
200 getter_AddRefs(testPrincipal));
201 ASSERT_EQ(rv, NS_OK) << "Could not get foreign partitioned principal";
202 EXPECT_TRUE(testPrincipal);
203 if (isThirdParty) {
204 EXPECT_TRUE(
205 testPrincipal->OriginAttributesRef().mPartitionKey.EqualsLiteral(
206 "(https,example.org)"));
207 } else {
208 EXPECT_TRUE(testPrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
209 }
210
211 // Note that we don't test eStorageAccessPrincipal here because it's hard to
212 // setup the right state for the storage access in gTest.
213 }
214 }
215