Back to index

lightning-sunbird  0.9+nobinonly
nsStyleSheetService.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * IBM Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2005
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Brian Ryner <bryner@brianryner.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsStyleSheetService.h"
00040 #include "nsIStyleSheet.h"
00041 #include "nsICSSLoader.h"
00042 #include "nsICSSStyleSheet.h"
00043 #include "nsIURI.h"
00044 #include "nsContentCID.h"
00045 #include "nsCOMPtr.h"
00046 #include "nsIServiceManager.h"
00047 #include "nsICategoryManager.h"
00048 #include "nsISupportsPrimitives.h"
00049 #include "nsNetUtil.h"
00050 
00051 static NS_DEFINE_CID(kCSSLoaderCID, NS_CSS_LOADER_CID);
00052 
00053 nsStyleSheetService *nsStyleSheetService::gInstance = nsnull;
00054 
00055 nsStyleSheetService::nsStyleSheetService()
00056 {
00057   NS_ASSERTION(0 == AGENT_SHEET && 1 == USER_SHEET, "Invalid value for USER_SHEET or AGENT_SHEET");
00058   NS_ASSERTION(!gInstance, "Someone is using CreateInstance instead of GetService");
00059   gInstance = this;
00060 }
00061 
00062 nsStyleSheetService::~nsStyleSheetService()
00063 {
00064   gInstance = nsnull;
00065 }
00066 
00067 NS_IMPL_ISUPPORTS1(nsStyleSheetService, nsIStyleSheetService)
00068 
00069 void
00070 nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager  *aManager,
00071                                             const char          *aCategory,
00072                                             nsISimpleEnumerator *aEnumerator,
00073                                             PRUint32             aSheetType)
00074 {
00075   if (!aEnumerator)
00076     return;
00077 
00078   PRBool hasMore;
00079   while (NS_SUCCEEDED(aEnumerator->HasMoreElements(&hasMore)) && hasMore) {
00080     nsCOMPtr<nsISupports> element;
00081     if (NS_FAILED(aEnumerator->GetNext(getter_AddRefs(element))))
00082       break;
00083 
00084     nsCOMPtr<nsISupportsCString> icStr = do_QueryInterface(element);
00085     NS_ASSERTION(icStr,
00086                  "category manager entries must be nsISupportsCStrings");
00087 
00088     nsCAutoString name;
00089     icStr->GetData(name);
00090 
00091     nsXPIDLCString spec;
00092     aManager->GetCategoryEntry(aCategory, name.get(), getter_Copies(spec));
00093 
00094     nsCOMPtr<nsIURI> uri;
00095     NS_NewURI(getter_AddRefs(uri), spec);
00096     if (uri)
00097       LoadAndRegisterSheet(uri, aSheetType);
00098   }
00099 }
00100 
00101 PRInt32
00102 nsStyleSheetService::FindSheetByURI(const nsCOMArray<nsIStyleSheet> &sheets,
00103                                     nsIURI *sheetURI)
00104 {
00105   for (PRInt32 i = sheets.Count() - 1; i >= 0; i-- ) {
00106     PRBool bEqual;
00107     nsCOMPtr<nsIURI> uri;
00108     if (NS_SUCCEEDED(sheets[i]->GetSheetURI(getter_AddRefs(uri)))
00109         && uri
00110         && NS_SUCCEEDED(uri->Equals(sheetURI, &bEqual))
00111         && bEqual) {
00112       return i;
00113     }
00114   }
00115 
00116   return -1;
00117 }
00118 
00119 nsresult
00120 nsStyleSheetService::Init()
00121 {
00122   // Enumerate all of the style sheet URIs registered in the category
00123   // manager and load them.
00124 
00125   nsCOMPtr<nsICategoryManager> catMan =
00126     do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
00127 
00128   NS_ENSURE_TRUE(catMan, NS_ERROR_OUT_OF_MEMORY);
00129 
00130   nsCOMPtr<nsISimpleEnumerator> sheets;
00131   catMan->EnumerateCategory("agent-style-sheets", getter_AddRefs(sheets));
00132   RegisterFromEnumerator(catMan, "agent-style-sheets", sheets, AGENT_SHEET);
00133 
00134   catMan->EnumerateCategory("user-style-sheets", getter_AddRefs(sheets));
00135   RegisterFromEnumerator(catMan, "user-style-sheets", sheets, USER_SHEET);
00136 
00137   return NS_OK;
00138 }
00139 
00140 NS_IMETHODIMP
00141 nsStyleSheetService::LoadAndRegisterSheet(nsIURI *aSheetURI,
00142                                           PRUint32 aSheetType)
00143 {
00144   NS_ENSURE_ARG(aSheetType == AGENT_SHEET || aSheetType == USER_SHEET);
00145   NS_ENSURE_ARG_POINTER(aSheetURI);
00146 
00147   nsCOMPtr<nsICSSLoader_MOZILLA_1_8_BRANCH> loader = do_CreateInstance(kCSSLoaderCID);
00148   nsCOMPtr<nsICSSStyleSheet> sheet;
00149   nsresult rv = loader->LoadSheetSync(aSheetURI, aSheetType == AGENT_SHEET,
00150                                       getter_AddRefs(sheet));
00151   NS_ENSURE_SUCCESS(rv, rv);
00152 
00153   mSheets[aSheetType].AppendObject(sheet);
00154 
00155   return NS_OK;
00156 }
00157 
00158 NS_IMETHODIMP
00159 nsStyleSheetService::SheetRegistered(nsIURI *sheetURI,
00160                                      PRUint32 aSheetType, PRBool *_retval)
00161 {
00162   NS_ENSURE_ARG(aSheetType == AGENT_SHEET || aSheetType == USER_SHEET);
00163   NS_ENSURE_ARG_POINTER(sheetURI);
00164   NS_PRECONDITION(_retval, "Null out param");
00165 
00166   *_retval = (FindSheetByURI(mSheets[aSheetType], sheetURI) >= 0);
00167 
00168   return NS_OK;
00169 }
00170 
00171 NS_IMETHODIMP
00172 nsStyleSheetService::UnregisterSheet(nsIURI *sheetURI, PRUint32 aSheetType)
00173 {
00174   NS_ENSURE_ARG(aSheetType == AGENT_SHEET || aSheetType == USER_SHEET);
00175   NS_ENSURE_ARG_POINTER(sheetURI);
00176 
00177   PRInt32 foundIndex = FindSheetByURI(mSheets[aSheetType], sheetURI);
00178   NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
00179   mSheets[aSheetType].RemoveObjectAt(foundIndex);
00180 
00181   return NS_OK;
00182 }