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.
17 * The Initial Developer of the Original Code is
19 * Portions created by the Initial Developer are Copyright (C) 2005
20 * the Initial Developer. All Rights Reserved.
23 * Brian Ryner <bryner@brianryner.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * 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 /* implementation of interface for managing user and user-agent style sheets */
42 #include "nsStyleSheetService.h"
43 #include "nsIStyleSheet.h"
44 #include "mozilla/css/Loader.h"
45 #include "nsCSSStyleSheet.h"
47 #include "nsContentCID.h"
49 #include "nsIServiceManager.h"
50 #include "nsICategoryManager.h"
51 #include "nsISupportsPrimitives.h"
52 #include "nsNetUtil.h"
53 #include "nsIObserverService.h"
54 #include "nsLayoutStatics.h"
56 nsStyleSheetService
*nsStyleSheetService::gInstance
= nsnull
;
58 nsStyleSheetService::nsStyleSheetService()
60 PR_STATIC_ASSERT(0 == AGENT_SHEET
&& 1 == USER_SHEET
);
61 NS_ASSERTION(!gInstance
, "Someone is using CreateInstance instead of GetService");
63 nsLayoutStatics::AddRef();
66 nsStyleSheetService::~nsStyleSheetService()
69 nsLayoutStatics::Release();
72 NS_IMPL_ISUPPORTS1(nsStyleSheetService
, nsIStyleSheetService
)
75 nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager
*aManager
,
76 const char *aCategory
,
77 nsISimpleEnumerator
*aEnumerator
,
84 while (NS_SUCCEEDED(aEnumerator
->HasMoreElements(&hasMore
)) && hasMore
) {
85 nsCOMPtr
<nsISupports
> element
;
86 if (NS_FAILED(aEnumerator
->GetNext(getter_AddRefs(element
))))
89 nsCOMPtr
<nsISupportsCString
> icStr
= do_QueryInterface(element
);
91 "category manager entries must be nsISupportsCStrings");
97 aManager
->GetCategoryEntry(aCategory
, name
.get(), getter_Copies(spec
));
100 NS_NewURI(getter_AddRefs(uri
), spec
);
102 LoadAndRegisterSheetInternal(uri
, aSheetType
);
107 nsStyleSheetService::FindSheetByURI(const nsCOMArray
<nsIStyleSheet
> &sheets
,
110 for (PRInt32 i
= sheets
.Count() - 1; i
>= 0; i
-- ) {
112 nsIURI
* uri
= sheets
[i
]->GetSheetURI();
114 && NS_SUCCEEDED(uri
->Equals(sheetURI
, &bEqual
))
124 nsStyleSheetService::Init()
126 // Enumerate all of the style sheet URIs registered in the category
127 // manager and load them.
129 nsCOMPtr
<nsICategoryManager
> catMan
=
130 do_GetService(NS_CATEGORYMANAGER_CONTRACTID
);
132 NS_ENSURE_TRUE(catMan
, NS_ERROR_OUT_OF_MEMORY
);
134 nsCOMPtr
<nsISimpleEnumerator
> sheets
;
135 catMan
->EnumerateCategory("agent-style-sheets", getter_AddRefs(sheets
));
136 RegisterFromEnumerator(catMan
, "agent-style-sheets", sheets
, AGENT_SHEET
);
138 catMan
->EnumerateCategory("user-style-sheets", getter_AddRefs(sheets
));
139 RegisterFromEnumerator(catMan
, "user-style-sheets", sheets
, USER_SHEET
);
145 nsStyleSheetService::LoadAndRegisterSheet(nsIURI
*aSheetURI
,
148 nsresult rv
= LoadAndRegisterSheetInternal(aSheetURI
, aSheetType
);
149 if (NS_SUCCEEDED(rv
)) {
150 const char* message
= (aSheetType
== AGENT_SHEET
) ?
151 "agent-sheet-added" : "user-sheet-added";
152 nsCOMPtr
<nsIObserverService
> serv
=
153 mozilla::services::GetObserverService();
155 // We're guaranteed that the new sheet is the last sheet in
156 // mSheets[aSheetType]
157 const nsCOMArray
<nsIStyleSheet
> & sheets
= mSheets
[aSheetType
];
158 serv
->NotifyObservers(sheets
[sheets
.Count() - 1], message
, nsnull
);
165 nsStyleSheetService::LoadAndRegisterSheetInternal(nsIURI
*aSheetURI
,
168 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
);
169 NS_ENSURE_ARG_POINTER(aSheetURI
);
171 nsRefPtr
<mozilla::css::Loader
> loader
= new mozilla::css::Loader();
172 NS_ENSURE_TRUE(loader
, NS_ERROR_OUT_OF_MEMORY
);
174 nsRefPtr
<nsCSSStyleSheet
> sheet
;
175 // Allow UA sheets, but not user sheets, to use unsafe rules
176 nsresult rv
= loader
->LoadSheetSync(aSheetURI
, aSheetType
== AGENT_SHEET
,
177 PR_TRUE
, getter_AddRefs(sheet
));
178 NS_ENSURE_SUCCESS(rv
, rv
);
180 if (!mSheets
[aSheetType
].AppendObject(sheet
)) {
181 rv
= NS_ERROR_OUT_OF_MEMORY
;
188 nsStyleSheetService::SheetRegistered(nsIURI
*sheetURI
,
189 PRUint32 aSheetType
, PRBool
*_retval
)
191 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
);
192 NS_ENSURE_ARG_POINTER(sheetURI
);
193 NS_PRECONDITION(_retval
, "Null out param");
195 *_retval
= (FindSheetByURI(mSheets
[aSheetType
], sheetURI
) >= 0);
201 nsStyleSheetService::UnregisterSheet(nsIURI
*sheetURI
, PRUint32 aSheetType
)
203 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
);
204 NS_ENSURE_ARG_POINTER(sheetURI
);
206 PRInt32 foundIndex
= FindSheetByURI(mSheets
[aSheetType
], sheetURI
);
207 NS_ENSURE_TRUE(foundIndex
>= 0, NS_ERROR_INVALID_ARG
);
208 nsCOMPtr
<nsIStyleSheet
> sheet
= mSheets
[aSheetType
][foundIndex
];
209 mSheets
[aSheetType
].RemoveObjectAt(foundIndex
);
211 const char* message
= (aSheetType
== AGENT_SHEET
) ?
212 "agent-sheet-removed" : "user-sheet-removed";
213 nsCOMPtr
<nsIObserverService
> serv
=
214 mozilla::services::GetObserverService();
216 serv
->NotifyObservers(sheet
, message
, nsnull
);