Bug 1099296 - Attach LoadInfo to remaining callers of ioService and ProtocolHandlers - websocket changes (r=jduell)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Tue, 17 Feb 2015 10:09:58 -0800
changeset 229537 e369969c0bdd106c9031741bb29ac02b888c47b2
parent 229536 f01170060577400ed845c1cf850df314b3cc9856
child 229538 b24695fc8d793288a8da01e1d84a997028ade671
push id28290
push userryanvm@gmail.com
push dateWed, 18 Feb 2015 02:34:43 +0000
treeherdermozilla-central@93ddd99ffd86 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs1099296
milestone38.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 1099296 - Attach LoadInfo to remaining callers of ioService and ProtocolHandlers - websocket changes (r=jduell)
docshell/base/LoadInfo.h
dom/base/WebSocket.cpp
netwerk/ipc/NeckoChannelParams.ipdlh
netwerk/protocol/websocket/BaseWebSocketChannel.cpp
netwerk/protocol/websocket/BaseWebSocketChannel.h
netwerk/protocol/websocket/PWebSocket.ipdl
netwerk/protocol/websocket/WebSocketChannelChild.cpp
netwerk/protocol/websocket/WebSocketChannelParent.cpp
netwerk/protocol/websocket/WebSocketChannelParent.h
netwerk/protocol/websocket/nsIWebSocketChannel.idl
netwerk/test/unit/test_dns_proxy_bypass.js
netwerk/test/unit/test_websocket_offline.js
--- a/docshell/base/LoadInfo.h
+++ b/docshell/base/LoadInfo.h
@@ -15,16 +15,17 @@
 
 class nsINode;
 
 namespace mozilla {
 
 namespace net {
 class HttpChannelParent;
 class FTPChannelParent;
+class WebSocketChannelParent;
 }
 
 /**
  * Class that provides an nsILoadInfo implementation.
  */
 class MOZ_EXPORT LoadInfo MOZ_FINAL : public nsILoadInfo
 {
 public:
@@ -46,16 +47,17 @@ private:
   LoadInfo(nsIPrincipal* aLoadingPrincipal,
            nsIPrincipal* aTriggeringPrincipal,
            nsSecurityFlags aSecurityFlags,
            nsContentPolicyType aContentPolicyType,
            uint32_t aInnerWindowID);
 
   friend class net::HttpChannelParent;
   friend class net::FTPChannelParent;
+  friend class net::WebSocketChannelParent;
 
   ~LoadInfo();
 
   nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   nsWeakPtr mLoadingContext;
   nsSecurityFlags mSecurityFlags;
   nsContentPolicyType mContentPolicyType;
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -1569,25 +1569,21 @@ WebSocketImpl::InitializeConnection()
   // manually adding loadinfo to the channel since it
   // was not set during channel creation.
   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mOriginDocument);
 
   // mOriginDocument has to be release on main-thread because WeakReferences
   // are not thread-safe.
   mOriginDocument = nullptr;
 
-  nsCOMPtr<nsILoadInfo> loadInfo =
-    new LoadInfo(doc ?
-                   doc->NodePrincipal() : mPrincipal.get(),
-                 mPrincipal,
-                 doc,
-                 nsILoadInfo::SEC_NORMAL,
-                 nsIContentPolicy::TYPE_WEBSOCKET);
-  rv = wsChannel->SetLoadInfo(loadInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
+  wsChannel->InitLoadInfo(doc ? doc->AsDOMNode() : nullptr,
+                          doc ? doc->NodePrincipal() : mPrincipal.get(),
+                          mPrincipal,
+                          nsILoadInfo::SEC_NORMAL,
+                          nsIContentPolicy::TYPE_WEBSOCKET);
 
   if (!mRequestedProtocolList.IsEmpty()) {
     rv = wsChannel->SetProtocol(mRequestedProtocolList);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(wsChannel);
   NS_ENSURE_TRUE(rr, NS_ERROR_FAILURE);
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -116,10 +116,23 @@ union ChannelDiverterArgs
 //-----------------------------------------------------------------------------
 
 struct RtspChannelConnectArgs
 {
   URIParams uri;
   uint32_t channelId;
 };
 
+//-----------------------------------------------------------------------------
+// WS IPDL structs
+//-----------------------------------------------------------------------------
+
+struct WebSocketLoadInfoArgs
+{
+  PrincipalInfo requestingPrincipalInfo;
+  PrincipalInfo triggeringPrincipalInfo;
+  uint32_t      securityFlags;
+  uint32_t      contentPolicyType;
+  uint32_t      innerWindowID;
+};
+
 } // namespace ipc
 } // namespace mozilla
--- a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp
@@ -177,16 +177,29 @@ BaseWebSocketChannel::SetPingTimeout(uin
   }
 
   mPingResponseTimeout = aSeconds * 1000;
   mClientSetPingTimeout = 1;
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+BaseWebSocketChannel::InitLoadInfo(nsIDOMNode* aLoadingNode,
+                                   nsIPrincipal* aLoadingPrincipal,
+                                   nsIPrincipal* aTriggeringPrincipal,
+                                   uint32_t aSecurityFlags,
+                                   uint32_t aContentPolicyType)
+{
+  nsCOMPtr<nsINode> node = do_QueryInterface(aLoadingNode);
+  mLoadInfo = new LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
+                           node, aSecurityFlags, aContentPolicyType);
+  return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // BaseWebSocketChannel::nsIProtocolHandler
 //-----------------------------------------------------------------------------
 
 
 NS_IMETHODIMP
 BaseWebSocketChannel::GetScheme(nsACString &aScheme)
 {
--- a/netwerk/protocol/websocket/BaseWebSocketChannel.h
+++ b/netwerk/protocol/websocket/BaseWebSocketChannel.h
@@ -47,16 +47,19 @@ class BaseWebSocketChannel : public nsIW
   NS_IMETHOD GetLoadInfo(nsILoadInfo **aLoadInfo) MOZ_OVERRIDE;
   NS_IMETHOD GetExtensions(nsACString &aExtensions) MOZ_OVERRIDE;
   NS_IMETHOD GetProtocol(nsACString &aProtocol) MOZ_OVERRIDE;
   NS_IMETHOD SetProtocol(const nsACString &aProtocol) MOZ_OVERRIDE;
   NS_IMETHOD GetPingInterval(uint32_t *aSeconds) MOZ_OVERRIDE;
   NS_IMETHOD SetPingInterval(uint32_t aSeconds) MOZ_OVERRIDE;
   NS_IMETHOD GetPingTimeout(uint32_t *aSeconds) MOZ_OVERRIDE;
   NS_IMETHOD SetPingTimeout(uint32_t aSeconds) MOZ_OVERRIDE;
+  NS_IMETHOD InitLoadInfo(nsIDOMNode* aLoadingNode, nsIPrincipal* aLoadingPrincipal,
+                          nsIPrincipal* aTriggeringPrincipal, uint32_t aSecurityFlags,
+                          uint32_t aContentPolicyType) MOZ_OVERRIDE;
 
   // Off main thread URI access.
   virtual void GetEffectiveURL(nsAString& aEffectiveURL) const = 0;
   virtual bool IsEncrypted() const = 0;
 
   class ListenerAndContextContainer MOZ_FINAL
   {
   public:
--- a/netwerk/protocol/websocket/PWebSocket.ipdl
+++ b/netwerk/protocol/websocket/PWebSocket.ipdl
@@ -4,16 +4,17 @@
 /* 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 protocol PNecko;
 include protocol PBrowser;
 include InputStreamParams;
 include URIParams;
+include NeckoChannelParams;
 
 include protocol PBlob; //FIXME: bug #792908
 
 using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
 
 namespace mozilla {
 namespace net {
 
@@ -26,17 +27,18 @@ parent:
   AsyncOpen(URIParams aURI,
             nsCString aOrigin,
             nsCString aProtocol,
             bool aSecure,
             // ping values only meaningful if client set them
             uint32_t aPingInterval,
             bool aClientSetPingInterval,
             uint32_t aPingTimeout,
-            bool aClientSetPingTimeout);
+            bool aClientSetPingTimeout,
+            WebSocketLoadInfoArgs aLoadInfoArgs);
   Close(uint16_t code, nsCString reason);
   SendMsg(nsCString aMsg);
   SendBinaryMsg(nsCString aMsg);
   SendBinaryStream(InputStreamParams aStream, uint32_t aLength);
 
   DeleteSelf();
 
 child:
--- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp
@@ -8,16 +8,17 @@
 #include "base/compiler_specific.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "WebSocketChannelChild.h"
 #include "nsITabChild.h"
 #include "nsNetUtil.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
+#include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/net/ChannelEventQueue.h"
 #include "SerializedLoadContext.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
@@ -447,16 +448,35 @@ WebSocketChannelChild::OnServerClose(con
   LOG(("WebSocketChannelChild::RecvOnServerClose() %p\n", this));
   if (mListenerMT) {
     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     mListenerMT->mListener->OnServerClose(mListenerMT->mContext, aCode,
                                           aReason);
   }
 }
 
+// helper function to assign loadInfo to wsArgs
+void
+propagateLoadInfo(nsILoadInfo *aLoadInfo,
+                  WebSocketLoadInfoArgs& wsArgs)
+{
+  mozilla::ipc::PrincipalInfo requestingPrincipalInfo;
+  mozilla::ipc::PrincipalInfo triggeringPrincipalInfo;
+
+  mozilla::ipc::PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(),
+                                         &requestingPrincipalInfo);
+  wsArgs.requestingPrincipalInfo() = requestingPrincipalInfo;
+  mozilla::ipc::PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(),
+                                         &triggeringPrincipalInfo);
+  wsArgs.triggeringPrincipalInfo() = triggeringPrincipalInfo;
+  wsArgs.securityFlags() = aLoadInfo->GetSecurityFlags();
+  wsArgs.contentPolicyType() = aLoadInfo->GetContentPolicyType();
+  wsArgs.innerWindowID() = aLoadInfo->GetInnerWindowID();
+}
+
 NS_IMETHODIMP
 WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
                                  const nsACString &aOrigin,
                                  nsIWebSocketListener *aListener,
                                  nsISupports *aContext)
 {
   LOG(("WebSocketChannelChild::AsyncOpen() %p\n", this));
 
@@ -477,22 +497,26 @@ WebSocketChannelChild::AsyncOpen(nsIURI 
   }
 
   URIParams uri;
   SerializeURI(aURI, uri);
 
   // Corresponding release in DeallocPWebSocket
   AddIPDLReference();
 
+  WebSocketLoadInfoArgs wsArgs;
+  propagateLoadInfo(mLoadInfo, wsArgs);
+
   gNeckoChild->SendPWebSocketConstructor(this, tabChild,
                                          IPC::SerializedLoadContext(this));
   if (!SendAsyncOpen(uri, nsCString(aOrigin), mProtocol, mEncrypted,
                      mPingInterval, mClientSetPingInterval,
-                     mPingResponseTimeout, mClientSetPingTimeout))
+                     mPingResponseTimeout, mClientSetPingTimeout, wsArgs)) {
     return NS_ERROR_UNEXPECTED;
+  }
 
   mOriginalURI = aURI;
   mURI = mOriginalURI;
   mListenerMT = new ListenerAndContextContainer(aListener, aContext);
   mOrigin = aOrigin;
   mWasOpened = 1;
 
   return NS_OK;
--- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp
@@ -4,16 +4,17 @@
  * 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 "WebSocketLog.h"
 #include "WebSocketChannelParent.h"
 #include "nsIAuthPromptProvider.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
+#include "mozilla/ipc/BackgroundUtils.h"
 #include "SerializedLoadContext.h"
 #include "nsIOService.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "mozilla/net/WebSocketChannel.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
@@ -61,23 +62,25 @@ WebSocketChannelParent::RecvDeleteSelf()
 bool
 WebSocketChannelParent::RecvAsyncOpen(const URIParams& aURI,
                                       const nsCString& aOrigin,
                                       const nsCString& aProtocol,
                                       const bool& aSecure,
                                       const uint32_t& aPingInterval,
                                       const bool& aClientSetPingInterval,
                                       const uint32_t& aPingTimeout,
-                                      const bool& aClientSetPingTimeout)
+                                      const bool& aClientSetPingTimeout,
+                                      const WebSocketLoadInfoArgs& aLoadInfoArgs)
 {
   LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this));
 
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
-
+  nsCOMPtr<nsIPrincipal> requestingPrincipal, triggeringPrincipal;
+  nsCOMPtr<nsILoadInfo> loadInfo;
 
   bool appOffline = false;
   uint32_t appId = GetAppId();
   if (appId != NECKO_UNKNOWN_APP_ID &&
       appId != NECKO_NO_APP_ID) {
     gIOService->IsAppOffline(appId, &appOffline);
     if (appOffline) {
       goto fail;
@@ -89,16 +92,38 @@ WebSocketChannelParent::RecvAsyncOpen(co
       do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
   } else {
     mChannel =
       do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv);
   }
   if (NS_FAILED(rv))
     goto fail;
 
+  requestingPrincipal =
+    mozilla::ipc::PrincipalInfoToPrincipal(aLoadInfoArgs.requestingPrincipalInfo(), &rv);
+  if (NS_FAILED(rv)) {
+    goto fail;
+  }
+
+  triggeringPrincipal =
+    mozilla::ipc::PrincipalInfoToPrincipal(aLoadInfoArgs.triggeringPrincipalInfo(), &rv);
+  if (NS_FAILED(rv)) {
+    goto fail;
+  }
+
+  loadInfo = new LoadInfo(requestingPrincipal,
+                          triggeringPrincipal,
+                          aLoadInfoArgs.securityFlags(),
+                          aLoadInfoArgs.contentPolicyType(),
+                          aLoadInfoArgs.innerWindowID());
+  rv = mChannel->SetLoadInfo(loadInfo);
+  if (NS_FAILED(rv)) {
+    goto fail;
+  }
+
   rv = mChannel->SetNotificationCallbacks(this);
   if (NS_FAILED(rv))
     goto fail;
 
   rv = mChannel->SetProtocol(aProtocol);
   if (NS_FAILED(rv))
     goto fail;
 
--- a/netwerk/protocol/websocket/WebSocketChannelParent.h
+++ b/netwerk/protocol/websocket/WebSocketChannelParent.h
@@ -40,17 +40,18 @@ class WebSocketChannelParent : public PW
  private:
   bool RecvAsyncOpen(const URIParams& aURI,
                      const nsCString& aOrigin,
                      const nsCString& aProtocol,
                      const bool& aSecure,
                      const uint32_t& aPingInterval,
                      const bool& aClientSetPingInterval,
                      const uint32_t& aPingTimeout,
-                     const bool& aClientSetPingTimeout) MOZ_OVERRIDE;
+                     const bool& aClientSetPingTimeout,
+                     const WebSocketLoadInfoArgs& aLoadInfoArgs) MOZ_OVERRIDE;
   bool RecvClose(const uint16_t & code, const nsCString & reason) MOZ_OVERRIDE;
   bool RecvSendMsg(const nsCString& aMsg) MOZ_OVERRIDE;
   bool RecvSendBinaryMsg(const nsCString& aMsg) MOZ_OVERRIDE;
   bool RecvSendBinaryStream(const InputStreamParams& aStream,
                             const uint32_t& aLength) MOZ_OVERRIDE;
   bool RecvDeleteSelf() MOZ_OVERRIDE;
 
   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
--- a/netwerk/protocol/websocket/nsIWebSocketChannel.idl
+++ b/netwerk/protocol/websocket/nsIWebSocketChannel.idl
@@ -5,27 +5,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 interface nsIURI;
 interface nsIInterfaceRequestor;
 interface nsILoadGroup;
 interface nsIWebSocketListener;
 interface nsIInputStream;
 interface nsILoadInfo;
+interface nsIDOMNode;
+interface nsIPrincipal;
 
 #include "nsISupports.idl"
 
 /**
  * Low-level websocket API: handles network protocol.  
  *
  * This is primarly intended for use by the higher-level nsIWebSocket.idl.
  * We are also making it scriptable for now, but this may change once we have
  * WebSockets for Workers.
  */
-[scriptable, uuid(3fb248c2-c0fc-4516-9c58-505a92ad8c64)]
+[scriptable, uuid(21217c03-2ff7-4f9c-9d10-6d3d94a7d843)]
 interface nsIWebSocketChannel : nsISupports
 {
     /**
      * The original URI used to construct the protocol connection. This is used
      * in the case of a redirect or URI "resolution" (e.g. resolving a
      * resource: URI to a file: URI) so that the original pre-redirect
      * URI can still be obtained.  This is never null.
      */
@@ -63,16 +65,73 @@ interface nsIWebSocketChannel : nsISuppo
     attribute ACString protocol;
 
     /**
      * Sec-Websocket-Extensions response header value
      */
     readonly attribute ACString extensions;
 
     /**
+     * Init the WebSocketChannel with LoadInfo arguments.
+     * @param aLoadingNode
+     *        The loadingDocument of the channel.
+     *        The element or document where the result of this request will be
+     *        used. This is the document/element that will get access to the
+     *        result of this request. For example for an image load, it's the
+     *        document in which the image will be loaded. And for a CSS
+     *        stylesheet it's the document whose rendering will be affected by
+     *        the stylesheet.
+     *        For loads that are not related to any document, such as loads coming
+     *        from addons or internal browser features, use null here.
+     * @param aLoadingPrincipal
+     *        The loadingPrincipal of the channel.
+     *        The principal of the document where the result of this request will
+     *        be used.
+     *        This defaults to the principal of aLoadingNode, so when aLoadingNode
+     *        is passed then aLoadingPrincipal can be left as null. However, for
+     *        loads where aLoadingNode is null this argument must be passed.
+     *        For example for loads from a WebWorker, pass the principal
+     *        of that worker. For loads from an addon or from internal browser
+     *        features, pass the system principal.
+     *        If aLoadingNode is null and the URI being loaded isn't coming from
+     *        a webpage, the principal should almost always be the systemPrincipal.
+     *        One exception to this is for loads from WebWorkers since they don't
+     *        have any nodes to be passed as aLoadingNode.
+     *        Please note, aLoadingPrincipal is *not* the principal of the
+     *        resource being loaded. But rather the principal of the context
+     *        where the resource will be used.
+     * @param aTriggeringPrincipal
+     *        The triggeringPrincipal of the load.
+     *        The triggeringPrincipal is the principal of the resource that caused
+     *        this particular URL to be loaded.
+     *        For WebSockets, the loadingPrincipal and the triggeringPrincipal
+     *        are *always* identical.
+     * @param aSecurityFlags
+     *        The securityFlags of the channel.
+     *        Any of the securityflags defined in nsILoadInfo.idl
+     * @param aContentPolicyType
+     *        The contentPolicyType of the channel.
+     *        Any of the content types defined in nsIContentPolicy.idl
+     * @return reference to the new nsIChannel object
+     *
+     *
+     * Keep in mind that URIs coming from a webpage should *never* use the
+     * systemPrincipal as the loadingPrincipal.
+     *
+     * Please note, if you provide both a loadingNode and a loadingPrincipal,
+     * then loadingPrincipal must be equal to loadingNode->NodePrincipal().
+     * But less error prone is to just supply a loadingNode.
+     */
+     void initLoadInfo(in nsIDOMNode aLoadingNode,
+                       in nsIPrincipal aLoadingPrincipal,
+                       in nsIPrincipal aTriggeringPrincipal,
+                       in unsigned long aSecurityFlags,
+                       in unsigned long aContentPolicyType);
+
+    /**
      * Asynchronously open the websocket connection.  Received messages are fed
      * to the socket listener as they arrive.  The socket listener's methods
      * are called on the thread that calls asyncOpen and are not called until
      * after asyncOpen returns.  If asyncOpen returns successfully, the
      * protocol implementation promises to call at least onStop on the listener.
      *
      * NOTE: Implementations should throw NS_ERROR_ALREADY_OPENED if the
      * websocket connection is reopened.
--- a/netwerk/test/unit/test_dns_proxy_bypass.js
+++ b/netwerk/test/unit/test_dns_proxy_bypass.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+Cu.import("resource://gre/modules/Services.jsm");
+
 var ioService = Cc["@mozilla.org/network/io-service;1"].
   getService(Ci.nsIIOService);
 
 var prefs = Cc["@mozilla.org/preferences-service;1"].
   getService(Ci.nsIPrefBranch);
 
 var url = "ws://dnsleak.example.com";
 
@@ -56,13 +58,20 @@ function run_test() {
   dnsRequestObserver.register();
   prefs.setBoolPref("network.dns.notifyResolution", true);
   prefs.setCharPref("network.proxy.socks", "127.0.0.1");
   prefs.setIntPref("network.proxy.socks_port", 9000);
   prefs.setIntPref("network.proxy.type", 1);
   prefs.setBoolPref("network.proxy.socks_remote_dns", true);
   var chan = Cc["@mozilla.org/network/protocol;1?name=ws"].
     createInstance(Components.interfaces.nsIWebSocketChannel);
+
+  chan.initLoadInfo(null, // aLoadingNode
+                    Services.scriptSecurityManager.getSystemPrincipal(),
+                    null, // aTriggeringPrincipal
+                    Ci.nsILoadInfo.SEC_NORMAL,
+                    Ci.nsIContentPolicy.TYPE_WEBSOCKET);
+
   var uri = ioService.newURI(url, null, null);
   chan.asyncOpen(uri, url, listener, null);
   do_test_pending();
 }
 
--- a/netwerk/test/unit/test_websocket_offline.js
+++ b/netwerk/test/unit/test_websocket_offline.js
@@ -30,16 +30,22 @@ var listener = {
 
 function run_test() {
   offlineStatus = Services.io.offline;
   Services.io.offline = true;
 
   try {
     chan = Cc["@mozilla.org/network/protocol;1?name=ws"].
       createInstance(Components.interfaces.nsIWebSocketChannel);
+    chan.initLoadInfo(null, // aLoadingNode
+                      Services.scriptSecurityManager.getSystemPrincipal(),
+                      null, // aTriggeringPrincipal
+                      Ci.nsILoadInfo.SEC_NORMAL,
+                      Ci.nsIContentPolicy.TYPE_WEBSOCKET);
+
     var uri = Services.io.newURI(url, null, null);
     chan.asyncOpen(uri, url, listener, null);
     do_test_pending();
   } catch (x) {
     dump("throwing " + x);
     do_throw(x);
   }
 }