Bug 848332 part 1. Add WebIDL API for XMLDocument. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 26 Mar 2013 11:31:54 -0400
changeset 126260 eed8d8cc96cf7aff51799f91183a30ea34a284f7
parent 126259 952ba47dcfb7042d62fb4d6e238f2693d4ee0653
child 126261 3ce43c16627e622c59444e55712f0de25020c30c
push id24481
push userryanvm@gmail.com
push dateWed, 27 Mar 2013 16:41:34 +0000
treeherdermozilla-central@5dbcbd03d7ba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs848332
milestone22.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 848332 part 1. Add WebIDL API for XMLDocument. r=peterv
content/xml/document/src/XMLDocument.cpp
content/xml/document/src/XMLDocument.h
dom/webidl/XMLDocument.webidl
--- a/content/xml/document/src/XMLDocument.cpp
+++ b/content/xml/document/src/XMLDocument.cpp
@@ -294,107 +294,130 @@ ReportUseOfDeprecatedMethod(nsIDocument 
                                   "DOM3 Load", aDoc,
                                   nsContentUtils::eDOM_PROPERTIES,
                                   aWarning);
 }
 
 NS_IMETHODIMP
 XMLDocument::Load(const nsAString& aUrl, bool *aReturn)
 {
+  ErrorResult rv;
+  *aReturn = Load(aUrl, rv);
+  return rv.ErrorCode();
+}
+
+bool
+XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv)
+{
   bool hasHadScriptObject = true;
   nsIScriptGlobalObject* scriptObject =
     GetScriptHandlingObject(hasHadScriptObject);
-  NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
+  if (!scriptObject && hasHadScriptObject) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return false;
+  }
 
   ReportUseOfDeprecatedMethod(this, "UseOfDOM3LoadMethodWarning");
 
-  NS_ENSURE_ARG_POINTER(aReturn);
-  *aReturn = false;
-
   nsCOMPtr<nsIDocument> callingDoc =
     do_QueryInterface(nsContentUtils::GetDocumentFromContext());
 
   nsIURI *baseURI = mDocumentURI;
   nsAutoCString charset;
 
   if (callingDoc) {
     baseURI = callingDoc->GetDocBaseURI();
     charset = callingDoc->GetDocumentCharacterSet();
   }
 
   // Create a new URI
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI);
   if (NS_FAILED(rv)) {
-    return rv;
+    aRv.Throw(rv);
+    return false;
   }
 
   // Check to see whether the current document is allowed to load this URI.
   // It's important to use the current document's principal for this check so
   // that we don't end up in a case where code with elevated privileges is
   // calling us and changing the principal of this document.
 
   // Enforce same-origin even for chrome loaders to avoid someone accidentally
   // using a document that content has a reference to and turn that into a
   // chrome document.
   nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
   if (!nsContentUtils::IsSystemPrincipal(principal)) {
     rv = principal->CheckMayLoad(uri, false, false);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      aRv.Throw(rv);
+      return false;
+    }
 
     int16_t shouldLoad = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST,
                                    uri,
                                    principal,
                                    callingDoc ? callingDoc.get() :
                                      static_cast<nsIDocument*>(this),
                                    NS_LITERAL_CSTRING("application/xml"),
                                    nullptr,
                                    &shouldLoad,
                                    nsContentUtils::GetContentPolicy(),
                                    nsContentUtils::GetSecurityManager());
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      aRv.Throw(rv);
+      return false;
+    }
     if (NS_CP_REJECTED(shouldLoad)) {
-      return NS_ERROR_CONTENT_BLOCKED;
+      aRv.Throw(NS_ERROR_CONTENT_BLOCKED);
+      return false;
     }
   } else {
     // We're called from chrome, check to make sure the URI we're
     // about to load is also chrome.
 
     bool isChrome = false;
     if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
       nsAutoCString spec;
       if (mDocumentURI)
         mDocumentURI->GetSpec(spec);
 
       nsAutoString error;
       error.AssignLiteral("Cross site loading using document.load is no "
                           "longer supported. Use XMLHttpRequest instead.");
       nsCOMPtr<nsIScriptError> errorObject =
           do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_FAILED(rv)) {
+        aRv.Throw(rv);
+        return false;
+      }
 
       rv = errorObject->InitWithWindowID(error,
                                          NS_ConvertUTF8toUTF16(spec),
                                          EmptyString(),
                                          0, 0, nsIScriptError::warningFlag,
                                          "DOM",
                                          callingDoc ?
                                            callingDoc->InnerWindowID() :
                                            this->InnerWindowID());
 
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_FAILED(rv)) {
+        aRv.Throw(rv);
+        return false;
+      }
 
       nsCOMPtr<nsIConsoleService> consoleService =
         do_GetService(NS_CONSOLESERVICE_CONTRACTID);
       if (consoleService) {
         consoleService->LogMessage(errorObject);
       }
 
-      return NS_ERROR_DOM_SECURITY_ERR;
+      aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return false;
     }
   }
 
   // Partial Reset, need to restore principal for security reasons and
   // event listener manager so that load listeners etc. will
   // remain. This should be done before the security check is done to
   // ensure that the document is reset even if the new document can't
   // be loaded.  Note that we need to hold a strong ref to |principal|
