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 "nsICSSLoader.h"
45 #include "nsICSSStyleSheet.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"
55 static NS_DEFINE_CID(kCSSLoaderCID
, NS_CSS_LOADER_CID
);
57 nsStyleSheetService
*nsStyleSheetService::gInstance
= nsnull
;
59 nsStyleSheetService::nsStyleSheetService()
61 PR_STATIC_ASSERT(0 == AGENT_SHEET
&& 1 == USER_SHEET
);
62 NS_ASSERTION(!gInstance
, "Someone is using CreateInstance instead of GetService");
66 nsStyleSheetService::~nsStyleSheetService()
71 NS_IMPL_ISUPPORTS1(nsStyleSheetService
, nsIStyleSheetService
)
74 nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager
*aManager
,
75 const char *aCategory
,
76 nsISimpleEnumerator
*aEnumerator
,
83 while (NS_SUCCEEDED(aEnumerator
->HasMoreElements(&hasMore
)) && hasMore
) {
84 nsCOMPtr
<nsISupports
> element
;
85 if (NS_FAILED(aEnumerator
->GetNext(getter_AddRefs(element
))))
88 nsCOMPtr
<nsISupportsCString
> icStr
= do_QueryInterface(element
);
90 "category manager entries must be nsISupportsCStrings");
96 aManager
->GetCategoryEntry(aCategory
, name
.get(), getter_Copies(spec
));
99 NS_NewURI(getter_AddRefs(uri
), spec
);
101 LoadAndRegisterSheetInternal(uri
, aSheetType
);
106 nsStyleSheetService::FindSheetByURI(const nsCOMArray
<nsIStyleSheet
> &sheets
,
109 for (PRInt32 i
= sheets
.Count() - 1; i
>= 0; i
-- ) {
111 nsCOMPtr
<nsIURI
> uri
;
112 if (NS_SUCCEEDED(sheets
[i
]->GetSheetURI(getter_AddRefs(uri
)))
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 do_GetService("@mozilla.org/observer-service;1");
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 nsCOMPtr
<nsICSSLoader
> loader
= do_CreateInstance(kCSSLoaderCID
);
172 nsCOMPtr
<nsICSSStyleSheet
> sheet
;
173 // Allow UA sheets, but not user sheets, to use unsafe rules
174 nsresult rv
= loader
->LoadSheetSync(aSheetURI
, aSheetType
== AGENT_SHEET
,
175 getter_AddRefs(sheet
));
176 NS_ENSURE_SUCCESS(rv
, rv
);
178 if (!mSheets
[aSheetType
].AppendObject(sheet
)) {
179 rv
= NS_ERROR_OUT_OF_MEMORY
;
186 nsStyleSheetService::SheetRegistered(nsIURI
*sheetURI
,
187 PRUint32 aSheetType
, PRBool
*_retval
)
189 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
);
190 NS_ENSURE_ARG_POINTER(sheetURI
);
191 NS_PRECONDITION(_retval
, "Null out param");
193 *_retval
= (FindSheetByURI(mSheets
[aSheetType
], sheetURI
) >= 0);
199 nsStyleSheetService::UnregisterSheet(nsIURI
*sheetURI
, PRUint32 aSheetType
)
201 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
);
202 NS_ENSURE_ARG_POINTER(sheetURI
);
204 PRInt32 foundIndex
= FindSheetByURI(mSheets
[aSheetType
], sheetURI
);
205 NS_ENSURE_TRUE(foundIndex
>= 0, NS_ERROR_INVALID_ARG
);
206 nsCOMPtr
<nsIStyleSheet
> sheet
= mSheets
[aSheetType
][foundIndex
];
207 mSheets
[aSheetType
].RemoveObjectAt(foundIndex
);
209 const char* message
= (aSheetType
== AGENT_SHEET
) ?
210 "agent-sheet-removed" : "user-sheet-removed";
211 nsCOMPtr
<nsIObserverService
> serv
=
212 do_GetService("@mozilla.org/observer-service;1");
214 serv
->NotifyObservers(sheet
, message
, nsnull
);