Bug 608171 - Make ChromeWorkers available to JSMs. r=bent.
authorJason Orendorff <jorendorff@mozilla.com>
Tue, 16 Nov 2010 14:53:47 -0600
changeset 57827 f3cfb74fd41301d9d01d942a53aaffa30d2678f9
parent 57826 f1a334334d13dd84a8171cf650af24a15f926c8e
child 57828 9baf4ce0920b157152e6f17323ea2fb08a01d498
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersbent
bugs608171
milestone2.0b8pre
Bug 608171 - Make ChromeWorkers available to JSMs. r=bent.
dom/base/nsDOMClassInfo.cpp
dom/interfaces/threads/nsIDOMWorkers.idl
dom/src/threads/nsDOMWorker.cpp
dom/src/threads/nsDOMWorker.h
dom/src/threads/test/Makefile.in
dom/src/threads/test/test_chromeWorker.html
dom/src/threads/test/test_chromeWorkerComponent.xul
layout/build/nsLayoutModule.cpp
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3947,18 +3947,17 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(Worker, nsIWorker)
     DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
     DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(ChromeWorker, nsIChromeWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIChromeWorker)
+  DOM_CLASSINFO_MAP_BEGIN(ChromeWorker, nsIWorker)
     DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
     DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CanvasRenderingContextWebGL, nsICanvasRenderingContextWebGL)
     DOM_CLASSINFO_MAP_ENTRY(nsICanvasRenderingContextWebGL)
--- a/dom/interfaces/threads/nsIDOMWorkers.idl
+++ b/dom/interfaces/threads/nsIDOMWorkers.idl
@@ -139,12 +139,18 @@ interface nsIWorker : nsIAbstractWorker
 {
   void postMessage(/* in JSObject aMessage */);
 
   attribute nsIDOMEventListener onmessage;
 
   void terminate();
 };
 
-[scriptable, uuid(c40dfe2c-c9d4-4c48-8e5d-adc99f207dd2)]
-interface nsIChromeWorker : nsIWorker
+[scriptable, uuid(cfc4bb32-ca83-4d58-9b6f-66f8054a333a)]
+interface nsIWorkerFactory : nsISupports
 {
+    nsIWorker newChromeWorker(/* in DOMString aScriptURL */);
 };
+
+%{ C++
+#define NS_WORKERFACTORY_CONTRACTID \
+"@mozilla.org/threads/workerfactory;1"
+%}
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -1173,55 +1173,62 @@ nsDOMWorker::NewWorker(nsISupports** aNe
   NS_ENSURE_TRUE(newWorker, NS_ERROR_OUT_OF_MEMORY);
 
   newWorker.forget(aNewObject);
   return NS_OK;
 }
 
 // static
 nsresult
-nsDOMWorker::NewChromeWorker(nsISupports** aNewObject)
+nsDOMWorker::NewChromeDOMWorker(nsDOMWorker** aNewObject)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   // Subsumes nsContentUtils::IsCallerChrome
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   NS_ASSERTION(ssm, "Should never be null!");
 
   PRBool enabled;
   nsresult rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &enabled);
   NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(enabled, NS_ERROR_DOM_SECURITY_ERR);
 
-  if(!enabled) {
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  nsCOMPtr<nsISupports> newWorker =
-    NS_ISUPPORTS_CAST(nsIWorker*, new nsDOMWorker(nsnull, nsnull, CHROME));
+  nsRefPtr<nsDOMWorker> newWorker = new nsDOMWorker(nsnull, nsnull, CHROME);
   NS_ENSURE_TRUE(newWorker, NS_ERROR_OUT_OF_MEMORY);
 
   newWorker.forget(aNewObject);
   return NS_OK;
 }
 
+// static
+nsresult
+nsDOMWorker::NewChromeWorker(nsISupports** aNewObject)
+{
+  nsDOMWorker* newWorker;
+  nsresult rv = NewChromeDOMWorker(&newWorker);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aNewObject = NS_ISUPPORTS_CAST(nsIWorker*, newWorker);
+  return NS_OK;
+}
+
 NS_IMPL_ADDREF_INHERITED(nsDOMWorker, nsDOMWorkerMessageHandler)
 NS_IMPL_RELEASE_INHERITED(nsDOMWorker, nsDOMWorkerMessageHandler)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMWorker)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWorker)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIWorker)
   NS_INTERFACE_MAP_ENTRY(nsIAbstractWorker)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMNSEventTarget,
                                    nsDOMWorkerMessageHandler)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventTarget, nsDOMWorkerMessageHandler)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeWorker, IsPrivileged())
 NS_INTERFACE_MAP_END
 
 // Use the xpc_map_end.h macros to generate the nsIXPCScriptable methods we want
 // for the worker.
 
 #define XPC_MAP_CLASSNAME nsDOMWorker
 #define XPC_MAP_QUOTED_CLASSNAME "Worker"
 #define XPC_MAP_WANT_PRECREATE
