layout/base/nsStyleSheetService.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/base/nsStyleSheetService.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,310 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* implementation of interface for managing user and user-agent style sheets */
    1.11 +
    1.12 +#include "nsStyleSheetService.h"
    1.13 +#include "nsIStyleSheet.h"
    1.14 +#include "mozilla/MemoryReporting.h"
    1.15 +#include "mozilla/unused.h"
    1.16 +#include "mozilla/css/Loader.h"
    1.17 +#include "mozilla/dom/ContentParent.h"
    1.18 +#include "mozilla/ipc/URIUtils.h"
    1.19 +#include "nsCSSStyleSheet.h"
    1.20 +#include "nsIURI.h"
    1.21 +#include "nsCOMPtr.h"
    1.22 +#include "nsICategoryManager.h"
    1.23 +#include "nsISupportsPrimitives.h"
    1.24 +#include "nsNetUtil.h"
    1.25 +#include "nsIObserverService.h"
    1.26 +#include "nsLayoutStatics.h"
    1.27 +
    1.28 +using namespace mozilla;
    1.29 +
    1.30 +nsStyleSheetService *nsStyleSheetService::gInstance = nullptr;
    1.31 +
    1.32 +nsStyleSheetService::nsStyleSheetService()
    1.33 +{
    1.34 +  PR_STATIC_ASSERT(0 == AGENT_SHEET && 1 == USER_SHEET && 2 == AUTHOR_SHEET);
    1.35 +  NS_ASSERTION(!gInstance, "Someone is using CreateInstance instead of GetService");
    1.36 +  gInstance = this;
    1.37 +  nsLayoutStatics::AddRef();
    1.38 +}
    1.39 +
    1.40 +nsStyleSheetService::~nsStyleSheetService()
    1.41 +{
    1.42 +  UnregisterWeakMemoryReporter(this);
    1.43 +
    1.44 +  gInstance = nullptr;
    1.45 +  nsLayoutStatics::Release();
    1.46 +}
    1.47 +
    1.48 +NS_IMPL_ISUPPORTS(
    1.49 +  nsStyleSheetService, nsIStyleSheetService, nsIMemoryReporter)
    1.50 +
    1.51 +void
    1.52 +nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager  *aManager,
    1.53 +                                            const char          *aCategory,
    1.54 +                                            nsISimpleEnumerator *aEnumerator,
    1.55 +                                            uint32_t             aSheetType)
    1.56 +{
    1.57 +  if (!aEnumerator)
    1.58 +    return;
    1.59 +
    1.60 +  bool hasMore;
    1.61 +  while (NS_SUCCEEDED(aEnumerator->HasMoreElements(&hasMore)) && hasMore) {
    1.62 +    nsCOMPtr<nsISupports> element;
    1.63 +    if (NS_FAILED(aEnumerator->GetNext(getter_AddRefs(element))))
    1.64 +      break;
    1.65 +
    1.66 +    nsCOMPtr<nsISupportsCString> icStr = do_QueryInterface(element);
    1.67 +    NS_ASSERTION(icStr,
    1.68 +                 "category manager entries must be nsISupportsCStrings");
    1.69 +
    1.70 +    nsAutoCString name;
    1.71 +    icStr->GetData(name);
    1.72 +
    1.73 +    nsXPIDLCString spec;
    1.74 +    aManager->GetCategoryEntry(aCategory, name.get(), getter_Copies(spec));
    1.75 +
    1.76 +    nsCOMPtr<nsIURI> uri;
    1.77 +    NS_NewURI(getter_AddRefs(uri), spec);
    1.78 +    if (uri)
    1.79 +      LoadAndRegisterSheetInternal(uri, aSheetType);
    1.80 +  }
    1.81 +}
    1.82 +
    1.83 +int32_t
    1.84 +nsStyleSheetService::FindSheetByURI(const nsCOMArray<nsIStyleSheet> &sheets,
    1.85 +                                    nsIURI *sheetURI)
    1.86 +{
    1.87 +  for (int32_t i = sheets.Count() - 1; i >= 0; i-- ) {
    1.88 +    bool bEqual;
    1.89 +    nsIURI* uri = sheets[i]->GetSheetURI();
    1.90 +    if (uri
    1.91 +        && NS_SUCCEEDED(uri->Equals(sheetURI, &bEqual))
    1.92 +        && bEqual) {
    1.93 +      return i;
    1.94 +    }
    1.95 +  }
    1.96 +
    1.97 +  return -1;
    1.98 +}
    1.99 +
   1.100 +nsresult
   1.101 +nsStyleSheetService::Init()
   1.102 +{
   1.103 +  // Child processes get their style sheets from the ContentParent.
   1.104 +  if (XRE_GetProcessType() == GeckoProcessType_Content) {
   1.105 +    return NS_OK;
   1.106 +  }
   1.107 +
   1.108 +  // Enumerate all of the style sheet URIs registered in the category
   1.109 +  // manager and load them.
   1.110 +
   1.111 +  nsCOMPtr<nsICategoryManager> catMan =
   1.112 +    do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
   1.113 +
   1.114 +  NS_ENSURE_TRUE(catMan, NS_ERROR_OUT_OF_MEMORY);
   1.115 +
   1.116 +  nsCOMPtr<nsISimpleEnumerator> sheets;
   1.117 +  catMan->EnumerateCategory("agent-style-sheets", getter_AddRefs(sheets));
   1.118 +  RegisterFromEnumerator(catMan, "agent-style-sheets", sheets, AGENT_SHEET);
   1.119 +
   1.120 +  catMan->EnumerateCategory("user-style-sheets", getter_AddRefs(sheets));
   1.121 +  RegisterFromEnumerator(catMan, "user-style-sheets", sheets, USER_SHEET);
   1.122 +
   1.123 +  catMan->EnumerateCategory("author-style-sheets", getter_AddRefs(sheets));
   1.124 +  RegisterFromEnumerator(catMan, "author-style-sheets", sheets, AUTHOR_SHEET);
   1.125 +
   1.126 +  RegisterWeakMemoryReporter(this);
   1.127 +
   1.128 +  return NS_OK;
   1.129 +}
   1.130 +
   1.131 +NS_IMETHODIMP
   1.132 +nsStyleSheetService::LoadAndRegisterSheet(nsIURI *aSheetURI,
   1.133 +                                          uint32_t aSheetType)
   1.134 +{
   1.135 +  nsresult rv = LoadAndRegisterSheetInternal(aSheetURI, aSheetType);
   1.136 +  if (NS_SUCCEEDED(rv)) {
   1.137 +    const char* message;
   1.138 +    switch (aSheetType) {
   1.139 +      case AGENT_SHEET:
   1.140 +        message = "agent-sheet-added";
   1.141 +        break;
   1.142 +      case USER_SHEET:
   1.143 +        message = "user-sheet-added";
   1.144 +        break;
   1.145 +      case AUTHOR_SHEET:
   1.146 +        message = "author-sheet-added";
   1.147 +        break;
   1.148 +      default:
   1.149 +        return NS_ERROR_INVALID_ARG;
   1.150 +    }
   1.151 +    nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
   1.152 +    if (serv) {
   1.153 +      // We're guaranteed that the new sheet is the last sheet in
   1.154 +      // mSheets[aSheetType]
   1.155 +      const nsCOMArray<nsIStyleSheet> & sheets = mSheets[aSheetType];
   1.156 +      serv->NotifyObservers(sheets[sheets.Count() - 1], message, nullptr);
   1.157 +    }
   1.158 +
   1.159 +    if (XRE_GetProcessType() == GeckoProcessType_Default) {
   1.160 +      nsTArray<dom::ContentParent*> children;
   1.161 +      dom::ContentParent::GetAll(children);
   1.162 +
   1.163 +      if (children.IsEmpty()) {
   1.164 +        return rv;
   1.165 +      }
   1.166 +
   1.167 +      mozilla::ipc::URIParams uri;
   1.168 +      SerializeURI(aSheetURI, uri);
   1.169 +
   1.170 +      for (uint32_t i = 0; i < children.Length(); i++) {
   1.171 +        unused << children[i]->SendLoadAndRegisterSheet(uri, aSheetType);
   1.172 +      }
   1.173 +    }
   1.174 +  }
   1.175 +  return rv;
   1.176 +}
   1.177 +
   1.178 +nsresult
   1.179 +nsStyleSheetService::LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
   1.180 +                                                  uint32_t aSheetType)
   1.181 +{
   1.182 +  NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
   1.183 +                aSheetType == USER_SHEET ||
   1.184 +                aSheetType == AUTHOR_SHEET);
   1.185 +  NS_ENSURE_ARG_POINTER(aSheetURI);
   1.186 +
   1.187 +  nsRefPtr<css::Loader> loader = new css::Loader();
   1.188 +
   1.189 +  nsRefPtr<nsCSSStyleSheet> sheet;
   1.190 +  // Allow UA sheets, but not user sheets, to use unsafe rules
   1.191 +  nsresult rv = loader->LoadSheetSync(aSheetURI, aSheetType == AGENT_SHEET,
   1.192 +                                      true, getter_AddRefs(sheet));
   1.193 +  NS_ENSURE_SUCCESS(rv, rv);
   1.194 +
   1.195 +  if (!mSheets[aSheetType].AppendObject(sheet)) {
   1.196 +    rv = NS_ERROR_OUT_OF_MEMORY;
   1.197 +  }
   1.198 +
   1.199 +  return rv;
   1.200 +}
   1.201 +
   1.202 +NS_IMETHODIMP
   1.203 +nsStyleSheetService::SheetRegistered(nsIURI *sheetURI,
   1.204 +                                     uint32_t aSheetType, bool *_retval)
   1.205 +{
   1.206 +  NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
   1.207 +                aSheetType == USER_SHEET ||
   1.208 +                aSheetType == AUTHOR_SHEET);
   1.209 +  NS_ENSURE_ARG_POINTER(sheetURI);
   1.210 +  NS_PRECONDITION(_retval, "Null out param");
   1.211 +
   1.212 +  *_retval = (FindSheetByURI(mSheets[aSheetType], sheetURI) >= 0);
   1.213 +
   1.214 +  return NS_OK;
   1.215 +}
   1.216 +
   1.217 +NS_IMETHODIMP
   1.218 +nsStyleSheetService::UnregisterSheet(nsIURI *aSheetURI, uint32_t aSheetType)
   1.219 +{
   1.220 +  NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
   1.221 +                aSheetType == USER_SHEET ||
   1.222 +                aSheetType == AUTHOR_SHEET);
   1.223 +  NS_ENSURE_ARG_POINTER(aSheetURI);
   1.224 +
   1.225 +  int32_t foundIndex = FindSheetByURI(mSheets[aSheetType], aSheetURI);
   1.226 +  NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
   1.227 +  nsCOMPtr<nsIStyleSheet> sheet = mSheets[aSheetType][foundIndex];
   1.228 +  mSheets[aSheetType].RemoveObjectAt(foundIndex);
   1.229 +
   1.230 +  const char* message;
   1.231 +  switch (aSheetType) {
   1.232 +    case AGENT_SHEET:
   1.233 +      message = "agent-sheet-removed";
   1.234 +      break;
   1.235 +    case USER_SHEET:
   1.236 +      message = "user-sheet-removed";
   1.237 +      break;
   1.238 +    case AUTHOR_SHEET:
   1.239 +      message = "author-sheet-removed";
   1.240 +      break;
   1.241 +  }
   1.242 +
   1.243 +  nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
   1.244 +  if (serv)
   1.245 +    serv->NotifyObservers(sheet, message, nullptr);
   1.246 +
   1.247 +  if (XRE_GetProcessType() == GeckoProcessType_Default) {
   1.248 +    nsTArray<dom::ContentParent*> children;
   1.249 +    dom::ContentParent::GetAll(children);
   1.250 +
   1.251 +    if (children.IsEmpty()) {
   1.252 +      return NS_OK;
   1.253 +    }
   1.254 +
   1.255 +    mozilla::ipc::URIParams uri;
   1.256 +    SerializeURI(aSheetURI, uri);
   1.257 +
   1.258 +    for (uint32_t i = 0; i < children.Length(); i++) {
   1.259 +      unused << children[i]->SendUnregisterSheet(uri, aSheetType);
   1.260 +    }
   1.261 +  }
   1.262 +
   1.263 +  return NS_OK;
   1.264 +}
   1.265 +
   1.266 +//static
   1.267 +nsStyleSheetService *
   1.268 +nsStyleSheetService::GetInstance()
   1.269 +{
   1.270 +  static bool first = true;
   1.271 +  if (first) {
   1.272 +    // make sure at first call that it's inited
   1.273 +    nsCOMPtr<nsIStyleSheetService> dummy =
   1.274 +      do_GetService(NS_STYLESHEETSERVICE_CONTRACTID);
   1.275 +    first = false;
   1.276 +  }
   1.277 +
   1.278 +  return gInstance;
   1.279 +}
   1.280 +
   1.281 +static size_t
   1.282 +SizeOfElementIncludingThis(nsIStyleSheet* aElement,
   1.283 +                           MallocSizeOf aMallocSizeOf, void *aData)
   1.284 +{
   1.285 +  return aElement->SizeOfIncludingThis(aMallocSizeOf);
   1.286 +}
   1.287 +
   1.288 +MOZ_DEFINE_MALLOC_SIZE_OF(StyleSheetServiceMallocSizeOf)
   1.289 +
   1.290 +NS_IMETHODIMP
   1.291 +nsStyleSheetService::CollectReports(nsIHandleReportCallback* aHandleReport,
   1.292 +                                    nsISupports* aData)
   1.293 +{
   1.294 +  return MOZ_COLLECT_REPORT(
   1.295 +    "explicit/layout/style-sheet-service", KIND_HEAP, UNITS_BYTES,
   1.296 +    SizeOfIncludingThis(StyleSheetServiceMallocSizeOf),
   1.297 +    "Memory used for style sheets held by the style sheet service.");
   1.298 +}
   1.299 +
   1.300 +size_t
   1.301 +nsStyleSheetService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   1.302 +{
   1.303 +  size_t n = aMallocSizeOf(this);
   1.304 +  n += mSheets[AGENT_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,
   1.305 +                                                aMallocSizeOf);
   1.306 +  n += mSheets[USER_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,
   1.307 +                                               aMallocSizeOf);
   1.308 +  n += mSheets[AUTHOR_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,
   1.309 +                                                 aMallocSizeOf);
   1.310 +  return n;
   1.311 +}
   1.312 +
   1.313 +

mercurial