Bug 832014 part 5. Add WebIDL API to nsLocation. r=peterv,bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 11 Jul 2014 19:31:46 -0400
changeset 215627 f7bce1d778cf327e53148271bb696b722b60f48a
parent 215626 20e4769e2106bfb858d280083eac90e6e276b8ea
child 215628 ddfd6eb4518f65bb3cb8d01d936158aebcc44371
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, bholley
bugs832014
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 832014 part 5. Add WebIDL API to nsLocation. r=peterv,bholley
dom/base/nsGlobalWindow.cpp
dom/base/nsLocation.cpp
dom/base/nsLocation.h
dom/webidl/Location.webidl
dom/webidl/URLUtils.webidl
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9651,17 +9651,17 @@ nsGlobalWindow::GetPrivateRoot()
 
 nsLocation*
 nsGlobalWindow::GetLocation(ErrorResult& aError)
 {
   FORWARD_TO_INNER_OR_THROW(GetLocation, (aError), aError, nullptr);
 
   nsIDocShell *docShell = GetDocShell();
   if (!mLocation && docShell) {
-    mLocation = new nsLocation(docShell);
+    mLocation = new nsLocation(this, docShell);
   }
   return mLocation;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation)
 {
   ErrorResult rv;
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -28,16 +28,19 @@
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsNullPrincipal.h"
 #include "ScriptSettings.h"
 
+using namespace mozilla;
+using namespace mozilla::dom;
+
 static nsresult
 GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
 {
   aCharset.Truncate();
 
   JSContext *cx = nsContentUtils::GetCurrentJSContext();
   if (cx) {
     nsCOMPtr<nsPIDOMWindow> window =
@@ -47,40 +50,40 @@ GetDocumentCharacterSetForURI(const nsAS
     if (nsIDocument* doc = window->GetDoc()) {
       aCharset = doc->GetDocumentCharacterSet();
     }
   }
 
   return NS_OK;
 }
 
-nsLocation::nsLocation(nsIDocShell *aDocShell)
+nsLocation::nsLocation(nsPIDOMWindow* aWindow, nsIDocShell *aDocShell)
+  : mInnerWindow(aWindow)
 {
   MOZ_ASSERT(aDocShell);
+  MOZ_ASSERT(mInnerWindow->IsInnerWindow());
 
   mDocShell = do_GetWeakReference(aDocShell);
-  nsCOMPtr<nsIDOMWindow> outer = aDocShell->GetWindow();
-  mOuter = do_GetWeakReference(outer);
 }
 
 nsLocation::~nsLocation()
 {
 }
 
 DOMCI_DATA(Location, nsLocation)
 
 // QueryInterface implementation for nsLocation
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsLocation)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMLocation)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Location)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsLocation)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsLocation, mInnerWindow)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsLocation)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsLocation)
 
 void
 nsLocation::SetDocShell(nsIDocShell *aDocShell)
 {
    mDocShell = do_GetWeakReference(aDocShell);
 }
@@ -724,16 +727,112 @@ nsLocation::SetProtocol(const nsAString&
   rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return SetURI(uri);
 }
 