@@ -1240,18 +1247,21 @@ NS_INTERFACE_MAP_END
 #include "xpc_map_end.h"
 
 NS_IMETHODIMP
 nsDOMWorker::PreCreate(nsISupports* aObject,
                        JSContext* /* aCx */,
                        JSObject* /* aPlannedParent */,
                        JSObject** /* aParent */)
 {
-  nsCOMPtr<nsIChromeWorker> privilegedWorker(do_QueryInterface(aObject));
-  return privilegedWorker ? NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
+  nsCOMPtr<nsIWorker> iworker(do_QueryInterface(aObject));
+  if (iworker && static_cast<nsDOMWorker *>(iworker.get())->IsPrivileged()) {
+    return NS_SUCCESS_CHROME_ACCESS_ONLY;
+  }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWorker::PostCreate(nsIXPConnectWrappedNative* aWrapper,
                         JSContext* /* aCx */,
                         JSObject* /* aObj */)
 {
   nsAutoLock lock(mLock);
@@ -1300,17 +1310,16 @@ nsDOMWorker::Finalize(nsIXPConnectWrappe
   if (TerminateInternal(PR_TRUE) == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
     // We're shutting down, jump right to Kill.
     Kill();
   }
 
   return NS_OK;
 }
 
-// Keep this list in sync with the list in nsDOMClassInfo.cpp!
 NS_IMPL_CI_INTERFACE_GETTER4(nsDOMWorker, nsIWorker,
                                           nsIAbstractWorker,
                                           nsIDOMNSEventTarget,
                                           nsIDOMEventTarget)
 NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorker)
 NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorker)
 
 NS_IMETHODIMP
