/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * This Original Code has been modified by IBM Corporation. * Modifications made by IBM described herein are * Copyright (c) International Business Machines * Corporation, 2000 * * Modifications to Mozilla code or documentation * identified per MPL Section 3.3 * * Date Modified by Description of modification * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink * use in OS2 */ /* A package of routines shared by the XUL content code. */ #include "mozilla/ArrayUtils.h" #include "DateTimeFormat.h" #include "nsCOMPtr.h" #include "nsIContent.h" #include "nsIDocument.h" #include "nsIDOMElement.h" #include "nsIDOMXULCommandDispatcher.h" #include "nsIDOMXULDocument.h" #include "nsIRDFNode.h" #include "nsIRDFService.h" #include "nsIServiceManager.h" #include "nsIURL.h" #include "nsXULContentUtils.h" #include "nsLayoutCID.h" #include "nsNameSpaceManager.h" #include "nsRDFCID.h" #include "nsString.h" #include "nsXPIDLString.h" #include "nsGkAtoms.h" #include "mozilla/Logging.h" #include "prtime.h" #include "rdf.h" #include "nsContentUtils.h" #include "nsIScriptableDateFormat.h" #include "nsICollation.h" #include "nsCollationCID.h" #include "nsIConsoleService.h" #include "nsEscape.h" using namespace mozilla; //------------------------------------------------------------------------ nsIRDFService* nsXULContentUtils::gRDF; nsICollation *nsXULContentUtils::gCollation; extern LazyLogModule gXULTemplateLog; #define XUL_RESOURCE(ident, uri) nsIRDFResource* nsXULContentUtils::ident #define XUL_LITERAL(ident, val) nsIRDFLiteral* nsXULContentUtils::ident #include "nsXULResourceList.h" #undef XUL_RESOURCE #undef XUL_LITERAL //------------------------------------------------------------------------ // Constructors n' stuff // nsresult nsXULContentUtils::Init() { static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); nsresult rv = CallGetService(kRDFServiceCID, &gRDF); if (NS_FAILED(rv)) { return rv; } #define XUL_RESOURCE(ident, uri) \ PR_BEGIN_MACRO \ rv = gRDF->GetResource(NS_LITERAL_CSTRING(uri), &(ident)); \ if (NS_FAILED(rv)) return rv; \ PR_END_MACRO #define XUL_LITERAL(ident, val) \ PR_BEGIN_MACRO \ rv = gRDF->GetLiteral(val, &(ident)); \ if (NS_FAILED(rv)) return rv; \ PR_END_MACRO #include "nsXULResourceList.h" #undef XUL_RESOURCE #undef XUL_LITERAL return NS_OK; } nsresult nsXULContentUtils::Finish() { NS_IF_RELEASE(gRDF); #define XUL_RESOURCE(ident, uri) NS_IF_RELEASE(ident) #define XUL_LITERAL(ident, val) NS_IF_RELEASE(ident) #include "nsXULResourceList.h" #undef XUL_RESOURCE #undef XUL_LITERAL NS_IF_RELEASE(gCollation); return NS_OK; } nsICollation* nsXULContentUtils::GetCollation() { if (!gCollation) { nsCOMPtr colFactory = do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID); if (colFactory) { DebugOnly rv = colFactory->CreateCollation(&gCollation); NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't create collation instance"); } else NS_ERROR("couldn't create instance of collation factory"); } return gCollation; } //------------------------------------------------------------------------ nsresult nsXULContentUtils::FindChildByTag(nsIContent* aElement, int32_t aNameSpaceID, nsIAtom* aTag, nsIContent** aResult) { for (nsIContent* child = aElement->GetFirstChild(); child; child = child->GetNextSibling()) { if (child->NodeInfo()->Equals(aTag, aNameSpaceID)) { NS_ADDREF(*aResult = child); return NS_OK; } } *aResult = nullptr; return NS_RDF_NO_VALUE; // not found } /* Note: this routine is similar, yet distinctly different from, nsBookmarksService::GetTextForNode */ nsresult nsXULContentUtils::GetTextForNode(nsIRDFNode* aNode, nsAString& aResult) { if (! aNode) { aResult.Truncate(); return NS_OK; } nsresult rv; // Literals are the most common, so try these first. nsCOMPtr literal = do_QueryInterface(aNode); if (literal) { const char16_t* p; rv = literal->GetValueConst(&p); if (NS_FAILED(rv)) return rv; aResult = p; return NS_OK; } nsCOMPtr dateLiteral = do_QueryInterface(aNode); if (dateLiteral) { PRTime value; rv = dateLiteral->GetValue(&value); if (NS_FAILED(rv)) return rv; nsAutoString str; rv = DateTimeFormat::FormatPRTime(kDateFormatShort, kTimeFormatSeconds, value, str); aResult.Assign(str); if (NS_FAILED(rv)) return rv; return NS_OK; } nsCOMPtr intLiteral = do_QueryInterface(aNode); if (intLiteral) { int32_t value; rv = intLiteral->GetValue(&value); if (NS_FAILED(rv)) return rv; aResult.Truncate(); nsAutoString intStr; intStr.AppendInt(value, 10); aResult.Append(intStr); return NS_OK; } nsCOMPtr resource = do_QueryInterface(aNode); if (resource) { const char* p; rv = resource->GetValueConst(&p); if (NS_FAILED(rv)) return rv; CopyUTF8toUTF16(p, aResult); return NS_OK; } NS_ERROR("not a resource or a literal"); return NS_ERROR_UNEXPECTED; } nsresult nsXULContentUtils::GetResource(int32_t aNameSpaceID, nsIAtom* aAttribute, nsIRDFResource** aResult) { // construct a fully-qualified URI from the namespace/tag pair. NS_PRECONDITION(aAttribute != nullptr, "null ptr"); if (! aAttribute) return NS_ERROR_NULL_POINTER; return GetResource(aNameSpaceID, nsDependentAtomString(aAttribute), aResult); } nsresult nsXULContentUtils::GetResource(int32_t aNameSpaceID, const nsAString& aAttribute, nsIRDFResource** aResult) { // construct a fully-qualified URI from the namespace/tag pair. // XXX should we allow nodes with no namespace??? //NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "no namespace"); //if (aNameSpaceID == kNameSpaceID_Unknown) // return NS_ERROR_UNEXPECTED; nsresult rv; char16_t buf[256]; nsFixedString uri(buf, ArrayLength(buf), 0); if (aNameSpaceID != kNameSpaceID_Unknown && aNameSpaceID != kNameSpaceID_None) { rv = nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, uri); // XXX ignore failure; treat as "no namespace" } // XXX check to see if we need to insert a '/' or a '#'. Oy. if (!uri.IsEmpty() && uri.Last() != '#' && uri.Last() != '/' && aAttribute.First() != '#') uri.Append(char16_t('#')); uri.Append(aAttribute); rv = gRDF->GetUnicodeResource(uri, aResult); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource"); if (NS_FAILED(rv)) return rv; return NS_OK; } nsresult nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, nsIContent* aElement) { // Deal with setting up a 'commandupdater'. Pulls the 'events' and // 'targets' attributes off of aElement, and adds it to the // document's command dispatcher. NS_PRECONDITION(aDocument != nullptr, "null ptr"); if (! aDocument) return NS_ERROR_NULL_POINTER; NS_PRECONDITION(aElement != nullptr, "null ptr"); if (! aElement) return NS_ERROR_NULL_POINTER; nsresult rv; nsCOMPtr xuldoc = do_QueryInterface(aDocument); NS_ASSERTION(xuldoc != nullptr, "not a xul document"); if (! xuldoc) return NS_ERROR_UNEXPECTED; nsCOMPtr dispatcher; rv = xuldoc->GetCommandDispatcher(getter_AddRefs(dispatcher)); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get dispatcher"); if (NS_FAILED(rv)) return rv; NS_ASSERTION(dispatcher != nullptr, "no dispatcher"); if (! dispatcher) return NS_ERROR_UNEXPECTED; nsAutoString events; aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::events, events); if (events.IsEmpty()) events.Assign('*'); nsAutoString targets; aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::targets, targets); if (targets.IsEmpty()) targets.Assign('*'); nsCOMPtr domelement = do_QueryInterface(aElement); NS_ASSERTION(domelement != nullptr, "not a DOM element"); if (! domelement) return NS_ERROR_UNEXPECTED; rv = dispatcher->AddCommandUpdater(domelement, events, targets); if (NS_FAILED(rv)) return rv; return NS_OK; } void nsXULContentUtils::LogTemplateError(const char* aStr) { nsAutoString message; message.AssignLiteral("Error parsing template: "); message.Append(NS_ConvertUTF8toUTF16(aStr).get()); nsCOMPtr cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID); if (cs) { cs->LogStringMessage(message.get()); MOZ_LOG(gXULTemplateLog, LogLevel::Info, ("Error parsing template: %s", aStr)); } }