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
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.
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"
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
)
76 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLResourceLoader
)
77 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLResourceLoader
)
79 nsXBLResourceLoader::nsXBLResourceLoader(nsXBLPrototypeBinding
* aBinding
,
80 nsXBLPrototypeResources
* aResources
)
82 mResources(aResources
),
83 mResourceList(nsnull
),
84 mLastResource(nsnull
),
85 mLoadingResources(PR_FALSE
),
86 mInLoadResourcesFunc(PR_FALSE
),
91 nsXBLResourceLoader::~nsXBLResourceLoader()
97 nsXBLResourceLoader::LoadResources(PRBool
* aResult
)
99 mInLoadResourcesFunc
= PR_TRUE
;
101 if (mLoadingResources
) {
102 *aResult
= (mPendingSheets
== 0);
103 mInLoadResourcesFunc
= PR_FALSE
;
107 mLoadingResources
= 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())
124 if (NS_FAILED(NS_NewURI(getter_AddRefs(url
), curr
->mSrc
,
125 doc
->GetDocumentCharacterSet().get(), docURL
)))
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...
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?
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!!!");
162 rv
= cssLoader
->LoadSheet(url
, docPrincipal
, this);
163 if (NS_SUCCEEDED(rv
))
169 *aResult
= (mPendingSheets
== 0);
170 mInLoadResourcesFunc
= PR_FALSE
;
172 // Destroy our resource list.
173 delete mResourceList
;
174 mResourceList
= nsnull
;
177 // nsICSSLoaderObserver
179 nsXBLResourceLoader::StyleSheetLoaded(nsICSSStyleSheet
* aSheet
,
180 PRBool aWasAlternate
,
184 // Our resources got destroyed -- just bail out
188 mResources
->mStyleSheetList
.AppendObject(aSheet
);
190 if (!mInLoadResourcesFunc
)
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();
207 nsXBLResourceLoader::AddResource(nsIAtom
* aResourceType
, const nsAString
& aSrc
)
209 nsXBLResource
* res
= new nsXBLResource(aResourceType
, aSrc
);
216 mLastResource
->mNext
= res
;
222 nsXBLResourceLoader::AddResourceListener(nsIContent
* aBoundElement
)
225 mBoundElements
.AppendObject(aBoundElement
);
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
);
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();
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
260 nsIPresShell
*shell
= doc
->GetPrimaryShell();
262 nsIFrame
* childFrame
= shell
->GetPrimaryFrameFor(content
);
264 // Check to see if it's in the undisplayed content map.
266 shell
->FrameManager()->GetUndisplayedContent(content
);
269 shell
->RecreateFramesFor(content
);
275 // XXXbz why is this needed?
276 doc
->FlushPendingNotifications(Flush_ContentAndNotify
);
281 // Clear out the whole array.
282 mBoundElements
.Clear();
285 NS_RELEASE(mResources
->mLoader
);