Bug 792675. Part 1: Make the URL interface use WebIDL. r=bz
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 25 Sep 2012 15:24:43 +1200
changeset 112678 02a99623c5529ed02025385d67bf7e8aa800571b
parent 112677 78ee98d369d17d51feb1b4f9fcdffbf99a25eeb5
child 112679 fb9aee660b543fd0fdc2b5a5a1477678492c0064
push id23835
push userryanvm@gmail.com
push dateFri, 09 Nov 2012 00:52:02 +0000
treeherdermozilla-central@27ae6c86237f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs792675
milestone19.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 792675. Part 1: Make the URL interface use WebIDL. r=bz
dom/base/Makefile.in
dom/base/URL.cpp
dom/base/URL.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsPIDOMWindow.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/interfaces/base/nsIDOMWindow.idl
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/URL.webidl
dom/webidl/WebIDL.mk
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -79,16 +79,17 @@ EXPORTS = \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
   DOMError.h \
   DOMRequest.h \
   StructuredCloneTags.h \
   ScreenOrientation.h \
+  URL.h \
   $(NULL)
 
 CPPSRCS =			\
 	nsBarProps.cpp          \
 	nsDOMException.cpp 	\
 	nsDOMWindowUtils.cpp 	\
 	nsJSEnvironment.cpp	\
 	nsJSTimeoutHandler.cpp	\
@@ -110,16 +111,17 @@ CPPSRCS =			\
 	nsContentPermissionHelper.cpp \
 	nsStructuredCloneContainer.cpp \
 	nsDOMNavigationTiming.cpp \
 	nsPerformance.cpp	\
 	nsWindowMemoryReporter.cpp \
 	DOMError.cpp \
 	DOMRequest.cpp \
 	Navigator.cpp \
+	URL.cpp \
 	$(NULL)
 
 include $(topsrcdir)/dom/dom-config.mk
 
 ifdef MOZ_JSDEBUGGER
 DEFINES += -DMOZ_JSDEBUGGER
 endif
 
