gecko/dom/base/URL.cpp
Ryan VanderMeulen 566e49b6ff Backed out 7 changesets (bug 1047483, bug 1079301, bug 1079335) for webplatform test failures.
Backed out changeset 7d06b68c44d0 (bug 1079335)
Backed out changeset 92030169528e (bug 1079301)
Backed out changeset c09d7f95554a (bug 1047483)
Backed out changeset c199f1057d7e (bug 1047483)
Backed out changeset 18830d07884c (bug 1047483)
Backed out changeset e087289ccfbb (bug 1047483)
Backed out changeset 6238ff5d3ed0 (bug 1047483)

CLOSED TREE

--HG--
rename : content/base/public/File.h => content/base/public/nsDOMFile.h
rename : content/base/src/MultipartFileImpl.cpp => content/base/src/nsDOMBlobBuilder.cpp
rename : content/base/src/MultipartFileImpl.h => content/base/src/nsDOMBlobBuilder.h
rename : content/base/src/File.cpp => content/base/src/nsDOMFile.cpp
2014-10-07 13:16:11 -04:00

573 lines
13 KiB
C++

/* -*- 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 "URL.h"
#include "nsGlobalWindow.h"
#include "nsDOMFile.h"
#include "DOMMediaStream.h"
#include "mozilla/dom/MediaSource.h"
#include "mozilla/dom/URLBinding.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsServiceManagerUtils.h"
#include "nsIIOService.h"
#include "nsEscape.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsIURL.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(URL)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(URL)
if (tmp->mSearchParams) {
tmp->mSearchParams->RemoveObserver(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(URL)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSearchParams)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(URL)
NS_IMPL_CYCLE_COLLECTING_RELEASE(URL)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
URL::URL(nsIURI* aURI)
: mURI(aURI)
{
}
JSObject*
URL::WrapObject(JSContext* aCx)
{
return URLBinding::Wrap(aCx, this);
}
/* static */ already_AddRefed<URL>
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
URL& aBase, ErrorResult& aRv)
{
nsresult rv;
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
nsCOMPtr<nsIURI> uri;
rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, aBase.GetURI(),
getter_AddRefs(uri));
if (NS_FAILED(rv)) {
nsAutoString label(aUrl);
aRv.ThrowTypeError(MSG_INVALID_URL, &label);
return nullptr;
}
nsRefPtr<URL> url = new URL(uri);
return url.forget();
}
/* static */ already_AddRefed<URL>
URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
const nsAString& aBase, ErrorResult& aRv)
{
nsresult rv;
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
nsCOMPtr<nsIURI> baseUri;
rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aBase), nullptr, nullptr,
getter_AddRefs(baseUri));
if (NS_FAILED(rv)) {
nsAutoString label(aBase);
aRv.ThrowTypeError(MSG_INVALID_URL, &label);
return nullptr;
}
nsCOMPtr<nsIURI> uri;
rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, baseUri,
getter_AddRefs(uri));
if (NS_FAILED(rv)) {
nsAutoString label(aUrl);
aRv.ThrowTypeError(MSG_INVALID_URL, &label);
return nullptr;
}
nsRefPtr<URL> url = new URL(uri);
return url.forget();
}
void
URL::CreateObjectURL(const GlobalObject& aGlobal,
nsIDOMBlob* aBlob,
const objectURLOptions& aOptions,
nsString& aResult,
ErrorResult& aError)
{
DOMFile* blob = static_cast<DOMFile*>(aBlob);
MOZ_ASSERT(blob);
CreateObjectURLInternal(aGlobal, blob->Impl(),
NS_LITERAL_CSTRING(BLOBURI_SCHEME), aOptions, aResult,
aError);
}
void
URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
const mozilla::dom::objectURLOptions& aOptions,
nsString& aResult,
ErrorResult& aError)
{
CreateObjectURLInternal(aGlobal, &aStream,
NS_LITERAL_CSTRING(MEDIASTREAMURI_SCHEME), aOptions,
aResult, aError);
}
void
URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
const objectURLOptions& aOptions,
nsString& aResult,
ErrorResult& aError)
{
CreateObjectURLInternal(aGlobal, &aSource,
NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME), aOptions,
aResult, aError);
}
void
URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
const nsACString& aScheme,
const objectURLOptions& aOptions,
nsString& aResult, ErrorResult& aError)
{
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
nsCString url;
nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
principal, url);
if (NS_FAILED(rv)) {
aError.Throw(rv);
return;
}
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
if (window) {
NS_PRECONDITION(window->IsInnerWindow(), "Should be inner window");
if (!window->GetExtantDoc()) {
aError.Throw(NS_ERROR_INVALID_POINTER);
return;
}
nsIDocument* doc = window->GetExtantDoc();
if (doc) {
doc->RegisterHostObjectUri(url);
}
}
CopyASCIItoUTF16(url, aResult);
}
void
URL::RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL)
{
nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
NS_LossyConvertUTF16toASCII asciiurl(aURL);
nsIPrincipal* urlPrincipal =
nsHostObjectProtocolHandler::GetDataEntryPrincipal(asciiurl);
if (urlPrincipal && principal->Subsumes(urlPrincipal)) {
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal.GetAsSupports());
nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
if (window && window->GetExtantDoc()) {
window->GetExtantDoc()->UnregisterHostObjectUri(asciiurl);
}
nsHostObjectProtocolHandler::RemoveDataEntry(asciiurl);
}
}
void
URL::GetHref(nsString& aHref, ErrorResult& aRv) const
{
aHref.Truncate();
nsAutoCString href;
nsresult rv = mURI->GetSpec(href);
if (NS_SUCCEEDED(rv)) {
CopyUTF8toUTF16(href, aHref);
}
}
void
URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
{
nsCString href = NS_ConvertUTF16toUTF8(aHref);
nsresult rv;
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
nsCOMPtr<nsIURI> uri;
rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
if (NS_FAILED(rv)) {
nsAutoString label(aHref);
aRv.ThrowTypeError(MSG_INVALID_URL, &label);
return;
}
mURI = uri;
UpdateURLSearchParams();
}
void
URL::GetOrigin(nsString& aOrigin, ErrorResult& aRv) const
{
nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(mURI);
if (uriWithPrincipal) {
nsCOMPtr<nsIPrincipal> principal;
uriWithPrincipal->GetPrincipal(getter_AddRefs(principal));
if (principal) {
nsContentUtils::GetUTFOrigin(principal, aOrigin);
return;
}
}
nsContentUtils::GetUTFOrigin(mURI, aOrigin);
}
void
URL::GetProtocol(nsString& aProtocol, ErrorResult& aRv) const
{
nsCString protocol;
if (NS_SUCCEEDED(mURI->GetScheme(protocol))) {
aProtocol.Truncate();
}
CopyASCIItoUTF16(protocol, aProtocol);
aProtocol.Append(char16_t(':'));
}
void
URL::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
{
nsAString::const_iterator start, end;
aProtocol.BeginReading(start);
aProtocol.EndReading(end);
nsAString::const_iterator iter(start);
FindCharInReadable(':', iter, end);
// Changing the protocol of a URL, changes the "nature" of the URI
// implementation. In order to do this properly, we have to serialize the
// existing URL and reparse it in a new object.
nsCOMPtr<nsIURI> clone;
nsresult rv = mURI->Clone(getter_AddRefs(clone));
if (NS_WARN_IF(NS_FAILED(rv)) || !clone) {
return;
}
rv = clone->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoCString href;
rv = clone->GetSpec(href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
mURI = uri;
}
#define URL_GETTER( value, func ) \
value.Truncate(); \
nsAutoCString tmp; \
nsresult rv = mURI->func(tmp); \
if (NS_SUCCEEDED(rv)) { \
CopyUTF8toUTF16(tmp, value); \
}
void
URL::GetUsername(nsString& aUsername, ErrorResult& aRv) const
{
URL_GETTER(aUsername, GetUsername);
}
void
URL::SetUsername(const nsAString& aUsername, ErrorResult& aRv)
{
mURI->SetUsername(NS_ConvertUTF16toUTF8(aUsername));
}
void
URL::GetPassword(nsString& aPassword, ErrorResult& aRv) const
{
URL_GETTER(aPassword, GetPassword);
}
void
URL::SetPassword(const nsAString& aPassword, ErrorResult& aRv)
{
mURI->SetPassword(NS_ConvertUTF16toUTF8(aPassword));
}
void
URL::GetHost(nsString& aHost, ErrorResult& aRv) const
{
URL_GETTER(aHost, GetHostPort);
}
void
URL::SetHost(const nsAString& aHost, ErrorResult& aRv)
{
mURI->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
}
void
URL::URLSearchParamsUpdated(URLSearchParams* aSearchParams)
{
MOZ_ASSERT(mSearchParams);
MOZ_ASSERT(mSearchParams == aSearchParams);
nsAutoString search;
mSearchParams->Serialize(search);
SetSearchInternal(search);
}
void
URL::UpdateURLSearchParams()
{
if (!mSearchParams) {
return;
}
nsAutoCString search;
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
if (url) {
nsresult rv = url->GetQuery(search);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get the query from a nsIURL.");
}
}
mSearchParams->ParseInput(search, this);
}
void
URL::GetHostname(nsString& aHostname, ErrorResult& aRv) const
{
aHostname.Truncate();
nsAutoCString tmp;
nsresult rv = mURI->GetHost(tmp);
if (NS_SUCCEEDED(rv)) {
if (tmp.FindChar(':') != -1) { // Escape IPv6 address
MOZ_ASSERT(!tmp.Length() ||
(tmp[0] !='[' && tmp[tmp.Length() - 1] != ']'));
tmp.Insert('[', 0);
tmp.Append(']');
}
CopyUTF8toUTF16(tmp, aHostname);
}
}
void
URL::SetHostname(const nsAString& aHostname, ErrorResult& aRv)
{
// nsStandardURL returns NS_ERROR_UNEXPECTED for an empty hostname
// The return code is silently ignored
mURI->SetHost(NS_ConvertUTF16toUTF8(aHostname));
}
void
URL::GetPort(nsString& aPort, ErrorResult& aRv) const
{
aPort.Truncate();
int32_t port;
nsresult rv = mURI->GetPort(&port);
if (NS_SUCCEEDED(rv) && port != -1) {
nsAutoString portStr;
portStr.AppendInt(port, 10);
aPort.Assign(portStr);
}
}
void
URL::SetPort(const nsAString& aPort, ErrorResult& aRv)
{
nsresult rv;
nsAutoString portStr(aPort);
int32_t port = -1;
// nsIURI uses -1 as default value.
if (!portStr.IsEmpty()) {
port = portStr.ToInteger(&rv);
if (NS_FAILED(rv)) {
return;
}
}
mURI->SetPort(port);
}
void
URL::GetPathname(nsString& aPathname, ErrorResult& aRv) const
{
aPathname.Truncate();
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
if (!url) {
// Do not throw! Not having a valid URI or URL should result in an empty
// string.
return;
}
nsAutoCString file;
nsresult rv = url->GetFilePath(file);
if (NS_SUCCEEDED(rv)) {
CopyUTF8toUTF16(file, aPathname);
}
}
void
URL::SetPathname(const nsAString& aPathname, ErrorResult& aRv)
{
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
if (!url) {
// Ignore failures to be compatible with NS4.
return;
}
url->SetFilePath(NS_ConvertUTF16toUTF8(aPathname));
}
void
URL::GetSearch(nsString& aSearch, ErrorResult& aRv) const
{
aSearch.Truncate();
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
if (!url) {
// Do not throw! Not having a valid URI or URL should result in an empty
// string.
return;
}
nsAutoCString search;
nsresult rv = url->GetQuery(search);
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
}
}
void
URL::SetSearch(const nsAString& aSearch, ErrorResult& aRv)
{
SetSearchInternal(aSearch);
UpdateURLSearchParams();
}
void
URL::SetSearchInternal(const nsAString& aSearch)
{
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
if (!url) {
// Ignore failures to be compatible with NS4.
return;
}
url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
}
URLSearchParams*
URL::SearchParams()
{
CreateSearchParamsIfNeeded();
return mSearchParams;
}
void
URL::SetSearchParams(URLSearchParams& aSearchParams)
{
if (mSearchParams) {
mSearchParams->RemoveObserver(this);
}
// the observer will be cleared using the cycle collector.
mSearchParams = &aSearchParams;
mSearchParams->AddObserver(this);
nsAutoString search;
mSearchParams->Serialize(search);
SetSearchInternal(search);
}
void
URL::GetHash(nsString& aHash, ErrorResult& aRv) const
{
aHash.Truncate();
nsAutoCString ref;
nsresult rv = mURI->GetRef(ref);
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
aHash.Assign(char16_t('#'));
AppendUTF8toUTF16(ref, aHash);
}
}
void
URL::SetHash(const nsAString& aHash, ErrorResult& aRv)
{
mURI->SetRef(NS_ConvertUTF16toUTF8(aHash));
}
bool IsChromeURI(nsIURI* aURI)
{
bool isChrome = false;
if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)))
return isChrome;
return false;
}
void
URL::CreateSearchParamsIfNeeded()
{
if (!mSearchParams) {
mSearchParams = new URLSearchParams();
mSearchParams->AddObserver(this);
UpdateURLSearchParams();
}
}
}
}