@@ -413,25 +436,29 @@ XMLDocument::Load(const nsAString& aUrl,
   }
 
   ResetToURI(uri, loadGroup, principal);
 
   mListenerManager = elm;
 
   // Create a channel
   nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::GetSameOriginChecker();
-  NS_ENSURE_TRUE(req, NS_ERROR_OUT_OF_MEMORY);  
+  if (!req) {
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return false;
+  }
 
   nsCOMPtr<nsIChannel> channel;
   // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active,
   // which in turn keeps STOP button from becoming active  
   rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, loadGroup, req, 
                      nsIRequest::LOAD_BACKGROUND);
   if (NS_FAILED(rv)) {
-    return rv;
+    aRv.Throw(rv);
+    return false;
   }
 
   // StartDocumentLoad asserts that readyState is uninitialized, so
   // uninitialize it. SetReadyStateInternal make this transition invisible to
   // Web content. But before doing that, assert that the current readyState
   // is complete as it should be after the call to ResetToURI() above.
   MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE,
              "Bad readyState");
@@ -439,57 +466,57 @@ XMLDocument::Load(const nsAString& aUrl,
 
   // Prepare for loading the XML document "into oneself"
   nsCOMPtr<nsIStreamListener> listener;
   if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, 
                                        loadGroup, nullptr, 
                                        getter_AddRefs(listener),
                                        false))) {
     NS_ERROR("XMLDocument::Load: Failed to start the document load.");
-    return rv;
+    aRv.Throw(rv);
+    return false;
   }
 
   // After this point, if we error out of this method we should clear
   // mChannelIsPending.
 
   // Start an asynchronous read of the XML document
   rv = channel->AsyncOpen(listener, nullptr);
   if (NS_FAILED(rv)) {
     mChannelIsPending = false;
-    return rv;
+    aRv.Throw(rv);
+    return false;
   }
 
   if (!mAsync) {
     nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
 
     nsAutoSyncOperation sync(this);
     mLoopingForSyncLoad = true;
     while (mLoopingForSyncLoad) {
       if (!NS_ProcessNextEvent(thread))
         break;
     }
 
     // We set return to true unless there was a parsing error
-    nsCOMPtr<nsIDOMNode> node = do_QueryInterface(GetRootElement());
-    if (node) {
-      nsAutoString name, ns;      
-      if (NS_SUCCEEDED(node->GetLocalName(name)) &&
-          name.EqualsLiteral("parsererror") &&
-          NS_SUCCEEDED(node->GetNamespaceURI(ns)) &&
-          ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) {
-        //return is already false
-      } else {
-        *aReturn = true;
+    Element* rootElement = GetRootElement();
+    if (!rootElement) {
+      return false;
+    }
+
+    if (rootElement->LocalName().EqualsLiteral("parsererror")) {
+      nsAutoString ns;
+      rootElement->GetNamespaceURI(ns);
+      if (ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) {
+        return false;
       }
     }
-  } else {
-    *aReturn = true;
   }
 
-  return NS_OK;
+  return true;
 }
 
 nsresult
 XMLDocument::StartDocumentLoad(const char* aCommand,
                                nsIChannel* aChannel,
                                nsILoadGroup* aLoadGroup,
                                nsISupports* aContainer,
                                nsIStreamListener **aDocListener,
--- a/content/xml/document/src/XMLDocument.h
+++ b/content/xml/document/src/XMLDocument.h
@@ -46,16 +46,33 @@ public:
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
   // DocSizeOfIncludingThis is inherited from nsIDocument.
 
+
+  // WebIDL API
+  bool Load(const nsAString& aUrl, mozilla::ErrorResult& aRv);
+  bool Async() const
+  {
+    return mAsync;
+  }
+  // The XPCOM SetAsync is ok for us
+
+  // .location is [Unforgeable], so we have to make it clear that the
+  // nsIDocument version applies to us (it's shadowed by the XPCOM thing on
+  // nsDocument).
+  using nsIDocument::GetLocation;
+  // But then we need to also pull in the nsDocument XPCOM version
+  // because nsXULDocument tries to forward to it.
+  using nsDocument::GetLocation;
+
 protected:
   // mChannelIsPending indicates whether we're currently asynchronously loading
   // data from mChannel (via document.load() or normal load).  It's set to true
   // when we first find out about the channel (StartDocumentLoad) and set to
   // false in EndLoad or if ResetToURI() is called.  In the latter case our
   // mChannel is also cancelled.  Note that if this member is true, mChannel
   // cannot be null.
   bool mChannelIsPending;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/XMLDocument.webidl
@@ -0,0 +1,23 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is:
+ * http://dom.spec.whatwg.org/#xmldocument
+ * http://www.whatwg.org/specs/web-apps/current-work/#xmldocument
+ */
+
+// http://dom.spec.whatwg.org/#xmldocument
+interface XMLDocument : Document {};
+
+// http://www.whatwg.org/specs/web-apps/current-work/#xmldocument
+partial interface XMLDocument {
+  [Throws]
+  boolean load(DOMString url);
+};
+
+// Gecko extensions?
+partial interface XMLDocument {
+  attribute boolean async;
+};