new file mode 100644
--- /dev/null
+++ b/dom/base/URL.cpp
@@ -0,0 +1,76 @@
+/* -*- 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 "nsIDOMFile.h"
+#include "nsIDocument.h"
+#include "nsIPrincipal.h"
+#include "nsContentUtils.h"
+#include "nsBlobProtocolHandler.h"
+
+namespace mozilla {
+namespace dom {
+
+void
+URL::CreateObjectURL(nsISupports* aGlobal, nsIDOMBlob* aBlob,
+                     const objectURLOptions& aOptions,
+                     nsAString& aResult,
+                     ErrorResult& aError)
+{
+  nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal);
+  nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
+  NS_PRECONDITION(!window || window->IsInnerWindow(),
+                  "Should be inner window");
+
+  if (!window || !window->GetExtantDoc()) {
+    aError.Throw(NS_ERROR_INVALID_POINTER);
+    return;
+  }
+
+  nsIDocument* doc = window->GetExtantDoc();
+
+  nsresult rv = aBlob->GetInternalUrl(doc->NodePrincipal(), aResult);
+  if (NS_FAILED(rv)) {
+    aError.Throw(rv);
+    return;
+  }
+
+  doc->RegisterFileDataUri(NS_LossyConvertUTF16toASCII(aResult));
+}
+
+void
+URL::RevokeObjectURL(nsISupports* aGlobal, const nsAString& aURL)
+{
+  nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aGlobal);
+  nsGlobalWindow* window = static_cast<nsGlobalWindow*>(w.get());
+  NS_PRECONDITION(!window || window->IsInnerWindow(),
+                  "Should be inner window");
+  if (!window)
+    return;
+
+  NS_LossyConvertUTF16toASCII asciiurl(aURL);
+
+  nsIPrincipal* winPrincipal = window->GetPrincipal();
+  if (!winPrincipal) {
+    return;
+  }
+
+  nsIPrincipal* principal =
+    nsBlobProtocolHandler::GetFileDataEntryPrincipal(asciiurl);
+  bool subsumes;
+  if (principal && winPrincipal &&
+      NS_SUCCEEDED(winPrincipal->Subsumes(principal, &subsumes)) &&
+      subsumes) {
+    if (window->GetExtantDoc()) {
+      window->GetExtantDoc()->UnregisterFileDataUri(asciiurl);
+    }
+    nsBlobProtocolHandler::RemoveFileDataEntry(asciiurl);
+  }
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/URL.h
@@ -0,0 +1,30 @@
+/* -*- 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/. */
+#ifndef URL_h___
+#define URL_h___
+
+#include "nscore.h"
+#include "mozilla/dom/URLBinding.h"
+
+class nsIDOMBlob;
+
+namespace mozilla {
+namespace dom {
+
+class URL MOZ_FINAL
+{
+public:
+  // WebIDL methods
+  static void CreateObjectURL(nsISupports* aGlobal, nsIDOMBlob* aBlob,
+                              const objectURLOptions& aOptions,
+                              nsAString& aResult,
+                              ErrorResult& aError);
+  static void RevokeObjectURL(nsISupports* aGlobal, const nsAString& aURL);
+};
+
+}
+}
+
+#endif /* URL_h___ */
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1429,18 +1429,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(FileReader, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ArchiveReader, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ArchiveRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
                            DEFAULT_SCRIPTABLE_FLAGS |
                            WINDOW_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DataContainerEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
@@ -4003,20 +4001,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMArchiveReader)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(ArchiveRequest, nsIDOMArchiveRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMArchiveRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(MozURLProperty, nsIDOMMozURLProperty)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
     DOM_CLASSINFO_WINDOW_MAP_ENTRIES(nsGlobalWindow::HasIndexedDBSupport())
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataContainerEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -361,17 +361,16 @@ DOMCI_CLASS(CommandEvent)
 DOMCI_CLASS(OfflineResourceList)
 
 DOMCI_CLASS(FileList)
 DOMCI_CLASS(Blob)
 DOMCI_CLASS(File)
 DOMCI_CLASS(FileReader)
 DOMCI_CLASS(ArchiveReader)
 DOMCI_CLASS(ArchiveRequest)
-DOMCI_CLASS(MozURLProperty)
 
 // DOM modal content window class, almost identical to Window
 DOMCI_CLASS(ModalContentWindow)
 
 // Data Events
 DOMCI_CLASS(DataContainerEvent)
 
 // event used for cross-domain message-passing and for server-sent events in
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -143,17 +143,16 @@
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIControllers.h"
 #include "nsIControllerContext.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsCSSProps.h"
-#include "nsBlobProtocolHandler.h"
 #include "nsIDOMFile.h"
 #include "nsIDOMFileList.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsEventDispatcher.h"
 #include "nsIObserverService.h"
 #include "nsIXULAppInfo.h"
 #include "nsNetUtil.h"
@@ -418,95 +417,16 @@ static const char kCryptoContractID[] = 
 static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID;
 #endif
 static const char sPopStatePrefStr[] = "browser.history.allowPopState";
 
 #define NETWORK_UPLOAD_EVENT_NAME     NS_LITERAL_STRING("moznetworkupload")
 #define NETWORK_DOWNLOAD_EVENT_NAME   NS_LITERAL_STRING("moznetworkdownload")
 
 /**
- * An object implementing the window.URL property.
- */
-class nsDOMMozURLProperty MOZ_FINAL : public nsIDOMMozURLProperty
-{
-public:
-  nsDOMMozURLProperty(nsGlobalWindow* aWindow)
-    : mWindow(aWindow)
-  {
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMMOZURLPROPERTY
-
-  void ClearWindowReference() {
-    mWindow = nullptr;
-  }
-private:
-  nsGlobalWindow* mWindow;
-};
-
-DOMCI_DATA(MozURLProperty, nsDOMMozURLProperty)
-NS_IMPL_ADDREF(nsDOMMozURLProperty)
-NS_IMPL_RELEASE(nsDOMMozURLProperty)
-NS_INTERFACE_MAP_BEGIN(nsDOMMozURLProperty)
-    NS_INTERFACE_MAP_ENTRY(nsIDOMMozURLProperty)
-    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozURLProperty)
-    NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozURLProperty)
-NS_INTERFACE_MAP_END
-
-NS_IMETHODIMP
-nsDOMMozURLProperty::CreateObjectURL(nsIDOMBlob* aBlob, nsAString& aURL)
-{
-  NS_PRECONDITION(!mWindow || mWindow->IsInnerWindow(),
-                  "Should be inner window");
-
-  NS_ENSURE_STATE(mWindow && mWindow->mDoc);
-  NS_ENSURE_ARG_POINTER(aBlob);
-
-  nsIDocument* doc = mWindow->mDoc;
-
-  nsresult rv = aBlob->GetInternalUrl(doc->NodePrincipal(), aURL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  doc->RegisterFileDataUri(NS_LossyConvertUTF16toASCII(aURL));
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMMozURLProperty::RevokeObjectURL(const nsAString& aURL)
-{
-  NS_PRECONDITION(!mWindow || mWindow->IsInnerWindow(),
-                  "Should be inner window");
-
-  NS_ENSURE_STATE(mWindow);
-
-  NS_LossyConvertUTF16toASCII asciiurl(aURL);
-
-  nsIPrincipal* winPrincipal = mWindow->GetPrincipal();
-  if (!winPrincipal) {
-    return NS_OK;
-  }
-
-  nsIPrincipal* principal =
-    nsBlobProtocolHandler::GetFileDataEntryPrincipal(asciiurl);
-  bool subsumes;
-  if (principal && winPrincipal &&
-      NS_SUCCEEDED(winPrincipal->Subsumes(principal, &subsumes)) &&
-      subsumes) {
-    if (mWindow->mDoc) {
-      mWindow->mDoc->UnregisterFileDataUri(asciiurl);
-    }
-    nsBlobProtocolHandler::RemoveFileDataEntry(asciiurl);
-  }
-
-  return NS_OK;
-}
-
-/**
  * An indirect observer object that means we don't have to implement nsIObserver
  * on nsGlobalWindow, where any script could see it.
  */
 class nsGlobalWindowObserver MOZ_FINAL : public nsIObserver,
                                          public nsIInterfaceRequestor
 {
 public:
   nsGlobalWindowObserver(nsGlobalWindow* aWindow) : mWindow(aWindow) {}
@@ -923,20 +843,16 @@ nsGlobalWindow::~nsGlobalWindow()
   NS_ASSERTION(!mArguments, "mArguments wasn't cleaned up properly!");
 
   CleanUp(true);
 
 #ifdef DEBUG
   nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject*>(this));
 #endif
 
-  if (mURLProperty) {
-    mURLProperty->ClearWindowReference();
-  }
-
   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   if (ac)
     ac->RemoveWindowAsListener(this);
 
   nsLayoutStatics::Release();
 }
 
 void
@@ -10765,30 +10681,16 @@ nsGlobalWindow::DisableDeviceSensor(uint
   }
 
   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   if (ac) {
     ac->RemoveWindowListener(aType, this);
   }
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL)
-{
-  FORWARD_TO_INNER(GetURL, (aURL), NS_ERROR_UNEXPECTED);
-
-  if (!mURLProperty) {
-    mURLProperty = new nsDOMMozURLProperty(this);
-  }
-
-  NS_ADDREF(*aURL = mURLProperty);
-
-  return NS_OK;
-}
-
 void
 nsGlobalWindow::EnableTimeChangeNotifications()
 {
   nsSystemTimeChangeObserver::AddWindowListener(this);
 }
 
 void
 nsGlobalWindow::DisableTimeChangeNotifications()
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -106,29 +106,29 @@ class nsPerformance;
 class nsIDocShellLoadInfo;
 class WindowStateHolder;
 class nsGlobalWindowObserver;
 class nsGlobalWindow;
 class PostMessageEvent;
 class nsRunnable;
 class nsDOMEventTargetHelper;
 class nsDOMOfflineResourceList;