@@ -2307,8 +2316,57 @@ nsDOMWorker::Terminate()
 
 NS_IMETHODIMP
 nsDOMWorker::Notify(nsITimer* aTimer)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   Kill();
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsWorkerFactory::NewChromeWorker(nsIWorker** _retval)
+{
+  nsresult rv;
+
+  // Get the arguments from XPConnect.
+  nsCOMPtr<nsIXPConnect> xpc;
+  xpc = do_GetService(nsIXPConnect::GetCID());
+  NS_ASSERTION(xpc, "Could not get XPConnect");
+
+  nsAXPCNativeCallContext* cc;
+  rv = xpc->GetCurrentNativeCallContext(&cc);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  JSContext* cx;
+  rv = cc->GetJSContext(&cx);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRUint32 argc;
+  rv = cc->GetArgc(&argc);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  jsval* argv;
+  rv = cc->GetArgvPtr(&argv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Determine the current script global. We need it to register the worker.
+  // NewChromeDOMWorker will check that we are chrome, so no access check.
+  JSObject* globalobj = JS_GetGlobalForScopeChain(cx);
+  NS_ENSURE_TRUE(globalobj, NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIScriptGlobalObject> global =
+    nsJSUtils::GetStaticScriptGlobal(cx, globalobj);
+  NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
+
+  // Create, initialize, and return the worker.
+  nsRefPtr<nsDOMWorker> chromeWorker;
+  rv = nsDOMWorker::NewChromeDOMWorker(getter_AddRefs(chromeWorker));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = chromeWorker->InitializeInternal(global, cx, globalobj, argc, argv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  chromeWorker.forget(_retval);
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(nsWorkerFactory, nsIWorkerFactory)
--- a/dom/src/threads/nsDOMWorker.h
+++ b/dom/src/threads/nsDOMWorker.h
@@ -1,9 +1,9 @@
-/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -50,16 +50,21 @@
 #include "jsapi.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsTPtrArray.h"
 #include "prlock.h"
 
 #include "nsDOMWorkerMessageHandler.h"
 
+// {1295EFB5-8644-42B2-8B8E-80EEF56E4284}
+#define NS_WORKERFACTORY_CID \
+ {0x1295efb5, 0x8644, 0x42b2, \
+  {0x8b, 0x8e, 0x80, 0xee, 0xf5, 0x6e, 0x42, 0x84} }
+
 class nsDOMWorker;
 class nsDOMWorkerFeature;
 class nsDOMWorkerMessageHandler;
 class nsDOMWorkerNavigator;
 class nsDOMWorkerPool;
 class nsDOMWorkerTimeout;
 class nsICancelable;
 class nsIDOMEventListener;
@@ -128,17 +133,17 @@ public:
     other.mCx = tmp;
   }
 
 private:
   JSContext *mCx;
 };
 
 class nsDOMWorker : public nsDOMWorkerMessageHandler,
-                    public nsIChromeWorker,
+                    public nsIWorker,
                     public nsITimerCallback,
                     public nsIJSNativeInitializer,
                     public nsIXPCScriptable
 {
   friend class nsDOMWorkerFeature;
   friend class nsDOMWorkerFunctions;
   friend class nsDOMWorkerScope;
   friend class nsDOMWorkerScriptLoader;
@@ -159,23 +164,23 @@ public:
   // nsIDOMNSEventTarget
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               PRBool aUseCapture,
                               PRBool aWantsUntrusted,
                               PRUint8 optional_argc);
   NS_DECL_NSIABSTRACTWORKER
   NS_DECL_NSIWORKER
-  NS_DECL_NSICHROMEWORKER
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSICLASSINFO
   NS_DECL_NSIXPCSCRIPTABLE
 
   static nsresult NewWorker(nsISupports** aNewObject);
   static nsresult NewChromeWorker(nsISupports** aNewObject);
+  static nsresult NewChromeDOMWorker(nsDOMWorker** aNewObject);
 
   enum WorkerPrivilegeModel { CONTENT, CHROME };
 
   nsDOMWorker(nsDOMWorker* aParent,
               nsIXPConnectWrappedNative* aParentWN,
               WorkerPrivilegeModel aModel);
 
   NS_IMETHOD Initialize(nsISupports* aOwner,
@@ -430,9 +435,16 @@ protected:
   nsCOMPtr<nsIXPConnectWrappedNative> mWorkerWN;
   PRUint32 mId;
 
 private:
   PRPackedBool mHasId;
   PRPackedBool mFreeToDie;
 };
 
+class nsWorkerFactory : public nsIWorkerFactory
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIWORKERFACTORY
+};
+
 #endif /* __NSDOMWORKER_H__ */
--- a/dom/src/threads/test/Makefile.in
+++ b/dom/src/threads/test/Makefile.in
@@ -115,16 +115,17 @@ include $(topsrcdir)/config/rules.mk
 _SUBDIR_TEST_FILES = \
   relativeLoad_sub_worker.js \
   relativeLoad_sub_worker2.js \
   relativeLoad_sub_import.js \
   $(NULL)
 
 _CHROME_TEST_FILES = \
   test_chromeWorker.xul \
+  test_chromeWorkerComponent.xul \
   chromeWorker_worker.js \
   chromeWorker_subworker.js \
   $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_SUBDIR_TEST_FILES)
--- a/dom/src/threads/test/test_chromeWorker.html
+++ b/dom/src/threads/test/test_chromeWorker.html
@@ -12,13 +12,23 @@
   try {
     var worker = new ChromeWorker("simpleThread_worker.js");
     ok(false, "ChromeWorker constructor should be blocked!");
   }
   catch (e) {
     ok(true, "ChromeWorker constructor wasn't blocked!");
   }
 
+  try {
+    var worker = Components.classes["@mozilla.org/threads/workerfactory;1"]
+      .createInstance(Components.interfaces.nsIWorkerFactory)
+      .newChromeWorker("simpleThread_worker.js");
+    ok(false, "nsIWorkerFactory should be blocked!");
+  }
+  catch (e) {
+    ok(true, "nsIWorkerFactory wasn't blocked!");
+  }
+
 </script>
 </pre>
 </body>
 </html>
 
new file mode 100644
--- /dev/null
+++ b/dom/src/threads/test/test_chromeWorkerComponent.xul
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is DOM Worker tests.
+   -
+   - The Initial Developer of the Original Code is
+   - The Mozilla Foundation.
+   - Portions created by the Initial Developer are Copyright (C) 2010
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Ben Turner <bent.mozilla@gmail.com>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the LGPL or the GPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+<window title="DOM Worker Threads Test"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="test();">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"/>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+  <script type="application/javascript">
+  <![CDATA[
+
+    function test()
+    {
+      SimpleTest.waitForExplicitFinish();
+      const Cc = Components.classes;
+      const Ci = Components.interfaces;
+      var wf = Cc["@mozilla.org/threads/workerfactory;1"]
+        .createInstance(Ci.nsIWorkerFactory);
+
+      var worker = wf.newChromeWorker("chromeWorker_worker.js");
+      worker.onmessage = function(event) {
+        is(event.data, "Done!", "Wrong message!");
+        SimpleTest.finish();
+      }
+      worker.onerror = function(event) {
+        ok(false, "Worker had an error: " + event.message);
+        worker.terminate();
+        SimpleTest.finish();
+      }
+    }
+
+  ]]>
+  </script>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <p id="display"></p>
+    <div id="content" style="display:none;"></div>
+    <pre id="test"></pre>
+  </body>
+  <label id="test-result"/>
+</window>
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -109,16 +109,17 @@
 #include "txNodeSetAdaptor.h"
 #include "nsXPath1Scheme.h"
 
 #include "nsDOMParser.h"
 #include "nsDOMSerializer.h"
 #include "nsXMLHttpRequest.h"
 #include "nsChannelPolicy.h"
 #include "nsWebSocket.h"
