Follow-on fix for bug 457825. Use sheet principal for agent and user sheets. r=dbaron...
[wine-gecko.git] / content / xbl / src / nsXBLResourceLoader.cpp
blobef5fd477f3932cd012eb91eb4f2077602d7bb5df
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Original Author: David W. Hyatt (hyatt@netscape.com)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsICSSStyleSheet.h"
40 #include "nsIStyleRuleProcessor.h"
41 #include "nsIDocument.h"
42 #include "nsIContent.h"
43 #include "nsIPresShell.h"
44 #include "nsIXBLService.h"
45 #include "nsIServiceManager.h"
46 #include "nsXBLResourceLoader.h"
47 #include "nsXBLPrototypeResources.h"
48 #include "nsIDocumentObserver.h"
49 #include "imgILoader.h"
50 #include "imgIRequest.h"
51 #include "nsICSSLoader.h"
52 #include "nsIXBLDocumentInfo.h"
53 #include "nsIURI.h"
54 #include "nsNetUtil.h"
55 #include "nsGkAtoms.h"
56 #include "nsFrameManager.h"
57 #include "nsStyleContext.h"
58 #include "nsXBLPrototypeBinding.h"
59 #include "nsCSSRuleProcessor.h"
60 #include "nsContentUtils.h"
61 #include "nsStyleSet.h"
63 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLResourceLoader)
64 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLResourceLoader)
65 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mBoundElements)
66 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
67 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLResourceLoader)
68 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mBoundElements)
69 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
71 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLResourceLoader)
72 NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
73 NS_INTERFACE_MAP_ENTRY(nsISupports)
74 NS_INTERFACE_MAP_END
76 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLResourceLoader)
77 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLResourceLoader)
79 nsXBLResourceLoader::nsXBLResourceLoader(nsXBLPrototypeBinding* aBinding,
80 nsXBLPrototypeResources* aResources)
81 :mBinding(aBinding),
82 mResources(aResources),
83 mResourceList(nsnull),
84 mLastResource(nsnull),
85 mLoadingResources(PR_FALSE),
86 mInLoadResourcesFunc(PR_FALSE),
87 mPendingSheets(0)
91 nsXBLResourceLoader::~nsXBLResourceLoader()
93 delete mResourceList;
96 void
97 nsXBLResourceLoader::LoadResources(PRBool* aResult)
99 mInLoadResourcesFunc = PR_TRUE;
101 if (mLoadingResources) {
102 *aResult = (mPendingSheets == 0);
103 mInLoadResourcesFunc = PR_FALSE;
104 return;
107 mLoadingResources = PR_TRUE;
108 *aResult = PR_TRUE;
110 // Declare our loaders.
111 nsCOMPtr<nsIDocument> doc;
112 mBinding->XBLDocumentInfo()->GetDocument(getter_AddRefs(doc));
114 nsICSSLoader* cssLoader = doc->CSSLoader();
115 nsIURI *docURL = doc->GetDocumentURI();
116 nsIPrincipal* docPrincipal = doc->NodePrincipal();
118 nsCOMPtr<nsIURI> url;
120 for (nsXBLResource* curr = mResourceList; curr; curr = curr->mNext) {
121 if (curr->mSrc.IsEmpty())
122 continue;
124 if (NS_FAILED(NS_NewURI(getter_AddRefs(url), curr->mSrc,
125 doc->GetDocumentCharacterSet().get(), docURL)))
126 continue;
128 if (curr->mType == nsGkAtoms::image) {
129 if (!nsContentUtils::CanLoadImage(url, doc, doc, docPrincipal)) {
130 // We're not permitted to load this image, move on...
131 continue;
134 // Now kick off the image load...
135 // Passing NULL for pretty much everything -- cause we don't care!
136 // XXX: initialDocumentURI is NULL!
137 nsCOMPtr<imgIRequest> req;
138 nsContentUtils::LoadImage(url, doc, docPrincipal, docURL, nsnull,
139 nsIRequest::LOAD_BACKGROUND,
140 getter_AddRefs(req));
142 else if (curr->mType == nsGkAtoms::stylesheet) {
143 // Kick off the load of the stylesheet.
145 // Always load chrome synchronously
146 // XXXbz should that still do a content policy check?
147 PRBool chrome;
148 nsresult rv;
149 if (NS_SUCCEEDED(url->SchemeIs("chrome", &chrome)) && chrome)
151 nsCOMPtr<nsICSSStyleSheet> sheet;
152 rv = cssLoader->LoadSheetSync(url, getter_AddRefs(sheet));
153 NS_ASSERTION(NS_SUCCEEDED(rv), "Load failed!!!");
154 if (NS_SUCCEEDED(rv))
156 rv = StyleSheetLoaded(sheet, PR_FALSE, NS_OK);
157 NS_ASSERTION(NS_SUCCEEDED(rv), "Processing the style sheet failed!!!");
160 else
162 rv = cssLoader->LoadSheet(url, docPrincipal, this);
163 if (NS_SUCCEEDED(rv))
164 ++mPendingSheets;
169 *aResult = (mPendingSheets == 0);
170 mInLoadResourcesFunc = PR_FALSE;
172 // Destroy our resource list.
173 delete mResourceList;
174 mResourceList = nsnull;
177 // nsICSSLoaderObserver
178 NS_IMETHODIMP
179 nsXBLResourceLoader::StyleSheetLoaded(nsICSSStyleSheet* aSheet,
180 PRBool aWasAlternate,
181 nsresult aStatus)
183 if (!mResources) {
184 // Our resources got destroyed -- just bail out
185 return NS_OK;
188 mResources->mStyleSheetList.AppendObject(aSheet);
190 if (!mInLoadResourcesFunc)
191 mPendingSheets--;
193 if (mPendingSheets == 0) {
194 // All stylesheets are loaded.
195 mResources->mRuleProcessor =
196 new nsCSSRuleProcessor(mResources->mStyleSheetList,
197 nsStyleSet::eDocSheet);
199 // XXX Check for mPendingScripts when scripts also come online.
200 if (!mInLoadResourcesFunc)
201 NotifyBoundElements();
203 return NS_OK;
206 void
207 nsXBLResourceLoader::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
209 nsXBLResource* res = new nsXBLResource(aResourceType, aSrc);
210 if (!res)
211 return;
213 if (!mResourceList)
214 mResourceList = res;
215 else
216 mLastResource->mNext = res;
218 mLastResource = res;
221 void
222 nsXBLResourceLoader::AddResourceListener(nsIContent* aBoundElement)
224 if (aBoundElement) {
225 mBoundElements.AppendObject(aBoundElement);
229 void
230 nsXBLResourceLoader::NotifyBoundElements()
232 nsCOMPtr<nsIXBLService> xblService(do_GetService("@mozilla.org/xbl;1"));
233 nsIURI* bindingURI = mBinding->BindingURI();
235 PRUint32 eltCount = mBoundElements.Count();
236 for (PRUint32 j = 0; j < eltCount; j++) {
237 nsCOMPtr<nsIContent> content = mBoundElements.ObjectAt(j);
239 PRBool ready = PR_FALSE;
240 xblService->BindingReady(content, bindingURI, &ready);
242 if (ready) {
243 // We need the document to flush out frame construction and
244 // such, so we want to use the current document.
245 nsIDocument* doc = content->GetCurrentDoc();
247 if (doc) {
248 // Flush first to make sure we can get the frame for content
249 doc->FlushPendingNotifications(Flush_Frames);
251 // If |content| is (in addition to having binding |mBinding|)
252 // also a descendant of another element with binding |mBinding|,
253 // then we might have just constructed it due to the
254 // notification of its parent. (We can know about both if the
255 // binding loads were triggered from the DOM rather than frame
256 // construction.) So we have to check both whether the element
257 // has a primary frame and whether it's in the undisplayed map
258 // before sending a ContentInserted notification, or bad things
259 // will happen.
260 nsIPresShell *shell = doc->GetPrimaryShell();
261 if (shell) {
262 nsIFrame* childFrame = shell->GetPrimaryFrameFor(content);
263 if (!childFrame) {
264 // Check to see if it's in the undisplayed content map.
265 nsStyleContext* sc =
266 shell->FrameManager()->GetUndisplayedContent(content);
268 if (!sc) {
269 shell->RecreateFramesFor(content);
274 // Flush again
275 // XXXbz why is this needed?
276 doc->FlushPendingNotifications(Flush_ContentAndNotify);
281 // Clear out the whole array.
282 mBoundElements.Clear();
284 // Delete ourselves.
285 NS_RELEASE(mResources->mLoader);