-class nsDOMMozURLProperty;
 class nsDOMWindowUtils;
 class nsIIdleService;
 
 #ifdef MOZ_DISABLE_DOMCRYPTO
 class nsIDOMCrypto;
 #endif
 
 class nsWindowSizes;
 
 namespace mozilla {
 namespace dom {
 class Navigator;
+class URL;
 } // namespace dom
 } // namespace mozilla
 
 extern nsresult
 NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
                           bool *aIsInterval,
                           int32_t *aInterval,
                           nsIScriptTimeoutHandler **aRet);
@@ -277,18 +277,16 @@ class nsGlobalWindow : public nsPIDOMWin
                        public nsITouchEventReceiver,
                        public nsIInlineEventHandlers,
                        public nsIWindowCrypto
 #ifdef MOZ_B2G
                      , public nsIDOMWindowB2G
 #endif // MOZ_B2G
 {
 public:
-  friend class nsDOMMozURLProperty;
-
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
   typedef mozilla::dom::Navigator Navigator;
   typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindow*> WindowByIdTable;
 
   // public methods
   nsPIDOMWindow* GetPrivateParent();
   // callback for close event
@@ -1123,18 +1121,16 @@ protected:
   // mDialogAbuseCount gets reset.
   bool                          mStopAbuseDialogs;
 
   // This flag gets set when dialogs should be permanently disabled for this
   // window (e.g. when we are closing the tab and therefore are guaranteed to be
   // destroying this window).
   bool                          mDialogsPermanentlyDisabled;
 
-  nsRefPtr<nsDOMMozURLProperty> mURLProperty;
-
   nsTHashtable<nsPtrHashKey<nsDOMEventTargetHelper> > mEventTargetObjects;
 
   nsTArray<uint32_t> mEnabledSensors;
 
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
   friend class PostMessageEvent;
 
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -43,18 +43,18 @@ class nsIDocument;
 class nsIScriptTimeoutHandler;
 struct nsTimeout;
 template <class> class nsScriptObjectHolder;
 class nsXBLPrototypeHandler;
 class nsIArray;
 class nsPIWindowRoot;
 
 #define NS_PIDOMWINDOW_IID \
-{ 0x54fd92bd, 0xda33, 0x4451, \
-  { 0x8f, 0xb5, 0x11, 0x20, 0x5c, 0x03, 0xce, 0xaa } }
+{ 0x7b18e421, 0x2179, 0x4e24, \
+  { 0x96, 0x58, 0x26, 0x75, 0xa4, 0x37, 0xf3, 0x8f } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -360,16 +360,20 @@ DOMInterfaces = {
     'headerFile': 'DOMSVGTransformList.h',
     'resultNotAddRefed': [ 'getItem' ]
 },
 
 'TextEncoder': {
     'implicitJSContext': [ 'encode' ],
 },
 
+'URL' : {
+    'concrete': False,
+},
+
 'WebGLActiveInfo': {
    'nativeType': 'mozilla::WebGLActiveInfo',
    'headerFile': 'WebGLContext.h',
    'wrapperCache': False
 },
 
 'WebGLBuffer': {
    'nativeType': 'mozilla::WebGLBuffer',
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5631,60 +5631,63 @@ def stripTrailingWhitespace(text):
 
 class CGDescriptor(CGThing):
     def __init__(self, descriptor):
         CGThing.__init__(self)
 
         assert not descriptor.concrete or descriptor.interface.hasInterfacePrototypeObject()
 
         cgThings = []
-        if descriptor.interface.hasInterfacePrototypeObject():
-            # These are set to true if at least one non-static
-            # method/getter/setter exist on the interface.
-            (hasMethod, hasGetter, hasLenientGetter,
-             hasSetter, hasLenientSetter) = False, False, False, False, False
-            for m in descriptor.interface.members:
-                if (m.isMethod() and
-                    (not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
-                    if m.isStatic():
-                        cgThings.append(CGStaticMethod(descriptor, m))
+        # These are set to true if at least one non-static
+        # method/getter/setter exist on the interface.
+        (hasMethod, hasGetter, hasLenientGetter,
+         hasSetter, hasLenientSetter) = False, False, False, False, False
+        for m in descriptor.interface.members:
+            if (m.isMethod() and
+                (not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
+                if m.isStatic():
+                    assert descriptor.interface.hasInterfaceObject
+                    cgThings.append(CGStaticMethod(descriptor, m))
+                elif descriptor.interface.hasInterfacePrototypeObject():
+                    cgThings.append(CGSpecializedMethod(descriptor, m))
+                    cgThings.append(CGMemberJITInfo(descriptor, m))
+                    hasMethod = True
+            elif m.isAttr():
+                if m.isStatic():
+                    assert descriptor.interface.hasInterfaceObject
+                    cgThings.append(CGStaticGetter(descriptor, m))
+                elif descriptor.interface.hasInterfacePrototypeObject():
+                    cgThings.append(CGSpecializedGetter(descriptor, m))
+                    if m.hasLenientThis():
+                        hasLenientGetter = True
                     else:
-                        cgThings.append(CGSpecializedMethod(descriptor, m))
-                        cgThings.append(CGMemberJITInfo(descriptor, m))
-                        hasMethod = True
-                elif m.isAttr():
+                        hasGetter = True
+                if not m.readonly:
                     if m.isStatic():
-                        cgThings.append(CGStaticGetter(descriptor, m))
-                    else:
-                        cgThings.append(CGSpecializedGetter(descriptor, m))
+                        assert descriptor.interface.hasInterfaceObject
+                        cgThings.append(CGStaticSetter(descriptor, m))
+                    elif descriptor.interface.hasInterfacePrototypeObject():
+                        cgThings.append(CGSpecializedSetter(descriptor, m))
                         if m.hasLenientThis():
-                            hasLenientGetter = True
+                            hasLenientSetter = True
                         else:
-                            hasGetter = True
-                    if not m.readonly:
-                        if m.isStatic():
-                            cgThings.append(CGStaticSetter(descriptor, m))
-                        else:
-                            cgThings.append(CGSpecializedSetter(descriptor, m))
-                            if m.hasLenientThis():
-                                hasLenientSetter = True
-                            else:
-                                hasSetter = True
-                    elif m.getExtendedAttribute("PutForwards"):
-                        cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
-                        hasSetter = True
-                    if not m.isStatic():
-                        cgThings.append(CGMemberJITInfo(descriptor, m))
-            if hasMethod: cgThings.append(CGGenericMethod(descriptor))
-            if hasGetter: cgThings.append(CGGenericGetter(descriptor))
-            if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
-                                                                 lenientThis=True))
-            if hasSetter: cgThings.append(CGGenericSetter(descriptor))
-            if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
-                                                                 lenientThis=True))
+                            hasSetter = True
+                elif m.getExtendedAttribute("PutForwards"):
+                    cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
+                    hasSetter = True
+                if (not m.isStatic() and
+                    descriptor.interface.hasInterfacePrototypeObject()):
+                    cgThings.append(CGMemberJITInfo(descriptor, m))
+        if hasMethod: cgThings.append(CGGenericMethod(descriptor))
+        if hasGetter: cgThings.append(CGGenericGetter(descriptor))
+        if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
+                                                             lenientThis=True))
+        if hasSetter: cgThings.append(CGGenericSetter(descriptor))
+        if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
+                                                             lenientThis=True))
 
         if descriptor.concrete:
             if descriptor.nativeOwnership == 'owned' or descriptor.nativeOwnership == 'refcounted':
                 cgThings.append(CGDeferredFinalizePointers(descriptor))
                 cgThings.append(CGGetDeferredFinalizePointers(descriptor))
                 cgThings.append(CGDeferredFinalize(descriptor))
 
             if not descriptor.proxy:
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -11,33 +11,26 @@ interface nsIDOMBlob;
 interface nsIDOMLocation;
 interface nsIDOMMediaQueryList;
 interface nsIDOMOfflineResourceList;
 interface nsIDOMStorage;
 interface nsIPrompt;
 interface nsISelection;
 interface nsIVariant;
 
