Bug 54488 - "[Mac] Non-draggable widgets in background windows should look disabled...
[mozilla-central.git] / layout / base / nsStyleSheetService.cpp
blob33cdc5a1dbe766bc0215e82b48286b0d17044b1e
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.
17 * The Initial Developer of the Original Code is
18 * IBM Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2005
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
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 */
41 #include "prlog.h"
42 #include "nsStyleSheetService.h"
43 #include "nsIStyleSheet.h"
44 #include "nsICSSLoader.h"
45 #include "nsICSSStyleSheet.h"
46 #include "nsIURI.h"
47 #include "nsContentCID.h"
48 #include "nsCOMPtr.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");
63 gInstance = this;
66 nsStyleSheetService::~nsStyleSheetService()
68 gInstance = nsnull;
71 NS_IMPL_ISUPPORTS1(nsStyleSheetService, nsIStyleSheetService)
73 void
74 nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager *aManager,
75 const char *aCategory,
76 nsISimpleEnumerator *aEnumerator,
77 PRUint32 aSheetType)
79 if (!aEnumerator)
80 return;
82 PRBool hasMore;
83 while (NS_SUCCEEDED(aEnumerator->HasMoreElements(&hasMore)) && hasMore) {
84 nsCOMPtr<nsISupports> element;
85 if (NS_FAILED(aEnumerator->GetNext(getter_AddRefs(element))))
86 break;
88 nsCOMPtr<nsISupportsCString> icStr = do_QueryInterface(element);
89 NS_ASSERTION(icStr,
90 "category manager entries must be nsISupportsCStrings");
92 nsCAutoString name;
93 icStr->GetData(name);
95 nsXPIDLCString spec;
96 aManager->GetCategoryEntry(aCategory, name.get(), getter_Copies(spec));
98 nsCOMPtr<nsIURI> uri;
99 NS_NewURI(getter_AddRefs(uri), spec);
100 if (uri)
101 LoadAndRegisterSheetInternal(uri, aSheetType);
105 PRInt32
106 nsStyleSheetService::FindSheetByURI(const nsCOMArray<nsIStyleSheet> &sheets,
107 nsIURI *sheetURI)
109 for (PRInt32 i = sheets.Count() - 1; i >= 0; i-- ) {
110 PRBool bEqual;
111 nsCOMPtr<nsIURI> uri;
112 if (NS_SUCCEEDED(sheets[i]->GetSheetURI(getter_AddRefs(uri)))
113 && uri
114 && NS_SUCCEEDED(uri->Equals(sheetURI, &bEqual))
115 && bEqual) {
116 return i;
120 return -1;
123 nsresult
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);
141 return NS_OK;
144 NS_IMETHODIMP
145 nsStyleSheetService::LoadAndRegisterSheet(nsIURI *aSheetURI,
146 PRUint32 aSheetType)
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");
154 if (serv) {
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);
161 return rv;
164 nsresult
165 nsStyleSheetService::LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
166 PRUint32 aSheetType)
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;
182 return rv;
185 NS_IMETHODIMP
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);
195 return NS_OK;
198 NS_IMETHODIMP
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");
213 if (serv) {
214 serv->NotifyObservers(sheet, message, nsnull);
217 return NS_OK;