Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
6 #include "nsTArray.h"
7 #include "nsString.h"
8 #include "nsCSSStyleSheet.h"
9 #include "nsIStyleRuleProcessor.h"
10 #include "nsIDocument.h"
11 #include "nsIContent.h"
12 #include "nsIPresShell.h"
13 #include "nsXBLService.h"
14 #include "nsIServiceManager.h"
15 #include "nsXBLResourceLoader.h"
16 #include "nsXBLPrototypeResources.h"
17 #include "nsIDocumentObserver.h"
18 #include "imgILoader.h"
19 #include "imgRequestProxy.h"
20 #include "mozilla/css/Loader.h"
21 #include "nsIURI.h"
22 #include "nsNetUtil.h"
23 #include "nsGkAtoms.h"
24 #include "nsFrameManager.h"
25 #include "nsStyleContext.h"
26 #include "nsXBLPrototypeBinding.h"
27 #include "nsCSSRuleProcessor.h"
28 #include "nsContentUtils.h"
29 #include "nsStyleSet.h"
30 #include "nsIScriptSecurityManager.h"
32 NS_IMPL_CYCLE_COLLECTION(nsXBLResourceLoader, mBoundElements)
34 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLResourceLoader)
35 NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
36 NS_INTERFACE_MAP_ENTRY(nsISupports)
37 NS_INTERFACE_MAP_END
39 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLResourceLoader)
40 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLResourceLoader)
42 struct nsXBLResource
43 {
44 nsXBLResource* mNext;
45 nsIAtom* mType;
46 nsString mSrc;
48 nsXBLResource(nsIAtom* aType, const nsAString& aSrc)
49 {
50 MOZ_COUNT_CTOR(nsXBLResource);
51 mNext = nullptr;
52 mType = aType;
53 mSrc = aSrc;
54 }
56 ~nsXBLResource()
57 {
58 MOZ_COUNT_DTOR(nsXBLResource);
59 NS_CONTENT_DELETE_LIST_MEMBER(nsXBLResource, this, mNext);
60 }
61 };
63 nsXBLResourceLoader::nsXBLResourceLoader(nsXBLPrototypeBinding* aBinding,
64 nsXBLPrototypeResources* aResources)
65 :mBinding(aBinding),
66 mResources(aResources),
67 mResourceList(nullptr),
68 mLastResource(nullptr),
69 mLoadingResources(false),
70 mInLoadResourcesFunc(false),
71 mPendingSheets(0)
72 {
73 }
75 nsXBLResourceLoader::~nsXBLResourceLoader()
76 {
77 delete mResourceList;
78 }
80 void
81 nsXBLResourceLoader::LoadResources(bool* aResult)
82 {
83 mInLoadResourcesFunc = true;
85 if (mLoadingResources) {
86 *aResult = (mPendingSheets == 0);
87 mInLoadResourcesFunc = false;
88 return;
89 }
91 mLoadingResources = true;
92 *aResult = true;
94 // Declare our loaders.
95 nsCOMPtr<nsIDocument> doc = mBinding->XBLDocumentInfo()->GetDocument();
97 mozilla::css::Loader* cssLoader = doc->CSSLoader();
98 nsIURI *docURL = doc->GetDocumentURI();
99 nsIPrincipal* docPrincipal = doc->NodePrincipal();
101 nsCOMPtr<nsIURI> url;
103 for (nsXBLResource* curr = mResourceList; curr; curr = curr->mNext) {
104 if (curr->mSrc.IsEmpty())
105 continue;
107 if (NS_FAILED(NS_NewURI(getter_AddRefs(url), curr->mSrc,
108 doc->GetDocumentCharacterSet().get(), docURL)))
109 continue;
111 if (curr->mType == nsGkAtoms::image) {
112 if (!nsContentUtils::CanLoadImage(url, doc, doc, docPrincipal)) {
113 // We're not permitted to load this image, move on...
114 continue;
115 }
117 // Now kick off the image load...
118 // Passing nullptr for pretty much everything -- cause we don't care!
119 // XXX: initialDocumentURI is nullptr!
120 nsRefPtr<imgRequestProxy> req;
121 nsContentUtils::LoadImage(url, doc, docPrincipal, docURL, nullptr,
122 nsIRequest::LOAD_BACKGROUND, EmptyString(),
123 getter_AddRefs(req));
124 }
125 else if (curr->mType == nsGkAtoms::stylesheet) {
126 // Kick off the load of the stylesheet.
128 // Always load chrome synchronously
129 // XXXbz should that still do a content policy check?
130 bool chrome;
131 nsresult rv;
132 if (NS_SUCCEEDED(url->SchemeIs("chrome", &chrome)) && chrome)
133 {
134 rv = nsContentUtils::GetSecurityManager()->
135 CheckLoadURIWithPrincipal(docPrincipal, url,
136 nsIScriptSecurityManager::ALLOW_CHROME);
137 if (NS_SUCCEEDED(rv)) {
138 nsRefPtr<nsCSSStyleSheet> sheet;
139 rv = cssLoader->LoadSheetSync(url, getter_AddRefs(sheet));
140 NS_ASSERTION(NS_SUCCEEDED(rv), "Load failed!!!");
141 if (NS_SUCCEEDED(rv))
142 {
143 rv = StyleSheetLoaded(sheet, false, NS_OK);
144 NS_ASSERTION(NS_SUCCEEDED(rv), "Processing the style sheet failed!!!");
145 }
146 }
147 }
148 else
149 {
150 rv = cssLoader->LoadSheet(url, docPrincipal, EmptyCString(), this);
151 if (NS_SUCCEEDED(rv))
152 ++mPendingSheets;
153 }
154 }
155 }
157 *aResult = (mPendingSheets == 0);
158 mInLoadResourcesFunc = false;
160 // Destroy our resource list.
161 delete mResourceList;
162 mResourceList = nullptr;
163 }
165 // nsICSSLoaderObserver
166 NS_IMETHODIMP
167 nsXBLResourceLoader::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
168 bool aWasAlternate,
169 nsresult aStatus)
170 {
171 if (!mResources) {
172 // Our resources got destroyed -- just bail out
173 return NS_OK;
174 }
176 mResources->mStyleSheetList.AppendElement(aSheet);
178 if (!mInLoadResourcesFunc)
179 mPendingSheets--;
181 if (mPendingSheets == 0) {
182 // All stylesheets are loaded.
183 mResources->mRuleProcessor =
184 new nsCSSRuleProcessor(mResources->mStyleSheetList,
185 nsStyleSet::eDocSheet,
186 nullptr);
188 // XXX Check for mPendingScripts when scripts also come online.
189 if (!mInLoadResourcesFunc)
190 NotifyBoundElements();
191 }
192 return NS_OK;
193 }
195 void
196 nsXBLResourceLoader::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
197 {
198 nsXBLResource* res = new nsXBLResource(aResourceType, aSrc);
199 if (!res)
200 return;
202 if (!mResourceList)
203 mResourceList = res;
204 else
205 mLastResource->mNext = res;
207 mLastResource = res;
208 }
210 void
211 nsXBLResourceLoader::AddResourceListener(nsIContent* aBoundElement)
212 {
213 if (aBoundElement) {
214 mBoundElements.AppendObject(aBoundElement);
215 }
216 }
218 void
219 nsXBLResourceLoader::NotifyBoundElements()
220 {
221 nsXBLService* xblService = nsXBLService::GetInstance();
222 if (!xblService)
223 return;
225 nsIURI* bindingURI = mBinding->BindingURI();
227 uint32_t eltCount = mBoundElements.Count();
228 for (uint32_t j = 0; j < eltCount; j++) {
229 nsCOMPtr<nsIContent> content = mBoundElements.ObjectAt(j);
231 bool ready = false;
232 xblService->BindingReady(content, bindingURI, &ready);
234 if (ready) {
235 // We need the document to flush out frame construction and
236 // such, so we want to use the current document.
237 nsIDocument* doc = content->GetCurrentDoc();
239 if (doc) {
240 // Flush first to make sure we can get the frame for content
241 doc->FlushPendingNotifications(Flush_Frames);
243 // If |content| is (in addition to having binding |mBinding|)
244 // also a descendant of another element with binding |mBinding|,
245 // then we might have just constructed it due to the
246 // notification of its parent. (We can know about both if the
247 // binding loads were triggered from the DOM rather than frame
248 // construction.) So we have to check both whether the element
249 // has a primary frame and whether it's in the undisplayed map
250 // before sending a ContentInserted notification, or bad things
251 // will happen.
252 nsIPresShell *shell = doc->GetShell();
253 if (shell) {
254 nsIFrame* childFrame = content->GetPrimaryFrame();
255 if (!childFrame) {
256 // Check to see if it's in the undisplayed content map.
257 nsStyleContext* sc =
258 shell->FrameManager()->GetUndisplayedContent(content);
260 if (!sc) {
261 shell->RecreateFramesFor(content);
262 }
263 }
264 }
266 // Flush again
267 // XXXbz why is this needed?
268 doc->FlushPendingNotifications(Flush_ContentAndNotify);
269 }
270 }
271 }
273 // Clear out the whole array.
274 mBoundElements.Clear();
276 // Delete ourselves.
277 mResources->ClearLoader();
278 }
280 nsresult
281 nsXBLResourceLoader::Write(nsIObjectOutputStream* aStream)
282 {
283 nsresult rv;
285 for (nsXBLResource* curr = mResourceList; curr; curr = curr->mNext) {
286 if (curr->mType == nsGkAtoms::image)
287 rv = aStream->Write8(XBLBinding_Serialize_Image);
288 else if (curr->mType == nsGkAtoms::stylesheet)
289 rv = aStream->Write8(XBLBinding_Serialize_Stylesheet);
290 else
291 continue;
293 NS_ENSURE_SUCCESS(rv, rv);
295 rv = aStream->WriteWStringZ(curr->mSrc.get());
296 NS_ENSURE_SUCCESS(rv, rv);
297 }
299 return NS_OK;
300 }