-[scriptable, uuid(8fc58f56-f769-4368-a098-edd08550cf1a)]
-interface nsIDOMMozURLProperty : nsISupports
-{
-  DOMString createObjectURL(in nsIDOMBlob blob);
-  void revokeObjectURL(in DOMString URL);
-};
-
 /**
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
  * @see <http://www.whatwg.org/html/#window>
  */
 
-[scriptable, uuid(1534ecd7-e298-420e-9063-e6c2d1243d49)]
+[scriptable, uuid(b9c71e0b-7f81-419a-8253-91f4c8893c4f)]
 interface nsIDOMWindow : nsISupports
 {
   // the current browsing context
   readonly attribute nsIDOMWindow                       window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindow                       self;
 
@@ -457,21 +450,16 @@ interface nsIDOMWindow : nsISupports
   void mozCancelRequestAnimationFrame(in long aHandle);
 
   /**
    * The current animation start time in milliseconds since the epoch.
    */
   readonly attribute long long mozAnimationStartTime;
 
   /**
-   * @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
-   */
-  readonly attribute nsIDOMMozURLProperty URL;
-
-  /**
    * HTML5 event attributes that only apply to windows and <body>/<frameset>
    */
   [implicit_jscontext] attribute jsval onafterprint;
   [implicit_jscontext] attribute jsval onbeforeprint;
   [implicit_jscontext] attribute jsval onbeforeunload;
   [implicit_jscontext] attribute jsval onhashchange;
   [implicit_jscontext] attribute jsval onmessage;
   [implicit_jscontext] attribute jsval onoffline;
@@ -520,10 +508,10 @@ interface nsIWindowCrypto : nsISupports
   readonly attribute nsIDOMCrypto                       crypto;
   readonly attribute nsIDOMPkcs11                       pkcs11;
 };
 
 /**
  * Empty interface for compatibility with older versions.
  * @deprecated Use nsIDOMWindow instead
  */