+void
+nsLocation::GetUsername(nsAString& aUsername, ErrorResult& aError)
+{
+  if (!CallerSubsumes()) {
+    aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  aUsername.Truncate();
+  nsCOMPtr<nsIURI> uri;
+  nsresult result = GetURI(getter_AddRefs(uri));
+  if (uri) {
+    nsAutoCString username;
+    result = uri->GetUsername(username);
+    if (NS_SUCCEEDED(result)) {
+      CopyUTF8toUTF16(username, aUsername);
+    }
+  }
+}
+
+void
+nsLocation::SetUsername(const nsAString& aUsername, ErrorResult& aError)
+{
+  if (!CallerSubsumes()) {
+    aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = GetWritableURI(getter_AddRefs(uri));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    aError.Throw(rv);
+    return;
+  }
+
+  if (!uri) {
+    return;
+  }
+
+  rv = uri->SetUsername(NS_ConvertUTF16toUTF8(aUsername));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    aError.Throw(rv);
+    return;
+  }
+
+  rv = SetURI(uri);
+}
+
+void
+nsLocation::GetPassword(nsAString& aPassword, ErrorResult& aError)
+{
+  if (!CallerSubsumes()) {
+    aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  aPassword.Truncate();
+  nsCOMPtr<nsIURI> uri;
+  nsresult result = GetURI(getter_AddRefs(uri));
+  if (uri) {
+    nsAutoCString password;
+    result = uri->GetPassword(password);
+    if (NS_SUCCEEDED(result)) {
+      CopyUTF8toUTF16(password, aPassword);
+    }
+  }
+}
+
+void
+nsLocation::SetPassword(const nsAString& aPassword, ErrorResult& aError)
+{
+  if (!CallerSubsumes()) {
+    aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = GetWritableURI(getter_AddRefs(uri));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    aError.Throw(rv);
+    return;
+  }
+
+  if (!uri) {
+    return;
+  }
+
+  rv = uri->SetPassword(NS_ConvertUTF16toUTF8(aPassword));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    aError.Throw(rv);
+    return;
+  }
+
+  rv = SetURI(uri);
+}
+
 NS_IMETHODIMP
 nsLocation::GetSearch(nsAString& aSearch)
 {
   if (!CallerSubsumes())
     return NS_ERROR_DOM_SECURITY_ERR;
 
   aSearch.SetLength(0);
 
@@ -913,18 +1012,22 @@ nsLocation::GetSourceBaseURL(JSContext* 
   NS_ENSURE_TRUE(doc, NS_OK);
   *sourceURL = doc->GetBaseURI().take();
   return NS_OK;
 }
 
 bool
 nsLocation::CallerSubsumes()
 {
-  // Get the principal associated with the location object.
-  nsCOMPtr<nsIDOMWindow> outer = do_QueryReferent(mOuter);
+  // Get the principal associated with the location object.  Note that this is
+  // the principal of the page which will actually be navigated, not the
+  // principal of the Location object itself.  This is why we need this check
+  // even though we only allow limited cross-origin access to Location objects
+  // in general.
+  nsCOMPtr<nsIDOMWindow> outer = mInnerWindow->GetOuterWindow();
   if (MOZ_UNLIKELY(!outer))
     return false;
   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
   bool subsumes = false;
   nsresult rv = nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sop->GetPrincipal(), &subsumes);
   NS_ENSURE_SUCCESS(rv, false);
   return subsumes;
 }
--- a/dom/base/nsLocation.h
+++ b/dom/base/nsLocation.h
@@ -8,40 +8,138 @@
 #define nsLocation_h__
 
 #include "nsIDOMLocation.h"
 #include "nsString.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "js/TypeDecls.h"
+#include "mozilla/ErrorResult.h"
+#include "nsPIDOMWindow.h"
 
 class nsIURI;
 class nsIDocShell;
 class nsIDocShellLoadInfo;
 
 //*****************************************************************************
 // nsLocation: Script "location" object
 //*****************************************************************************
 
-class nsLocation : public nsIDOMLocation
-                 , public nsWrapperCache
+class nsLocation MOZ_FINAL : public nsIDOMLocation
+                           , public nsWrapperCache
 {
+  typedef mozilla::ErrorResult ErrorResult;
+
 public:
-  nsLocation(nsIDocShell *aDocShell);
+  nsLocation(nsPIDOMWindow* aWindow, nsIDocShell *aDocShell);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsLocation)
 
   void SetDocShell(nsIDocShell *aDocShell);
   nsIDocShell *GetDocShell();
 
   // nsIDOMLocation
   NS_DECL_NSIDOMLOCATION
 
