Line data Source code
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 "nsIStyleRuleProcessor.h"
8 : #include "nsIDocument.h"
9 : #include "nsIContent.h"
10 : #include "nsIServiceManager.h"
11 : #include "nsXBLResourceLoader.h"
12 : #include "nsXBLPrototypeResources.h"
13 : #include "nsXBLPrototypeBinding.h"
14 : #include "nsIDocumentObserver.h"
15 : #include "mozilla/css/Loader.h"
16 : #include "nsIURI.h"
17 : #include "nsLayoutCID.h"
18 : #include "nsCSSRuleProcessor.h"
19 : #include "nsStyleSet.h"
20 : #include "mozilla/dom/URL.h"
21 : #include "mozilla/DebugOnly.h"
22 : #include "mozilla/StyleSheet.h"
23 : #include "mozilla/StyleSheetInlines.h"
24 :
25 : using namespace mozilla;
26 : using mozilla::dom::IsChromeURI;
27 :
28 30 : nsXBLPrototypeResources::nsXBLPrototypeResources(nsXBLPrototypeBinding* aBinding)
29 : {
30 30 : MOZ_COUNT_CTOR(nsXBLPrototypeResources);
31 :
32 30 : mLoader = new nsXBLResourceLoader(aBinding, this);
33 30 : }
34 :
35 0 : nsXBLPrototypeResources::~nsXBLPrototypeResources()
36 : {
37 0 : MOZ_COUNT_DTOR(nsXBLPrototypeResources);
38 0 : if (mLoader) {
39 0 : mLoader->mResources = nullptr;
40 : }
41 0 : if (mServoStyleSet) {
42 0 : mServoStyleSet->Shutdown();
43 : }
44 0 : }
45 :
46 : void
47 39 : nsXBLPrototypeResources::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
48 : {
49 39 : if (mLoader)
50 39 : mLoader->AddResource(aResourceType, aSrc);
51 39 : }
52 :
53 : bool
54 164 : nsXBLPrototypeResources::LoadResources(nsIContent* aBoundElement)
55 : {
56 164 : if (mLoader) {
57 164 : return mLoader->LoadResources(aBoundElement);
58 : }
59 :
60 0 : return true; // All resources loaded.
61 : }
62 :
63 : void
64 0 : nsXBLPrototypeResources::AddResourceListener(nsIContent* aBoundElement)
65 : {
66 0 : if (mLoader)
67 0 : mLoader->AddResourceListener(aBoundElement);
68 0 : }
69 :
70 : nsresult
71 0 : nsXBLPrototypeResources::FlushSkinSheets()
72 : {
73 0 : if (mStyleSheetList.Length() == 0)
74 0 : return NS_OK;
75 :
76 : nsCOMPtr<nsIDocument> doc =
77 0 : mLoader->mBinding->XBLDocumentInfo()->GetDocument();
78 :
79 : // If doc is null, we're in the process of tearing things down, so just
80 : // return without rebuilding anything.
81 0 : if (!doc) {
82 0 : return NS_OK;
83 : }
84 :
85 : // We have scoped stylesheets. Reload any chrome stylesheets we
86 : // encounter. (If they aren't skin sheets, it doesn't matter, since
87 : // they'll still be in the chrome cache. Skip inline sheets, which
88 : // skin sheets can't be, and which in any case don't have a usable
89 : // URL to reload.)
90 :
91 0 : nsTArray<RefPtr<StyleSheet>> oldSheets;
92 :
93 0 : oldSheets.SwapElements(mStyleSheetList);
94 :
95 0 : mozilla::css::Loader* cssLoader = doc->CSSLoader();
96 :
97 0 : for (size_t i = 0, count = oldSheets.Length(); i < count; ++i) {
98 0 : StyleSheet* oldSheet = oldSheets[i];
99 :
100 0 : nsIURI* uri = oldSheet->GetSheetURI();
101 :
102 0 : RefPtr<StyleSheet> newSheet;
103 0 : if (!oldSheet->IsInline() && IsChromeURI(uri)) {
104 0 : if (NS_FAILED(cssLoader->LoadSheetSync(uri, &newSheet)))
105 0 : continue;
106 : }
107 : else {
108 0 : newSheet = oldSheet;
109 : }
110 :
111 0 : mStyleSheetList.AppendElement(newSheet);
112 : }
113 :
114 0 : GatherRuleProcessor();
115 :
116 0 : return NS_OK;
117 : }
118 :
119 : nsresult
120 0 : nsXBLPrototypeResources::Write(nsIObjectOutputStream* aStream)
121 : {
122 0 : if (mLoader)
123 0 : return mLoader->Write(aStream);
124 0 : return NS_OK;
125 : }
126 :
127 : void
128 0 : nsXBLPrototypeResources::Traverse(nsCycleCollectionTraversalCallback &cb)
129 : {
130 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "proto mResources mLoader");
131 0 : cb.NoteXPCOMChild(mLoader);
132 :
133 0 : CycleCollectionNoteChild(cb, mRuleProcessor.get(), "mRuleProcessor");
134 0 : ImplCycleCollectionTraverse(cb, mStyleSheetList, "mStyleSheetList");
135 0 : }
136 :
137 : void
138 0 : nsXBLPrototypeResources::Unlink()
139 : {
140 0 : mStyleSheetList.Clear();
141 0 : mRuleProcessor = nullptr;
142 0 : }
143 :
144 : void
145 0 : nsXBLPrototypeResources::ClearLoader()
146 : {
147 0 : mLoader = nullptr;
148 0 : }
149 :
150 : void
151 32 : nsXBLPrototypeResources::GatherRuleProcessor()
152 : {
153 64 : nsTArray<RefPtr<CSSStyleSheet>> sheets(mStyleSheetList.Length());
154 74 : for (StyleSheet* sheet : mStyleSheetList) {
155 42 : MOZ_ASSERT(sheet->IsGecko(),
156 : "GatherRuleProcessor must only be called for "
157 : "nsXBLPrototypeResources objects with Gecko-flavored style "
158 : "backends");
159 42 : sheets.AppendElement(sheet->AsGecko());
160 : }
161 : mRuleProcessor = new nsCSSRuleProcessor(Move(sheets),
162 : SheetType::Doc,
163 : nullptr,
164 64 : mRuleProcessor);
165 32 : }
166 :
167 : void
168 0 : nsXBLPrototypeResources::ComputeServoStyleSet(nsPresContext* aPresContext)
169 : {
170 0 : mServoStyleSet.reset(new ServoStyleSet());
171 0 : mServoStyleSet->Init(aPresContext, nullptr);
172 0 : for (StyleSheet* sheet : mStyleSheetList) {
173 0 : MOZ_ASSERT(sheet->IsServo(),
174 : "This should only be called with Servo-flavored style backend!");
175 : // The sheets aren't document sheets, but we need to decide a particular
176 : // SheetType so that we can pull them out from the right place on the
177 : // Servo side.
178 0 : mServoStyleSet->AppendStyleSheet(SheetType::Doc, sheet->AsServo());
179 : }
180 0 : mServoStyleSet->UpdateStylistIfNeeded();
181 0 : }
182 :
183 : void
184 32 : nsXBLPrototypeResources::AppendStyleSheet(StyleSheet* aSheet)
185 : {
186 32 : mStyleSheetList.AppendElement(aSheet);
187 32 : }
188 :
189 : void
190 0 : nsXBLPrototypeResources::RemoveStyleSheet(StyleSheet* aSheet)
191 : {
192 0 : mStyleSheetList.RemoveElement(aSheet);
193 0 : }
194 :
195 : void
196 0 : nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, StyleSheet* aSheet)
197 : {
198 0 : mStyleSheetList.InsertElementAt(aIndex, aSheet);
199 0 : }
200 :
201 : StyleSheet*
202 0 : nsXBLPrototypeResources::StyleSheetAt(size_t aIndex) const
203 : {
204 0 : return mStyleSheetList[aIndex];
205 : }
206 :
207 : size_t
208 0 : nsXBLPrototypeResources::SheetCount() const
209 : {
210 0 : return mStyleSheetList.Length();
211 : }
212 :
213 : bool
214 155 : nsXBLPrototypeResources::HasStyleSheets() const
215 : {
216 155 : return !mStyleSheetList.IsEmpty();
217 : }
218 :
219 : void
220 0 : nsXBLPrototypeResources::AppendStyleSheetsTo(
221 : nsTArray<StyleSheet*>& aResult) const
222 : {
223 0 : aResult.AppendElements(mStyleSheetList);
224 0 : }
|