-[scriptable, uuid(8da641ab-906a-456e-97f2-b77df4ca2d95)]
+[scriptable, uuid(a5cd0946-bac1-4606-9aaa-9e68dd0a3279)]
 interface nsIDOMWindowInternal : nsIDOMWindow {};
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -337,17 +337,17 @@ var interfaceNamesInGlobalScope =
     "MozSmsManager",
     "MozSmsFilter",
     "SVGFETileElement",
     "MozMobileConnectionInfo",
     "CSSRule",
     "HTMLSelectElement",
     "MessageEvent",
     "SVGFEImageElement",
-    "MozURLProperty",
+    "URL",
     "DeviceStorage",
     "SVGFEOffsetElement",
     "DOMImplementation",
     "SVGFECompositeElement",
     "MediaList",
     "HTMLFrameElement",
     "NodeList",
     "SVGPathSegCurvetoQuadraticRel",
new file mode 100644
--- /dev/null
+++ b/dom/webidl/URL.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 origins of this IDL file are
+ * http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking
+ * http://dev.w3.org/2011/webrtc/editor/getusermedia.html#url
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface URL {
+  [Throws]
+  static DOMString? createObjectURL(Blob blob, optional objectURLOptions options);
+  static void revokeObjectURL(DOMString url);
+};
+
+dictionary objectURLOptions
+{
+/* boolean autoRevoke = true; */ /* not supported yet */
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -47,16 +47,17 @@ webidl_files = \
   Screen.webidl \
   SVGLengthList.webidl \
   SVGNumberList.webidl \
   SVGPathSegList.webidl \
   SVGPointList.webidl \
   SVGTransformList.webidl \
   TextDecoder.webidl \
   TextEncoder.webidl \
+  URL.webidl \
   WebSocket.webidl \
   XMLHttpRequest.webidl \
   XMLHttpRequestEventTarget.webidl \
   XMLHttpRequestUpload.webidl \
   $(NULL)
 
 ifdef MOZ_WEBGL
 webidl_files += \