+#include "nsDOMWorker.h"
 
 // view stuff
 #include "nsViewsCID.h"
 #include "nsViewManager.h"
 #include "nsContentCreatorFunctions.h"
 
 // DOM includes
 #include "nsDOMException.h"
@@ -328,16 +329,17 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
                                          IndexedDatabaseManager::FactoryCreate)
 #if defined(XP_UNIX)    || \
     defined(_WINDOWS)   || \
     defined(machintosh) || \
     defined(android)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAccelerometerSystem)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ThirdPartyUtil, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsWorkerFactory)
 
 //-----------------------------------------------------------------------------
 
 // Per bug 209804, it is necessary to observe the "xpcom-shutdown" event and
 // perform shutdown of the layout modules at that time instead of waiting for
 // our module destructor to run.  If we do not do this, then we risk holding
 // references to objects in other component libraries that have already been
 // shutdown (and possibly unloaded if 60709 is ever fixed).
@@ -881,16 +883,17 @@ NS_DEFINE_NAMED_CID(NS_PARENTPROCESSMESS
 NS_DEFINE_NAMED_CID(NS_CHILDPROCESSMESSAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NSCHANNELPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_SCRIPTSECURITYMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_PRINCIPAL_CID);
 NS_DEFINE_NAMED_CID(NS_SYSTEMPRINCIPAL_CID);
 NS_DEFINE_NAMED_CID(NS_NULLPRINCIPAL_CID);
 NS_DEFINE_NAMED_CID(NS_SECURITYNAMESET_CID);
 NS_DEFINE_NAMED_CID(THIRDPARTYUTIL_CID);
+NS_DEFINE_NAMED_CID(NS_WORKERFACTORY_CID);
 
 #if defined(XP_UNIX)    || \
     defined(_WINDOWS)   || \
     defined(machintosh) || \
     defined(android)
 NS_DEFINE_NAMED_CID(NS_ACCELEROMETER_CID);
 #endif
 
@@ -1038,16 +1041,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_SECURITYNAMESET_CID, false, NULL, nsSecurityNameSetConstructor },
 #if defined(XP_UNIX)    || \
     defined(_WINDOWS)   || \
     defined(machintosh) || \
     defined(android)
   { &kNS_ACCELEROMETER_CID, false, NULL, nsAccelerometerSystemConstructor },
 #endif
   { &kTHIRDPARTYUTIL_CID, false, NULL, ThirdPartyUtilConstructor },
+  { &kNS_WORKERFACTORY_CID, false, NULL, nsWorkerFactoryConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
   XPCONNECT_CONTRACTS
   { "@mozilla.org/layout/xul-boxobject;1", &kNS_BOXOBJECT_CID },
 #ifdef MOZ_XUL
   { "@mozilla.org/layout/xul-boxobject-listbox;1", &kNS_LISTBOXOBJECT_CID },
@@ -1184,16 +1188,17 @@ static const mozilla::Module::ContractID
   { NS_SECURITYNAMESET_CONTRACTID, &kNS_SECURITYNAMESET_CID },
 #if defined(XP_UNIX)    || \
     defined(_WINDOWS)   || \
     defined(machintosh) || \
     defined(android)
   { NS_ACCELEROMETER_CONTRACTID, &kNS_ACCELEROMETER_CID },
 #endif
   { THIRDPARTYUTIL_CONTRACTID, &kTHIRDPARTYUTIL_CID },
+  { NS_WORKERFACTORY_CONTRACTID, &kNS_WORKERFACTORY_CID },
   { NULL }
 };
 
 static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
   XPCONNECT_CATEGORIES
   { JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY, "Image", NS_HTMLIMGELEMENT_CONTRACTID },
   { JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY, "Image", "HTMLImageElement" },
   { JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY, "Option", NS_HTMLOPTIONELEMENT_CONTRACTID },