content/xul/templates/src/nsXULContentUtils.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6 *
michael@0 7 *
michael@0 8 * This Original Code has been modified by IBM Corporation.
michael@0 9 * Modifications made by IBM described herein are
michael@0 10 * Copyright (c) International Business Machines
michael@0 11 * Corporation, 2000
michael@0 12 *
michael@0 13 * Modifications to Mozilla code or documentation
michael@0 14 * identified per MPL Section 3.3
michael@0 15 *
michael@0 16 * Date Modified by Description of modification
michael@0 17 * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
michael@0 18 * use in OS2
michael@0 19 */
michael@0 20
michael@0 21
michael@0 22 /*
michael@0 23
michael@0 24 A package of routines shared by the XUL content code.
michael@0 25
michael@0 26 */
michael@0 27
michael@0 28 #include "mozilla/ArrayUtils.h"
michael@0 29
michael@0 30 #include "nsCOMPtr.h"
michael@0 31 #include "nsIContent.h"
michael@0 32 #include "nsIDocument.h"
michael@0 33 #include "nsIDOMElement.h"
michael@0 34 #include "nsIDOMXULCommandDispatcher.h"
michael@0 35 #include "nsIDOMXULDocument.h"
michael@0 36 #include "nsIRDFNode.h"
michael@0 37 #include "nsIRDFService.h"
michael@0 38 #include "nsIServiceManager.h"
michael@0 39 #include "nsIURL.h"
michael@0 40 #include "nsXULContentUtils.h"
michael@0 41 #include "nsLayoutCID.h"
michael@0 42 #include "nsNameSpaceManager.h"
michael@0 43 #include "nsNetUtil.h"
michael@0 44 #include "nsRDFCID.h"
michael@0 45 #include "nsString.h"
michael@0 46 #include "nsXPIDLString.h"
michael@0 47 #include "nsGkAtoms.h"
michael@0 48 #include "prlog.h"
michael@0 49 #include "prtime.h"
michael@0 50 #include "rdf.h"
michael@0 51 #include "nsContentUtils.h"
michael@0 52 #include "nsIDateTimeFormat.h"
michael@0 53 #include "nsDateTimeFormatCID.h"
michael@0 54 #include "nsIScriptableDateFormat.h"
michael@0 55 #include "nsICollation.h"
michael@0 56 #include "nsCollationCID.h"
michael@0 57 #include "nsILocale.h"
michael@0 58 #include "nsILocaleService.h"
michael@0 59 #include "nsIConsoleService.h"
michael@0 60 #include "nsEscape.h"
michael@0 61
michael@0 62 using namespace mozilla;
michael@0 63
michael@0 64 //------------------------------------------------------------------------
michael@0 65
michael@0 66 nsIRDFService* nsXULContentUtils::gRDF;
michael@0 67 nsIDateTimeFormat* nsXULContentUtils::gFormat;
michael@0 68 nsICollation *nsXULContentUtils::gCollation;
michael@0 69
michael@0 70 #ifdef PR_LOGGING
michael@0 71 extern PRLogModuleInfo* gXULTemplateLog;
michael@0 72 #endif
michael@0 73
michael@0 74 #define XUL_RESOURCE(ident, uri) nsIRDFResource* nsXULContentUtils::ident
michael@0 75 #define XUL_LITERAL(ident, val) nsIRDFLiteral* nsXULContentUtils::ident
michael@0 76 #include "nsXULResourceList.h"
michael@0 77 #undef XUL_RESOURCE
michael@0 78 #undef XUL_LITERAL
michael@0 79
michael@0 80 //------------------------------------------------------------------------
michael@0 81 // Constructors n' stuff
michael@0 82 //
michael@0 83
michael@0 84 nsresult
michael@0 85 nsXULContentUtils::Init()
michael@0 86 {
michael@0 87 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
michael@0 88 nsresult rv = CallGetService(kRDFServiceCID, &gRDF);
michael@0 89 if (NS_FAILED(rv)) {
michael@0 90 return rv;
michael@0 91 }
michael@0 92
michael@0 93 #define XUL_RESOURCE(ident, uri) \
michael@0 94 PR_BEGIN_MACRO \
michael@0 95 rv = gRDF->GetResource(NS_LITERAL_CSTRING(uri), &(ident)); \
michael@0 96 if (NS_FAILED(rv)) return rv; \
michael@0 97 PR_END_MACRO
michael@0 98
michael@0 99 #define XUL_LITERAL(ident, val) \
michael@0 100 PR_BEGIN_MACRO \
michael@0 101 rv = gRDF->GetLiteral(NS_LITERAL_STRING(val).get(), &(ident)); \
michael@0 102 if (NS_FAILED(rv)) return rv; \
michael@0 103 PR_END_MACRO
michael@0 104
michael@0 105 #include "nsXULResourceList.h"
michael@0 106 #undef XUL_RESOURCE
michael@0 107 #undef XUL_LITERAL
michael@0 108
michael@0 109 rv = CallCreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &gFormat);
michael@0 110 if (NS_FAILED(rv)) {
michael@0 111 return rv;
michael@0 112 }
michael@0 113
michael@0 114 return NS_OK;
michael@0 115 }
michael@0 116
michael@0 117
michael@0 118 nsresult
michael@0 119 nsXULContentUtils::Finish()
michael@0 120 {
michael@0 121 NS_IF_RELEASE(gRDF);
michael@0 122
michael@0 123 #define XUL_RESOURCE(ident, uri) NS_IF_RELEASE(ident)
michael@0 124 #define XUL_LITERAL(ident, val) NS_IF_RELEASE(ident)
michael@0 125 #include "nsXULResourceList.h"
michael@0 126 #undef XUL_RESOURCE
michael@0 127 #undef XUL_LITERAL
michael@0 128
michael@0 129 NS_IF_RELEASE(gFormat);
michael@0 130 NS_IF_RELEASE(gCollation);
michael@0 131
michael@0 132 return NS_OK;
michael@0 133 }
michael@0 134
michael@0 135 nsICollation*
michael@0 136 nsXULContentUtils::GetCollation()
michael@0 137 {
michael@0 138 if (!gCollation) {
michael@0 139 nsresult rv;
michael@0 140
michael@0 141 // get a locale service
michael@0 142 nsCOMPtr<nsILocaleService> localeService =
michael@0 143 do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
michael@0 144 if (NS_SUCCEEDED(rv)) {
michael@0 145 nsCOMPtr<nsILocale> locale;
michael@0 146 rv = localeService->GetApplicationLocale(getter_AddRefs(locale));
michael@0 147 if (NS_SUCCEEDED(rv) && locale) {
michael@0 148 nsCOMPtr<nsICollationFactory> colFactory =
michael@0 149 do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
michael@0 150 if (colFactory) {
michael@0 151 rv = colFactory->CreateCollation(locale, &gCollation);
michael@0 152 NS_ASSERTION(NS_SUCCEEDED(rv),
michael@0 153 "couldn't create collation instance");
michael@0 154 } else
michael@0 155 NS_ERROR("couldn't create instance of collation factory");
michael@0 156 } else
michael@0 157 NS_ERROR("unable to get application locale");
michael@0 158 } else
michael@0 159 NS_ERROR("couldn't get locale factory");
michael@0 160 }
michael@0 161
michael@0 162 return gCollation;
michael@0 163 }
michael@0 164
michael@0 165 //------------------------------------------------------------------------
michael@0 166
michael@0 167 nsresult
michael@0 168 nsXULContentUtils::FindChildByTag(nsIContent* aElement,
michael@0 169 int32_t aNameSpaceID,
michael@0 170 nsIAtom* aTag,
michael@0 171 nsIContent** aResult)
michael@0 172 {
michael@0 173 for (nsIContent* child = aElement->GetFirstChild();
michael@0 174 child;
michael@0 175 child = child->GetNextSibling()) {
michael@0 176
michael@0 177 if (child->NodeInfo()->Equals(aTag, aNameSpaceID)) {
michael@0 178 NS_ADDREF(*aResult = child);
michael@0 179
michael@0 180 return NS_OK;
michael@0 181 }
michael@0 182 }
michael@0 183
michael@0 184 *aResult = nullptr;
michael@0 185 return NS_RDF_NO_VALUE; // not found
michael@0 186 }
michael@0 187
michael@0 188
michael@0 189 nsresult
michael@0 190 nsXULContentUtils::GetElementResource(nsIContent* aElement, nsIRDFResource** aResult)
michael@0 191 {
michael@0 192 // Perform a reverse mapping from an element in the content model
michael@0 193 // to an RDF resource.
michael@0 194 nsresult rv;
michael@0 195
michael@0 196 char16_t buf[128];
michael@0 197 nsFixedString id(buf, ArrayLength(buf), 0);
michael@0 198
michael@0 199 // Whoa. Why the "id" attribute? What if it's not even a XUL
michael@0 200 // element? This is totally bogus!
michael@0 201 aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
michael@0 202 if (id.IsEmpty())
michael@0 203 return NS_ERROR_FAILURE;
michael@0 204
michael@0 205 // Since the element will store its ID attribute as a document-relative value,
michael@0 206 // we may need to qualify it first...
michael@0 207 nsCOMPtr<nsIDocument> doc = aElement->GetDocument();
michael@0 208 NS_ASSERTION(doc, "element is not in any document");
michael@0 209 if (! doc)
michael@0 210 return NS_ERROR_FAILURE;
michael@0 211
michael@0 212 rv = nsXULContentUtils::MakeElementResource(doc, id, aResult);
michael@0 213 if (NS_FAILED(rv)) return rv;
michael@0 214
michael@0 215 return NS_OK;
michael@0 216 }
michael@0 217
michael@0 218
michael@0 219 /*
michael@0 220 Note: this routine is similar, yet distinctly different from, nsBookmarksService::GetTextForNode
michael@0 221 */
michael@0 222
michael@0 223 nsresult
michael@0 224 nsXULContentUtils::GetTextForNode(nsIRDFNode* aNode, nsAString& aResult)
michael@0 225 {
michael@0 226 if (! aNode) {
michael@0 227 aResult.Truncate();
michael@0 228 return NS_OK;
michael@0 229 }
michael@0 230
michael@0 231 nsresult rv;
michael@0 232
michael@0 233 // Literals are the most common, so try these first.
michael@0 234 nsCOMPtr<nsIRDFLiteral> literal = do_QueryInterface(aNode);
michael@0 235 if (literal) {
michael@0 236 const char16_t* p;
michael@0 237 rv = literal->GetValueConst(&p);
michael@0 238 if (NS_FAILED(rv)) return rv;
michael@0 239
michael@0 240 aResult = p;
michael@0 241 return NS_OK;
michael@0 242 }
michael@0 243
michael@0 244 nsCOMPtr<nsIRDFDate> dateLiteral = do_QueryInterface(aNode);
michael@0 245 if (dateLiteral) {
michael@0 246 PRTime value;
michael@0 247 rv = dateLiteral->GetValue(&value);
michael@0 248 if (NS_FAILED(rv)) return rv;
michael@0 249
michael@0 250 nsAutoString str;
michael@0 251 rv = gFormat->FormatPRTime(nullptr /* nsILocale* locale */,
michael@0 252 kDateFormatShort,
michael@0 253 kTimeFormatSeconds,
michael@0 254 value,
michael@0 255 str);
michael@0 256 aResult.Assign(str);
michael@0 257
michael@0 258 if (NS_FAILED(rv)) return rv;
michael@0 259
michael@0 260 return NS_OK;
michael@0 261 }
michael@0 262
michael@0 263 nsCOMPtr<nsIRDFInt> intLiteral = do_QueryInterface(aNode);
michael@0 264 if (intLiteral) {
michael@0 265 int32_t value;
michael@0 266 rv = intLiteral->GetValue(&value);
michael@0 267 if (NS_FAILED(rv)) return rv;
michael@0 268
michael@0 269 aResult.Truncate();
michael@0 270 nsAutoString intStr;
michael@0 271 intStr.AppendInt(value, 10);
michael@0 272 aResult.Append(intStr);
michael@0 273 return NS_OK;
michael@0 274 }
michael@0 275
michael@0 276
michael@0 277 nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(aNode);
michael@0 278 if (resource) {
michael@0 279 const char* p;
michael@0 280 rv = resource->GetValueConst(&p);
michael@0 281 if (NS_FAILED(rv)) return rv;
michael@0 282 CopyUTF8toUTF16(p, aResult);
michael@0 283 return NS_OK;
michael@0 284 }
michael@0 285
michael@0 286 NS_ERROR("not a resource or a literal");
michael@0 287 return NS_ERROR_UNEXPECTED;
michael@0 288 }
michael@0 289
michael@0 290 nsresult
michael@0 291 nsXULContentUtils::MakeElementURI(nsIDocument* aDocument,
michael@0 292 const nsAString& aElementID,
michael@0 293 nsCString& aURI)
michael@0 294 {
michael@0 295 // Convert an element's ID to a URI that can be used to refer to
michael@0 296 // the element in the XUL graph.
michael@0 297
michael@0 298 nsIURI *docURI = aDocument->GetDocumentURI();
michael@0 299 NS_ENSURE_TRUE(docURI, NS_ERROR_UNEXPECTED);
michael@0 300
michael@0 301 nsRefPtr<nsIURI> docURIClone;
michael@0 302 nsresult rv = docURI->Clone(getter_AddRefs(docURIClone));
michael@0 303 NS_ENSURE_SUCCESS(rv, rv);
michael@0 304
michael@0 305 rv = docURIClone->SetRef(NS_ConvertUTF16toUTF8(aElementID));
michael@0 306 if (NS_SUCCEEDED(rv)) {
michael@0 307 return docURIClone->GetSpec(aURI);
michael@0 308 }
michael@0 309
michael@0 310 // docURIClone is apparently immutable. Fine - we can append ref manually.
michael@0 311 rv = docURI->GetSpec(aURI);
michael@0 312 NS_ENSURE_SUCCESS(rv, rv);
michael@0 313
michael@0 314 nsAutoCString ref;
michael@0 315 NS_EscapeURL(NS_ConvertUTF16toUTF8(aElementID), esc_FilePath | esc_AlwaysCopy, ref);
michael@0 316
michael@0 317 aURI.Append('#');
michael@0 318 aURI.Append(ref);
michael@0 319
michael@0 320 return NS_OK;
michael@0 321 }
michael@0 322
michael@0 323
michael@0 324 nsresult
michael@0 325 nsXULContentUtils::MakeElementResource(nsIDocument* aDocument, const nsAString& aID, nsIRDFResource** aResult)
michael@0 326 {
michael@0 327 nsresult rv;
michael@0 328
michael@0 329 char buf[256];
michael@0 330 nsFixedCString uri(buf, sizeof(buf), 0);
michael@0 331 rv = MakeElementURI(aDocument, aID, uri);
michael@0 332 if (NS_FAILED(rv)) return rv;
michael@0 333
michael@0 334 rv = gRDF->GetResource(uri, aResult);
michael@0 335 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create resource");
michael@0 336 if (NS_FAILED(rv)) return rv;
michael@0 337
michael@0 338 return NS_OK;
michael@0 339 }
michael@0 340
michael@0 341
michael@0 342
michael@0 343 nsresult
michael@0 344 nsXULContentUtils::MakeElementID(nsIDocument* aDocument,
michael@0 345 const nsACString& aURI,
michael@0 346 nsAString& aElementID)
michael@0 347 {
michael@0 348 // Convert a URI into an element ID that can be accessed from the
michael@0 349 // DOM APIs.
michael@0 350 nsCOMPtr<nsIURI> uri;
michael@0 351 nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI,
michael@0 352 aDocument->GetDocumentCharacterSet().get());
michael@0 353 NS_ENSURE_SUCCESS(rv, rv);
michael@0 354
michael@0 355 nsAutoCString ref;
michael@0 356 uri->GetRef(ref);
michael@0 357 CopyUTF8toUTF16(ref, aElementID);
michael@0 358
michael@0 359 return NS_OK;
michael@0 360 }
michael@0 361
michael@0 362 nsresult
michael@0 363 nsXULContentUtils::GetResource(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIRDFResource** aResult)
michael@0 364 {
michael@0 365 // construct a fully-qualified URI from the namespace/tag pair.
michael@0 366 NS_PRECONDITION(aAttribute != nullptr, "null ptr");
michael@0 367 if (! aAttribute)
michael@0 368 return NS_ERROR_NULL_POINTER;
michael@0 369
michael@0 370 return GetResource(aNameSpaceID, nsDependentAtomString(aAttribute),
michael@0 371 aResult);
michael@0 372 }
michael@0 373
michael@0 374
michael@0 375 nsresult
michael@0 376 nsXULContentUtils::GetResource(int32_t aNameSpaceID, const nsAString& aAttribute, nsIRDFResource** aResult)
michael@0 377 {
michael@0 378 // construct a fully-qualified URI from the namespace/tag pair.
michael@0 379
michael@0 380 // XXX should we allow nodes with no namespace???
michael@0 381 //NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "no namespace");
michael@0 382 //if (aNameSpaceID == kNameSpaceID_Unknown)
michael@0 383 // return NS_ERROR_UNEXPECTED;
michael@0 384
michael@0 385 nsresult rv;
michael@0 386
michael@0 387 char16_t buf[256];
michael@0 388 nsFixedString uri(buf, ArrayLength(buf), 0);
michael@0 389 if (aNameSpaceID != kNameSpaceID_Unknown && aNameSpaceID != kNameSpaceID_None) {
michael@0 390 rv = nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, uri);
michael@0 391 // XXX ignore failure; treat as "no namespace"
michael@0 392 }
michael@0 393
michael@0 394 // XXX check to see if we need to insert a '/' or a '#'. Oy.
michael@0 395 if (!uri.IsEmpty() && uri.Last() != '#' && uri.Last() != '/' && aAttribute.First() != '#')
michael@0 396 uri.Append(char16_t('#'));
michael@0 397
michael@0 398 uri.Append(aAttribute);
michael@0 399
michael@0 400 rv = gRDF->GetUnicodeResource(uri, aResult);
michael@0 401 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource");
michael@0 402 if (NS_FAILED(rv)) return rv;
michael@0 403
michael@0 404 return NS_OK;
michael@0 405 }
michael@0 406
michael@0 407
michael@0 408 nsresult
michael@0 409 nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, nsIContent* aElement)
michael@0 410 {
michael@0 411 // Deal with setting up a 'commandupdater'. Pulls the 'events' and
michael@0 412 // 'targets' attributes off of aElement, and adds it to the
michael@0 413 // document's command dispatcher.
michael@0 414 NS_PRECONDITION(aDocument != nullptr, "null ptr");
michael@0 415 if (! aDocument)
michael@0 416 return NS_ERROR_NULL_POINTER;
michael@0 417
michael@0 418 NS_PRECONDITION(aElement != nullptr, "null ptr");
michael@0 419 if (! aElement)
michael@0 420 return NS_ERROR_NULL_POINTER;
michael@0 421
michael@0 422 nsresult rv;
michael@0 423
michael@0 424 nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(aDocument);
michael@0 425 NS_ASSERTION(xuldoc != nullptr, "not a xul document");
michael@0 426 if (! xuldoc)
michael@0 427 return NS_ERROR_UNEXPECTED;
michael@0 428
michael@0 429 nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher;
michael@0 430 rv = xuldoc->GetCommandDispatcher(getter_AddRefs(dispatcher));
michael@0 431 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get dispatcher");
michael@0 432 if (NS_FAILED(rv)) return rv;
michael@0 433
michael@0 434 NS_ASSERTION(dispatcher != nullptr, "no dispatcher");
michael@0 435 if (! dispatcher)
michael@0 436 return NS_ERROR_UNEXPECTED;
michael@0 437
michael@0 438 nsAutoString events;
michael@0 439 aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::events, events);
michael@0 440 if (events.IsEmpty())
michael@0 441 events.AssignLiteral("*");
michael@0 442
michael@0 443 nsAutoString targets;
michael@0 444 aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::targets, targets);
michael@0 445
michael@0 446 if (targets.IsEmpty())
michael@0 447 targets.AssignLiteral("*");
michael@0 448
michael@0 449 nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(aElement);
michael@0 450 NS_ASSERTION(domelement != nullptr, "not a DOM element");
michael@0 451 if (! domelement)
michael@0 452 return NS_ERROR_UNEXPECTED;
michael@0 453
michael@0 454 rv = dispatcher->AddCommandUpdater(domelement, events, targets);
michael@0 455 if (NS_FAILED(rv)) return rv;
michael@0 456
michael@0 457 return NS_OK;
michael@0 458 }
michael@0 459
michael@0 460 void
michael@0 461 nsXULContentUtils::LogTemplateError(const char* aStr)
michael@0 462 {
michael@0 463 nsAutoString message;
michael@0 464 message.AssignLiteral("Error parsing template: ");
michael@0 465 message.Append(NS_ConvertUTF8toUTF16(aStr).get());
michael@0 466
michael@0 467 nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
michael@0 468 if (cs) {
michael@0 469 cs->LogStringMessage(message.get());
michael@0 470 PR_LOG(gXULTemplateLog, PR_LOG_ALWAYS, ("Error parsing template: %s", aStr));
michael@0 471 }
michael@0 472 }

mercurial