123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * 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/. */
- #include "nsIconURI.h"
- #include "mozilla/ArrayUtils.h"
- #include "mozilla/ipc/URIUtils.h"
- #include "mozilla/Sprintf.h"
- #include "nsIIOService.h"
- #include "nsIURL.h"
- #include "nsNetUtil.h"
- #include "plstr.h"
- #include <stdlib.h>
- using namespace mozilla;
- using namespace mozilla::ipc;
- #define DEFAULT_IMAGE_SIZE 16
- #if defined(MAX_PATH)
- #define SANE_FILE_NAME_LEN MAX_PATH
- #elif defined(PATH_MAX)
- #define SANE_FILE_NAME_LEN PATH_MAX
- #else
- #define SANE_FILE_NAME_LEN 1024
- #endif
- // helper function for parsing out attributes like size, and contentType
- // from the icon url.
- static void extractAttributeValue(const char* aSearchString,
- const char* aAttributeName,
- nsCString& aResult);
- static const char* kSizeStrings[] =
- {
- "button",
- "toolbar",
- "toolbarsmall",
- "menu",
- "dnd",
- "dialog"
- };
- static const char* kStateStrings[] =
- {
- "normal",
- "disabled"
- };
- ////////////////////////////////////////////////////////////////////////////////
- nsMozIconURI::nsMozIconURI()
- : mSize(DEFAULT_IMAGE_SIZE),
- mIconSize(-1),
- mIconState(-1)
- { }
- nsMozIconURI::~nsMozIconURI()
- { }
- NS_IMPL_ISUPPORTS(nsMozIconURI, nsIMozIconURI, nsIURI, nsIIPCSerializableURI)
- #define MOZICON_SCHEME "moz-icon:"
- #define MOZICON_SCHEME_LEN (sizeof(MOZICON_SCHEME) - 1)
- ////////////////////////////////////////////////////////////////////////////////
- // nsIURI methods:
- NS_IMETHODIMP
- nsMozIconURI::GetSpec(nsACString& aSpec)
- {
- aSpec = MOZICON_SCHEME;
- if (mIconURL) {
- nsAutoCString fileIconSpec;
- nsresult rv = mIconURL->GetSpec(fileIconSpec);
- NS_ENSURE_SUCCESS(rv, rv);
- aSpec += fileIconSpec;
- } else if (!mStockIcon.IsEmpty()) {
- aSpec += "//stock/";
- aSpec += mStockIcon;
- } else {
- aSpec += "//";
- aSpec += mFileName;
- }
- aSpec += "?size=";
- if (mIconSize >= 0) {
- aSpec += kSizeStrings[mIconSize];
- } else {
- char buf[20];
- SprintfLiteral(buf, "%d", mSize);
- aSpec.Append(buf);
- }
- if (mIconState >= 0) {
- aSpec += "&state=";
- aSpec += kStateStrings[mIconState];
- }
- if (!mContentType.IsEmpty()) {
- aSpec += "&contentType=";
- aSpec += mContentType.get();
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetSpecIgnoringRef(nsACString& result)
- {
- return GetSpec(result);
- }
- NS_IMETHODIMP
- nsMozIconURI::GetHasRef(bool* result)
- {
- *result = false;
- return NS_OK;
- }
- // takes a string like ?size=32&contentType=text/html and returns a new string
- // containing just the attribute value. i.e you could pass in this string with
- // an attribute name of 'size=', this will return 32
- // Assumption: attribute pairs in the string are separated by '&'.
- void
- extractAttributeValue(const char* aSearchString,
- const char* aAttributeName,
- nsCString& aResult)
- {
- //NS_ENSURE_ARG_POINTER(extractAttributeValue);
- aResult.Truncate();
- if (aSearchString && aAttributeName) {
- // search the string for attributeName
- uint32_t attributeNameSize = strlen(aAttributeName);
- const char* startOfAttribute = PL_strcasestr(aSearchString, aAttributeName);
- if (startOfAttribute &&
- ( *(startOfAttribute-1) == '?' || *(startOfAttribute-1) == '&') ) {
- startOfAttribute += attributeNameSize; // skip over the attributeName
- // is there something after the attribute name
- if (*startOfAttribute) {
- const char* endofAttribute = strchr(startOfAttribute, '&');
- if (endofAttribute) {
- aResult.Assign(Substring(startOfAttribute, endofAttribute));
- } else {
- aResult.Assign(startOfAttribute);
- }
- } // if we have a attribute value
- } // if we have a attribute name
- } // if we got non-null search string and attribute name values
- }
- NS_IMETHODIMP
- nsMozIconURI::SetSpec(const nsACString& aSpec)
- {
- // Reset everything to default values.
- mIconURL = nullptr;
- mSize = DEFAULT_IMAGE_SIZE;
- mContentType.Truncate();
- mFileName.Truncate();
- mStockIcon.Truncate();
- mIconSize = -1;
- mIconState = -1;
- nsAutoCString iconSpec(aSpec);
- if (!Substring(iconSpec, 0,
- MOZICON_SCHEME_LEN).EqualsLiteral(MOZICON_SCHEME)) {
- return NS_ERROR_MALFORMED_URI;
- }
- int32_t questionMarkPos = iconSpec.Find("?");
- if (questionMarkPos != -1 &&
- static_cast<int32_t>(iconSpec.Length()) > (questionMarkPos + 1)) {
- extractAttributeValue(iconSpec.get(), "contentType=", mContentType);
- nsAutoCString sizeString;
- extractAttributeValue(iconSpec.get(), "size=", sizeString);
- if (!sizeString.IsEmpty()) {
- const char* sizeStr = sizeString.get();
- for (uint32_t i = 0; i < ArrayLength(kSizeStrings); i++) {
- if (PL_strcasecmp(sizeStr, kSizeStrings[i]) == 0) {
- mIconSize = i;
- break;
- }
- }
- int32_t sizeValue = atoi(sizeString.get());
- if (sizeValue > 0) {
- mSize = sizeValue;
- }
- }
- nsAutoCString stateString;
- extractAttributeValue(iconSpec.get(), "state=", stateString);
- if (!stateString.IsEmpty()) {
- const char* stateStr = stateString.get();
- for (uint32_t i = 0; i < ArrayLength(kStateStrings); i++) {
- if (PL_strcasecmp(stateStr, kStateStrings[i]) == 0) {
- mIconState = i;
- break;
- }
- }
- }
- }
- int32_t pathLength = iconSpec.Length() - MOZICON_SCHEME_LEN;
- if (questionMarkPos != -1) {
- pathLength = questionMarkPos - MOZICON_SCHEME_LEN;
- }
- if (pathLength < 3) {
- return NS_ERROR_MALFORMED_URI;
- }
- nsAutoCString iconPath(Substring(iconSpec, MOZICON_SCHEME_LEN, pathLength));
- // Icon URI path can have three forms:
- // (1) //stock/<icon-identifier>
- // (2) //<some dummy file with an extension>
- // (3) a valid URL
- if (!strncmp("//stock/", iconPath.get(), 8)) {
- mStockIcon.Assign(Substring(iconPath, 8));
- // An icon identifier must always be specified.
- if (mStockIcon.IsEmpty()) {
- return NS_ERROR_MALFORMED_URI;
- }
- return NS_OK;
- }
- if (StringBeginsWith(iconPath, NS_LITERAL_CSTRING("//"))) {
- // Sanity check this supposed dummy file name.
- if (iconPath.Length() > SANE_FILE_NAME_LEN) {
- return NS_ERROR_MALFORMED_URI;
- }
- iconPath.Cut(0, 2);
- mFileName.Assign(iconPath);
- }
- nsresult rv;
- nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIURI> uri;
- ioService->NewURI(iconPath, nullptr, nullptr, getter_AddRefs(uri));
- mIconURL = do_QueryInterface(uri);
- if (mIconURL) {
- mFileName.Truncate();
- } else if (mFileName.IsEmpty()) {
- return NS_ERROR_MALFORMED_URI;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetPrePath(nsACString& prePath)
- {
- prePath = MOZICON_SCHEME;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetScheme(nsACString& aScheme)
- {
- aScheme = "moz-icon";
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetScheme(const nsACString& aScheme)
- {
- // doesn't make sense to set the scheme of a moz-icon URL
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetUsername(nsACString& aUsername)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetUsername(const nsACString& aUsername)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetPassword(nsACString& aPassword)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetPassword(const nsACString& aPassword)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetUserPass(nsACString& aUserPass)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetUserPass(const nsACString& aUserPass)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetHostPort(nsACString& aHostPort)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetHostPort(const nsACString& aHostPort)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetHostAndPort(const nsACString& aHostPort)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetHost(nsACString& aHost)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetHost(const nsACString& aHost)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetPort(int32_t* aPort)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetPort(int32_t aPort)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetPath(nsACString& aPath)
- {
- aPath.Truncate();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetPath(const nsACString& aPath)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetFilePath(nsACString& aFilePath)
- {
- aFilePath.Truncate();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetFilePath(const nsACString& aFilePath)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetQuery(nsACString& aQuery)
- {
- aQuery.Truncate();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetQuery(const nsACString& aQuery)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetRef(nsACString& aRef)
- {
- aRef.Truncate();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetRef(const nsACString& aRef)
- {
- return NS_ERROR_FAILURE;
- }
- NS_IMETHODIMP
- nsMozIconURI::Equals(nsIURI* other, bool* result)
- {
- *result = false;
- NS_ENSURE_ARG_POINTER(other);
- NS_PRECONDITION(result, "null pointer");
- nsAutoCString spec1;
- nsAutoCString spec2;
- nsresult rv = GetSpec(spec1);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = other->GetSpec(spec2);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!PL_strcasecmp(spec1.get(), spec2.get())) {
- *result = true;
- } else {
- *result = false;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::EqualsExceptRef(nsIURI* other, bool* result)
- {
- // GetRef/SetRef not supported by nsMozIconURI, so
- // EqualsExceptRef() is the same as Equals().
- return Equals(other, result);
- }
- NS_IMETHODIMP
- nsMozIconURI::SchemeIs(const char* aScheme, bool* aEquals)
- {
- NS_ENSURE_ARG_POINTER(aEquals);
- if (!aScheme) {
- return NS_ERROR_INVALID_ARG;
- }
- *aEquals = PL_strcasecmp("moz-icon", aScheme) ? false : true;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::Clone(nsIURI** result)
- {
- nsCOMPtr<nsIURL> newIconURL;
- if (mIconURL) {
- nsCOMPtr<nsIURI> newURI;
- nsresult rv = mIconURL->Clone(getter_AddRefs(newURI));
- if (NS_FAILED(rv)) {
- return rv;
- }
- newIconURL = do_QueryInterface(newURI, &rv);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- nsMozIconURI* uri = new nsMozIconURI();
- newIconURL.swap(uri->mIconURL);
- uri->mSize = mSize;
- uri->mContentType = mContentType;
- uri->mFileName = mFileName;
- uri->mStockIcon = mStockIcon;
- uri->mIconSize = mIconSize;
- uri->mIconState = mIconState;
- NS_ADDREF(*result = uri);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::CloneIgnoringRef(nsIURI** result)
- {
- // GetRef/SetRef not supported by nsMozIconURI, so
- // CloneIgnoringRef() is the same as Clone().
- return Clone(result);
- }
- NS_IMETHODIMP
- nsMozIconURI::CloneWithNewRef(const nsACString& newRef, nsIURI** result)
- {
- // GetRef/SetRef not supported by nsMozIconURI, so
- // CloneWithNewRef() is the same as Clone().
- return Clone(result);
- }
- NS_IMETHODIMP
- nsMozIconURI::Resolve(const nsACString& relativePath, nsACString& result)
- {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetAsciiSpec(nsACString& aSpecA)
- {
- return GetSpec(aSpecA);
- }
- NS_IMETHODIMP
- nsMozIconURI::GetAsciiHostPort(nsACString& aHostPortA)
- {
- return GetHostPort(aHostPortA);
- }
- NS_IMETHODIMP
- nsMozIconURI::GetAsciiHost(nsACString& aHostA)
- {
- return GetHost(aHostA);
- }
- NS_IMETHODIMP
- nsMozIconURI::GetOriginCharset(nsACString& result)
- {
- result.Truncate();
- return NS_OK;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // nsIIconUri methods:
- NS_IMETHODIMP
- nsMozIconURI::GetIconURL(nsIURL** aFileUrl)
- {
- *aFileUrl = mIconURL;
- NS_IF_ADDREF(*aFileUrl);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetIconURL(nsIURL* aFileUrl)
- {
- // this isn't called anywhere, needs to go through SetSpec parsing
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetImageSize(uint32_t* aImageSize)
- // measured by # of pixels in a row. defaults to 16.
- {
- *aImageSize = mSize;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetImageSize(uint32_t aImageSize)
- // measured by # of pixels in a row. defaults to 16.
- {
- mSize = aImageSize;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetContentType(nsACString& aContentType)
- {
- aContentType = mContentType;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::SetContentType(const nsACString& aContentType)
- {
- mContentType = aContentType;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetFileExtension(nsACString& aFileExtension)
- {
- // First, try to get the extension from mIconURL if we have one
- if (mIconURL) {
- nsAutoCString fileExt;
- if (NS_SUCCEEDED(mIconURL->GetFileExtension(fileExt))) {
- if (!fileExt.IsEmpty()) {
- // unfortunately, this code doesn't give us the required '.' in
- // front of the extension so we have to do it ourselves.
- aFileExtension.Assign('.');
- aFileExtension.Append(fileExt);
- }
- }
- return NS_OK;
- }
- if (!mFileName.IsEmpty()) {
- // truncate the extension out of the file path...
- const char* chFileName = mFileName.get(); // get the underlying buffer
- const char* fileExt = strrchr(chFileName, '.');
- if (!fileExt) {
- return NS_OK;
- }
- aFileExtension = fileExt;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetStockIcon(nsACString& aStockIcon)
- {
- aStockIcon = mStockIcon;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetIconSize(nsACString& aSize)
- {
- if (mIconSize >= 0) {
- aSize = kSizeStrings[mIconSize];
- } else {
- aSize.Truncate();
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsMozIconURI::GetIconState(nsACString& aState)
- {
- if (mIconState >= 0) {
- aState = kStateStrings[mIconState];
- } else {
- aState.Truncate();
- }
- return NS_OK;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // nsIIPCSerializableURI methods:
- void
- nsMozIconURI::Serialize(URIParams& aParams)
- {
- IconURIParams params;
- if (mIconURL) {
- URIParams iconURLParams;
- SerializeURI(mIconURL, iconURLParams);
- if (iconURLParams.type() == URIParams::T__None) {
- // Serialization failed, bail.
- return;
- }
- params.uri() = iconURLParams;
- } else {
- params.uri() = void_t();
- }
- params.size() = mSize;
- params.fileName() = mFileName;
- params.stockIcon() = mStockIcon;
- params.iconSize() = mIconSize;
- params.iconState() = mIconState;
- aParams = params;
- }
- bool
- nsMozIconURI::Deserialize(const URIParams& aParams)
- {
- if (aParams.type() != URIParams::TIconURIParams) {
- MOZ_ASSERT_UNREACHABLE("Received unknown URI from other process!");
- return false;
- }
- const IconURIParams& params = aParams.get_IconURIParams();
- if (params.uri().type() != OptionalURIParams::Tvoid_t) {
- nsCOMPtr<nsIURI> uri = DeserializeURI(params.uri().get_URIParams());
- mIconURL = do_QueryInterface(uri);
- if (!mIconURL) {
- MOZ_ASSERT_UNREACHABLE("bad nsIURI passed");
- return false;
- }
- }
- mSize = params.size();
- mContentType = params.contentType();
- mFileName = params.fileName();
- mStockIcon = params.stockIcon();
- if (params.iconSize() < -1 ||
- params.iconSize() >= (int32_t) ArrayLength(kSizeStrings)) {
- return false;
- }
- mIconSize = params.iconSize();
- if (params.iconState() < -1 ||
- params.iconState() >= (int32_t) ArrayLength(kStateStrings)) {
- return false;
- }
- mIconState = params.iconState();
- return true;
- }
- ////////////////////////////////////////////////////////////
- // Nested version of nsIconURI
- nsNestedMozIconURI::nsNestedMozIconURI()
- { }
- nsNestedMozIconURI::~nsNestedMozIconURI()
- { }
- NS_IMPL_ISUPPORTS_INHERITED(nsNestedMozIconURI, nsMozIconURI, nsINestedURI)
- NS_IMETHODIMP
- nsNestedMozIconURI::GetInnerURI(nsIURI** aURI)
- {
- nsCOMPtr<nsIURI> iconURL = do_QueryInterface(mIconURL);
- if (iconURL) {
- iconURL.forget(aURI);
- } else {
- *aURI = nullptr;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsNestedMozIconURI::GetInnermostURI(nsIURI** aURI)
- {
- return NS_ImplGetInnermostURI(this, aURI);
- }
|