+  // WebIDL API:
+  void Assign(const nsAString& aUrl, ErrorResult& aError)
+  {
+    aError = Assign(aUrl);
+  }
+  void Replace(const nsAString& aUrl, ErrorResult& aError)
+  {
+    aError = Replace(aUrl);
+  }
+  void Reload(bool aForceget, ErrorResult& aError)
+  {
+    aError = Reload(aForceget);
+  }
+  void GetHref(nsAString& aHref, ErrorResult& aError)
+  {
+    aError = GetHref(aHref);
+  }
+  void SetHref(const nsAString& aHref, ErrorResult& aError)
+  {
+    aError = SetHref(aHref);
+  }
+  void GetOrigin(nsAString& aOrigin, ErrorResult& aError)
+  {
+    aError = GetOrigin(aOrigin);
+  }
+  void GetProtocol(nsAString& aProtocol, ErrorResult& aError)
+  {
+    aError = GetProtocol(aProtocol);
+  }
+  void SetProtocol(const nsAString& aProtocol, ErrorResult& aError)
+  {
+    aError = SetProtocol(aProtocol);
+  }
+  void GetUsername(nsAString& aUsername, ErrorResult& aError);
+  void SetUsername(const nsAString& aUsername, ErrorResult& aError);
+  void GetPassword(nsAString& aPassword, ErrorResult& aError);
+  void SetPassword(const nsAString& aPassword, ErrorResult& aError);
+  void GetHost(nsAString& aHost, ErrorResult& aError)
+  {
+    aError = GetHost(aHost);
+  }
+  void SetHost(const nsAString& aHost, ErrorResult& aError)
+  {
+    aError = SetHost(aHost);
+  }
+  void GetHostname(nsAString& aHostname, ErrorResult& aError)
+  {
+    aError = GetHostname(aHostname);
+  }
+  void SetHostname(const nsAString& aHostname, ErrorResult& aError)
+  {
+    aError = SetHostname(aHostname);
+  }
+  void GetPort(nsAString& aPort, ErrorResult& aError)
+  {
+    aError = GetPort(aPort);
+  }
+  void SetPort(const nsAString& aPort, ErrorResult& aError)
+  {
+    aError = SetPort(aPort);
+  }
+  void GetPathname(nsAString& aPathname, ErrorResult& aError)
+  {
+    aError = GetPathname(aPathname);
+  }
+  void SetPathname(const nsAString& aPathname, ErrorResult& aError)
+  {
+    aError = SetPathname(aPathname);
+  }
+  void GetSearch(nsAString& aSeach, ErrorResult& aError)
+  {
+    aError = GetSearch(aSeach);
+  }
+  void SetSearch(const nsAString& aSeach, ErrorResult& aError)
+  {
+    aError = SetSearch(aSeach);
+  }
+  void GetHash(nsAString& aHash, ErrorResult& aError)
+  {
+    aError = GetHash(aHash);
+  }
+  void SetHash(const nsAString& aHash, ErrorResult& aError)
+  {
+    aError = SetHash(aHash);
+  }
+  void Stringify(nsAString& aRetval, ErrorResult& aError)
+  {
+    GetHref(aRetval, aError);
+  }
+  nsPIDOMWindow* GetParentObject() const
+  {
+    return mInnerWindow;
+  }
+
 protected:
   virtual ~nsLocation();
 
   // In the case of jar: uris, we sometimes want the place the jar was
   // fetched from as the URI instead of the jar: uri itself.  Pass in
   // true for aGetInnermostURI when that's the case.
   nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
   nsresult GetWritableURI(nsIURI** aURL);
@@ -51,14 +149,14 @@ protected:
   nsresult SetHrefWithContext(JSContext* cx, const nsAString& aHref,
                               bool aReplace);
 
   nsresult GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL);
   nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo);
   bool CallerSubsumes();
 
   nsString mCachedHash;
+  nsCOMPtr<nsPIDOMWindow> mInnerWindow;
   nsWeakPtr mDocShell;
-  nsWeakPtr mOuter;
 };
 
 #endif // nsLocation_h__
 
--- a/dom/webidl/Location.webidl
+++ b/dom/webidl/Location.webidl
@@ -8,13 +8,18 @@
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 [Unforgeable]
 interface Location {
+  [Throws]
   void assign(DOMString url);
+  [Throws]
   void replace(DOMString url);
-  void reload();
+  // XXXbz there is no forceget argument in the spec!  See bug 1037721.
+  [Throws]
+  void reload(optional boolean forceget = false);
 };
-Location implements URLUtils;
+// No support for .searchParams on Location yet.  See bug 1037715.
+Location implements URLUtilsNoSearchParams;
--- a/dom/webidl/URLUtils.webidl
+++ b/dom/webidl/URLUtils.webidl
@@ -9,17 +9,17 @@
  * To the extent possible under law, the editors have waived all copyright
  * and related or neighboring rights to this work. In addition, as of 17
  * February 2013, the editors have made this specification available under
  * the Open Web Foundation Agreement Version 1.0, which is available at
  * http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
  */
 
 [NoInterfaceObject]
-interface URLUtils {
+interface URLUtilsNoSearchParams {
   // Bug 824857: no support for stringifier attributes yet.
   //  stringifier attribute DOMString href;
   [Throws]
            attribute DOMString href;
   [Throws]
   readonly attribute DOMString origin;
 
   [Throws]
@@ -33,17 +33,22 @@ interface URLUtils {
   [Throws]
            attribute DOMString hostname;
   [Throws]
            attribute DOMString port;
   [Throws]
            attribute DOMString pathname;
   [Throws]
            attribute DOMString search;
-           attribute URLSearchParams searchParams;
+  // searchParams should go here once Location implements it.  See bug 1037715.
   [Throws]
            attribute DOMString hash;
 
   // Bug 824857 should remove this.
   [Throws]
   stringifier;
 };
 
+[NoInterfaceObject]
+interface URLUtils : URLUtilsNoSearchParams
+{
+           attribute URLSearchParams searchParams;
+};