Bug 1312954 - Part 5: Have the network predictor use OriginAttributes to properly partition connections it creates like non-predictive connections. r?nwgh draft
authorTim Huang <tihuang@mozilla.com>
Thu, 19 Jan 2017 16:03:12 +0800
changeset 465999 64f4bdb1f22ad3da332a30feea2ca41b3a0cbdd8
parent 465998 28df254d2795448d156e43135183ec8954126f8a
child 466000 f6af67709bfe253fe1e6458525508005bb246559
push id42767
push userbmo:tihuang@mozilla.com
push dateWed, 25 Jan 2017 04:18:41 +0000
reviewersnwgh
bugs1312954
milestone54.0a1
Bug 1312954 - Part 5: Have the network predictor use OriginAttributes to properly partition connections it creates like non-predictive connections. r?nwgh
netwerk/base/Predictor.cpp
netwerk/base/Predictor.h
netwerk/base/nsINetworkPredictor.idl
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
--- a/netwerk/base/Predictor.cpp
+++ b/netwerk/base/Predictor.cpp
@@ -583,27 +583,20 @@ Predictor::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   mLastStartupTime = mStartupTime = NOW_IN_SECONDS();
 
   if (!mDNSListener) {
     mDNSListener = new DNSListener();
   }
 
-  nsCOMPtr<nsICacheStorageService> cacheStorageService =
+  mCacheStorageService =
     do_GetService("@mozilla.org/netwerk/cache-storage-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  RefPtr<LoadContextInfo> lci =
-    new LoadContextInfo(false, OriginAttributes());
-
-  rv = cacheStorageService->DiskCacheStorage(lci, false,
-                                             getter_AddRefs(mCacheDiskStorage));
-  NS_ENSURE_SUCCESS(rv, rv);
-
   mIOService = do_GetService("@mozilla.org/network/io-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = NS_NewURI(getter_AddRefs(mStartupURI),
                  "predictor://startup", nullptr, mIOService);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mSpeculativeService = do_QueryInterface(mIOService, &rv);
@@ -768,67 +761,82 @@ Predictor::Create(nsISupports *aOuter, c
   // We treat init failure the same as the service being disabled, since this
   // is all an optimization anyway. No need to freak people out. That's why we
   // gladly continue on QI'ing here.
   rv = svc->QueryInterface(aIID, aResult);
 
   return rv;
 }
 
-// Called from the main thread to initiate predictive actions
 NS_IMETHODIMP
 Predictor::Predict(nsIURI *targetURI, nsIURI *sourceURI,
-                   PredictorPredictReason reason, nsILoadContext *loadContext,
-                   nsINetworkPredictorVerifier *verifier)
+                   PredictorPredictReason reason,
+                   JS::HandleValue originAttributes,
+                   nsINetworkPredictorVerifier *verifier,
+                   JSContext* aCx)
+{
+  OriginAttributes attrs;
+
+  if (!originAttributes.isObject() ||
+      !attrs.Init(aCx, originAttributes)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return PredictNative(targetURI, sourceURI, reason, attrs, verifier);
+}
+
+// Called from the main thread to initiate predictive actions
+NS_IMETHODIMP
+Predictor::PredictNative(nsIURI *targetURI, nsIURI *sourceURI,
+                         PredictorPredictReason reason,
+                         const OriginAttributes& originAttributes,
+                         nsINetworkPredictorVerifier *verifier)
 {
   MOZ_ASSERT(NS_IsMainThread(),
              "Predictor interface methods must be called on the main thread");
 
   PREDICTOR_LOG(("Predictor::Predict"));
 
   if (IsNeckoChild()) {
     MOZ_DIAGNOSTIC_ASSERT(gNeckoChild);
 
     PREDICTOR_LOG(("    called on child process"));
 
     ipc::OptionalURIParams serTargetURI, serSourceURI;
     SerializeURI(targetURI, serTargetURI);
     SerializeURI(sourceURI, serSourceURI);
 
-    IPC::SerializedLoadContext serLoadContext;
-    serLoadContext.Init(loadContext);
-
     // If two different threads are predicting concurently, this will be
     // overwritten. Thankfully, we only use this in tests, which will
     // overwrite mVerifier perhaps multiple times for each individual test;
     // however, within each test, the multiple predict calls should have the
     // same verifier.
     if (verifier) {
       PREDICTOR_LOG(("    was given a verifier"));
       mChildVerifier = verifier;
     }
     PREDICTOR_LOG(("    forwarding to parent process"));
     gNeckoChild->SendPredPredict(serTargetURI, serSourceURI,
-                                 reason, serLoadContext, verifier);
+                                 reason, originAttributes, verifier);
     return NS_OK;
   }
 
   PREDICTOR_LOG(("    called on parent process"));
 
   if (!mInitialized) {
     PREDICTOR_LOG(("    not initialized"));
     return NS_OK;
   }
 
   if (!mEnabled) {
     PREDICTOR_LOG(("    not enabled"));
     return NS_OK;
   }
 
-  if (loadContext && loadContext->UsePrivateBrowsing()) {
+  if (originAttributes.mPrivateBrowsingId > 0) {
     // Don't want to do anything in PB mode
     PREDICTOR_LOG(("    in PB mode"));
     return NS_OK;
   }
 
   if (!IsNullOrHttp(targetURI) || !IsNullOrHttp(sourceURI)) {
     // Nothing we can do for non-HTTP[S] schemes
     PREDICTOR_LOG(("    got non-http[s] URI"));
@@ -842,17 +850,18 @@ Predictor::Predict(nsIURI *targetURI, ns
   switch (reason) {
     case nsINetworkPredictor::PREDICT_LINK:
       if (!targetURI || !sourceURI) {
         PREDICTOR_LOG(("    link invalid URI state"));
         return NS_ERROR_INVALID_ARG;
       }
       // Link hover is a special case where we can predict without hitting the
       // db, so let's go ahead and fire off that prediction here.
-      PredictForLink(targetURI, sourceURI, verifier);
+      PredictForLink(targetURI, sourceURI,
+                     originAttributes, verifier);
       return NS_OK;
     case nsINetworkPredictor::PREDICT_LOAD:
       if (!targetURI || sourceURI) {
         PREDICTOR_LOG(("    load invalid URI state"));
         return NS_ERROR_INVALID_ARG;
       }
       break;
     case nsINetworkPredictor::PREDICT_STARTUP:
@@ -876,62 +885,81 @@ Predictor::Predict(nsIURI *targetURI, ns
   RefPtr<Predictor::Action> uriAction =
     new Predictor::Action(Predictor::Action::IS_FULL_URI,
                           Predictor::Action::DO_PREDICT, argReason, targetURI,
                           nullptr, verifier, this);
   nsAutoCString uriKeyStr;
   uriKey->GetAsciiSpec(uriKeyStr);
   PREDICTOR_LOG(("    Predict uri=%s reason=%d action=%p", uriKeyStr.get(),
                  reason, uriAction.get()));
+
+  nsCOMPtr<nsICacheStorage> cacheDiskStorage;
+
+  RefPtr<LoadContextInfo> lci =
+    new LoadContextInfo(false, originAttributes);
+
+  nsresult rv = mCacheStorageService->DiskCacheStorage(lci, false,
+                                                       getter_AddRefs(cacheDiskStorage));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+
   uint32_t openFlags = nsICacheStorage::OPEN_READONLY |
                        nsICacheStorage::OPEN_SECRETLY |
                        nsICacheStorage::OPEN_PRIORITY |
                        nsICacheStorage::CHECK_MULTITHREADED;
-  mCacheDiskStorage->AsyncOpenURI(uriKey, EmptyCString(), openFlags, uriAction);
+  cacheDiskStorage->AsyncOpenURI(uriKey, EmptyCString(), openFlags, uriAction);
 
   // Now we do the origin-only (and therefore predictor-only) entry
   nsCOMPtr<nsIURI> targetOrigin;
-  nsresult rv = ExtractOrigin(uriKey, getter_AddRefs(targetOrigin), mIOService);
+  rv = ExtractOrigin(uriKey, getter_AddRefs(targetOrigin), mIOService);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!originKey) {
     originKey = targetOrigin;
   }
 
   RefPtr<Predictor::Action> originAction =
     new Predictor::Action(Predictor::Action::IS_ORIGIN,
                           Predictor::Action::DO_PREDICT, argReason,
                           targetOrigin, nullptr, verifier, this);
   nsAutoCString originKeyStr;
   originKey->GetAsciiSpec(originKeyStr);
   PREDICTOR_LOG(("    Predict origin=%s reason=%d action=%p", originKeyStr.get(),
                  reason, originAction.get()));
   openFlags = nsICacheStorage::OPEN_READONLY |
               nsICacheStorage::OPEN_SECRETLY |
               nsICacheStorage::CHECK_MULTITHREADED;
-  mCacheDiskStorage->AsyncOpenURI(originKey,
-                                  NS_LITERAL_CSTRING(PREDICTOR_ORIGIN_EXTENSION),
-                                  openFlags, originAction);
+  cacheDiskStorage->AsyncOpenURI(originKey,
+                                 NS_LITERAL_CSTRING(PREDICTOR_ORIGIN_EXTENSION),
+                                 openFlags, originAction);
 
   PREDICTOR_LOG(("    predict returning"));
   return NS_OK;
 }
 
 bool
 Predictor::PredictInternal(PredictorPredictReason reason, nsICacheEntry *entry,
                            bool isNew, bool fullUri, nsIURI *targetURI,
                            nsINetworkPredictorVerifier *verifier,
                            uint8_t stackCount)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   PREDICTOR_LOG(("Predictor::PredictInternal"));
   bool rv = false;
 
+  nsCOMPtr<nsILoadContextInfo> lci;
+  entry->GetLoadContextInfo(getter_AddRefs(lci));
+
+  if (!lci) {
+    return rv;
+  }
+
   if (reason == nsINetworkPredictor::PREDICT_LOAD) {
-    MaybeLearnForStartup(targetURI, fullUri);
+    MaybeLearnForStartup(targetURI, fullUri,
+                         *lci->OriginAttributesPtr());
   }
 
   if (isNew) {
     // nothing else we can do here
     PREDICTOR_LOG(("    new entry"));
     return rv;
   }
 
@@ -947,16 +975,17 @@ Predictor::PredictInternal(PredictorPred
       MOZ_ASSERT(false, "Got unexpected value for prediction reason");
   }
 
   return rv;
 }
 
 void
 Predictor::PredictForLink(nsIURI *targetURI, nsIURI *sourceURI,
+                          const OriginAttributes& originAttributes,
                           nsINetworkPredictorVerifier *verifier)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   PREDICTOR_LOG(("Predictor::PredictForLink"));
   if (!mSpeculativeService) {
     PREDICTOR_LOG(("    missing speculative service"));
     return;
@@ -967,17 +996,20 @@ Predictor::PredictForLink(nsIURI *target
     sourceURI->SchemeIs("https", &isSSL);
     if (isSSL) {
       // We don't want to predict from an HTTPS page, to avoid info leakage
       PREDICTOR_LOG(("    Not predicting for link hover - on an SSL page"));
       return;
     }
   }
 
-  mSpeculativeService->SpeculativeConnect2(targetURI, nullptr, nullptr);
+  nsCOMPtr<nsIPrincipal> principal =
+    BasePrincipal::CreateCodebasePrincipal(targetURI, originAttributes);
+
+  mSpeculativeService->SpeculativeConnect2(targetURI, principal, nullptr);
   if (verifier) {
     PREDICTOR_LOG(("    sending verification"));
     verifier->OnPredictPreconnect(targetURI);
   }
 }
 
 // This is the driver for prediction based on a new pageload.
 static const uint8_t MAX_PAGELOAD_DEPTH = 10;
@@ -1001,57 +1033,75 @@ Predictor::PredictForPageload(nsICacheEn
 
   int32_t globalDegradation = CalculateGlobalDegradation(lastLoad);
   PREDICTOR_LOG(("    globalDegradation = %d", globalDegradation));
 
   int32_t loadCount;
   rv = entry->GetFetchCount(&loadCount);
   NS_ENSURE_SUCCESS(rv, false);
 
+  nsCOMPtr<nsILoadContextInfo> lci;
+
+  rv = entry->GetLoadContextInfo(getter_AddRefs(lci));
+  NS_ENSURE_SUCCESS(rv, false);
+
   nsCOMPtr<nsIURI> redirectURI;
   if (WouldRedirect(entry, loadCount, lastLoad, globalDegradation,
                     getter_AddRefs(redirectURI))) {
     mPreconnects.AppendElement(redirectURI);
     Predictor::Reason reason;
     reason.mPredict = nsINetworkPredictor::PREDICT_LOAD;
     RefPtr<Predictor::Action> redirectAction =
       new Predictor::Action(Predictor::Action::IS_FULL_URI,
                             Predictor::Action::DO_PREDICT, reason, redirectURI,
                             nullptr, verifier, this, stackCount + 1);
     nsAutoCString redirectUriString;
     redirectURI->GetAsciiSpec(redirectUriString);
+
+    nsCOMPtr<nsICacheStorage> cacheDiskStorage;
+
+    rv = mCacheStorageService->DiskCacheStorage(lci, false,
+                                               getter_AddRefs(cacheDiskStorage));
+    NS_ENSURE_SUCCESS(rv, false);
+
     PREDICTOR_LOG(("    Predict redirect uri=%s action=%p", redirectUriString.get(),
                    redirectAction.get()));
     uint32_t openFlags = nsICacheStorage::OPEN_READONLY |
                          nsICacheStorage::OPEN_SECRETLY |
                          nsICacheStorage::OPEN_PRIORITY |
                          nsICacheStorage::CHECK_MULTITHREADED;
-    mCacheDiskStorage->AsyncOpenURI(redirectURI, EmptyCString(), openFlags,
+    cacheDiskStorage->AsyncOpenURI(redirectURI, EmptyCString(), openFlags,
                                     redirectAction);
-    return RunPredictions(nullptr, verifier);
+    return RunPredictions(nullptr, *lci->OriginAttributesPtr(), verifier);
   }
 
   CalculatePredictions(entry, targetURI, lastLoad, loadCount, globalDegradation, fullUri);
 
-  return RunPredictions(targetURI, verifier);
+  return RunPredictions(targetURI, *lci->OriginAttributesPtr(), verifier);
 }
 
 // This is the driver for predicting at browser startup time based on pages that
 // have previously been loaded close to startup.
 bool
 Predictor::PredictForStartup(nsICacheEntry *entry, bool fullUri,
                              nsINetworkPredictorVerifier *verifier)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   PREDICTOR_LOG(("Predictor::PredictForStartup"));
+
+  nsCOMPtr<nsILoadContextInfo> lci;
+
+  nsresult rv = entry->GetLoadContextInfo(getter_AddRefs(lci));
+  NS_ENSURE_SUCCESS(rv, false);
+
   int32_t globalDegradation = CalculateGlobalDegradation(mLastStartupTime);
   CalculatePredictions(entry, nullptr, mLastStartupTime, mStartupCount,
                        globalDegradation, fullUri);
-  return RunPredictions(nullptr, verifier);
+  return RunPredictions(nullptr, *lci->OriginAttributesPtr(), verifier);
 }
 
 // This calculates how much to degrade our confidence in our data based on
 // the last time this top-level resource was loaded. This "global degradation"
 // applies to *all* subresources we have associated with the top-level
 // resource. This will be in addition to any reduction in confidence we have
 // associated with a particular subresource.
 int32_t
@@ -1274,16 +1324,17 @@ Predictor::SetupPrediction(int32_t confi
     mPreconnects.AppendElement(uri);
   } else if (confidence >= mPreresolveMinConfidence) {
     mPreresolves.AppendElement(uri);
   }
 }
 
 nsresult
 Predictor::Prefetch(nsIURI *uri, nsIURI *referrer,
+                    const OriginAttributes& originAttributes,
                     nsINetworkPredictorVerifier *verifier)
 {
   nsAutoCString strUri, strReferrer;
   uri->GetAsciiSpec(strUri);
   referrer->GetAsciiSpec(strReferrer);
   PREDICTOR_LOG(("Predictor::Prefetch uri=%s referrer=%s verifier=%p",
                  strUri.get(), strReferrer.get(), verifier));
   nsCOMPtr<nsIChannel> channel;
@@ -1295,16 +1346,24 @@ Predictor::Prefetch(nsIURI *uri, nsIURI 
                               nullptr, /* aCallbacks */
                               nsIRequest::LOAD_BACKGROUND);
 
   if (NS_FAILED(rv)) {
     PREDICTOR_LOG(("    NS_NewChannel failed rv=0x%X", rv));
     return rv;
   }
 
+  nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
+  rv = loadInfo->SetOriginAttributes(originAttributes);
+
+  if (NS_FAILED(rv)) {
+    PREDICTOR_LOG(("    Set originAttributes into loadInfo failed rv=0x%X", rv));
+    return rv;
+  }
+
   nsCOMPtr<nsIHttpChannel> httpChannel;
   httpChannel = do_QueryInterface(channel);
   if (!httpChannel) {
     PREDICTOR_LOG(("    Could not get HTTP Channel from new channel!"));
     return NS_ERROR_UNEXPECTED;
   }
 
   httpChannel->SetReferrer(referrer);
@@ -1319,17 +1378,19 @@ Predictor::Prefetch(nsIURI *uri, nsIURI 
     PREDICTOR_LOG(("    AsyncOpen2 failed rv=0x%X", rv));
   }
 
   return rv;
 }
 
 // Runs predictions that have been set up.
 bool
-Predictor::RunPredictions(nsIURI *referrer, nsINetworkPredictorVerifier *verifier)
+Predictor::RunPredictions(nsIURI *referrer,
+                          const OriginAttributes& originAttributes,
+                          nsINetworkPredictorVerifier *verifier)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Running prediction off main thread");
 
   PREDICTOR_LOG(("Predictor::RunPredictions"));
 
   bool predicted = false;
   uint32_t len, i;
 
@@ -1342,30 +1403,33 @@ Predictor::RunPredictions(nsIURI *referr
   Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PREFETCHES> totalPrefetches;
   Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRECONNECTS> totalPreconnects;
   Telemetry::AutoCounter<Telemetry::PREDICTOR_TOTAL_PRERESOLVES> totalPreresolves;
 
   len = prefetches.Length();
   for (i = 0; i < len; ++i) {
     PREDICTOR_LOG(("    doing prefetch"));
     nsCOMPtr<nsIURI> uri = prefetches[i];
-    if (NS_SUCCEEDED(Prefetch(uri, referrer, verifier))) {
+    if (NS_SUCCEEDED(Prefetch(uri, referrer,
+                              originAttributes, verifier))) {
       ++totalPredictions;
       ++totalPrefetches;
       predicted = true;
     }
   }
 
   len = preconnects.Length();
   for (i = 0; i < len; ++i) {
     PREDICTOR_LOG(("    doing preconnect"));
     nsCOMPtr<nsIURI> uri = preconnects[i];
     ++totalPredictions;
     ++totalPreconnects;
-    mSpeculativeService->SpeculativeConnect2(uri, nullptr, this);
+    nsCOMPtr<nsIPrincipal> principal =
+      BasePrincipal::CreateCodebasePrincipal(uri, originAttributes);
+    mSpeculativeService->SpeculativeConnect2(uri, principal, this);
     predicted = true;
     if (verifier) {
       PREDICTOR_LOG(("    sending preconnect verification"));
       verifier->OnPredictPreconnect(uri);
     }
   }
 
   len = preresolves.Length();
@@ -1400,21 +1464,37 @@ Predictor::WouldRedirect(nsICacheEntry *
                          nsIURI **redirectURI)
 {
   // TODO - not doing redirects for first go around
   MOZ_ASSERT(NS_IsMainThread());
 
   return false;
 }
 
-// Called from the main thread to update the database
 NS_IMETHODIMP
 Predictor::Learn(nsIURI *targetURI, nsIURI *sourceURI,
                  PredictorLearnReason reason,
-                 nsILoadContext *loadContext)
+                 JS::HandleValue originAttributes,
+                 JSContext* aCx)
+{
+  OriginAttributes attrs;
+
+  if (!originAttributes.isObject() ||
+      !attrs.Init(aCx, originAttributes)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return LearnNative(targetURI, sourceURI, reason, attrs);
+}
+
+// Called from the main thread to update the database
+NS_IMETHODIMP
+Predictor::LearnNative(nsIURI *targetURI, nsIURI *sourceURI,
+                       PredictorLearnReason reason,
+                       const OriginAttributes& originAttributes)
 {
   MOZ_ASSERT(NS_IsMainThread(),
              "Predictor interface methods must be called on the main thread");
 
   PREDICTOR_LOG(("Predictor::Learn"));
 
   if (IsNeckoChild()) {
     MOZ_DIAGNOSTIC_ASSERT(gNeckoChild);
@@ -1422,38 +1502,35 @@ Predictor::Learn(nsIURI *targetURI, nsIU
     PREDICTOR_LOG(("    called on child process"));
 
     ipc::URIParams serTargetURI;
     SerializeURI(targetURI, serTargetURI);
 
     ipc::OptionalURIParams serSourceURI;
     SerializeURI(sourceURI, serSourceURI);
 
-    IPC::SerializedLoadContext serLoadContext;
-    serLoadContext.Init(loadContext);
-
     PREDICTOR_LOG(("    forwarding to parent"));
     gNeckoChild->SendPredLearn(serTargetURI, serSourceURI, reason,
-                               serLoadContext);
+                               originAttributes);
     return NS_OK;
   }
 
   PREDICTOR_LOG(("    called on parent process"));
 
   if (!mInitialized) {
     PREDICTOR_LOG(("    not initialized"));
     return NS_OK;
   }
 
   if (!mEnabled) {
     PREDICTOR_LOG(("    not enabled"));
     return NS_OK;
   }
 
-  if (loadContext && loadContext->UsePrivateBrowsing()) {
+  if (originAttributes.mPrivateBrowsingId > 0) {
     // Don't want to do anything in PB mode
     PREDICTOR_LOG(("    in PB mode"));
     return NS_OK;
   }
 
   if (!IsNullOrHttp(targetURI) || !IsNullOrHttp(sourceURI)) {
     PREDICTOR_LOG(("    got non-HTTP[S] URI"));
     return NS_ERROR_INVALID_ARG;
@@ -1520,28 +1597,38 @@ Predictor::Learn(nsIURI *targetURI, nsIU
   uriKey->GetAsciiSpec(uriKeyStr);
   targetURI->GetAsciiSpec(targetUriStr);
   if (sourceURI) {
     sourceURI->GetAsciiSpec(sourceUriStr);
   }
   PREDICTOR_LOG(("    Learn uriKey=%s targetURI=%s sourceURI=%s reason=%d "
                  "action=%p", uriKeyStr.get(), targetUriStr.get(),
                  sourceUriStr.get(), reason, uriAction.get()));
+
+  nsCOMPtr<nsICacheStorage> cacheDiskStorage;
+
+  RefPtr<LoadContextInfo> lci =
+    new LoadContextInfo(false, originAttributes);
+
+  rv = mCacheStorageService->DiskCacheStorage(lci, false,
+                                              getter_AddRefs(cacheDiskStorage));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // For learning full URI things, we *always* open readonly and secretly, as we
   // rely on actual pageloads to update the entry's metadata for us.
   uint32_t uriOpenFlags = nsICacheStorage::OPEN_READONLY |
                           nsICacheStorage::OPEN_SECRETLY |
                           nsICacheStorage::CHECK_MULTITHREADED;
   if (reason == nsINetworkPredictor::LEARN_LOAD_TOPLEVEL) {
     // Learning for toplevel we want to open the full uri entry priority, since
     // it's likely this entry will be used soon anyway, and we want this to be
     // opened ASAP.
     uriOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
   }
-  mCacheDiskStorage->AsyncOpenURI(uriKey, EmptyCString(), uriOpenFlags,
+  cacheDiskStorage->AsyncOpenURI(uriKey, EmptyCString(), uriOpenFlags,
                                   uriAction);
 
   // Now we open the origin-only (and therefore predictor-only) entry
   RefPtr<Predictor::Action> originAction =
     new Predictor::Action(Predictor::Action::IS_ORIGIN,
                           Predictor::Action::DO_LEARN, argReason, targetOrigin,
                           sourceOrigin, nullptr, this);
   nsAutoCString originKeyStr, targetOriginStr, sourceOriginStr;
@@ -1560,17 +1647,17 @@ Predictor::Learn(nsIURI *targetURI, nsIU
     // entries.
     originOpenFlags = nsICacheStorage::OPEN_NORMALLY |
                       nsICacheStorage::CHECK_MULTITHREADED;
   } else {
     originOpenFlags = nsICacheStorage::OPEN_READONLY |
                       nsICacheStorage::OPEN_SECRETLY |
                       nsICacheStorage::CHECK_MULTITHREADED;
   }
-  mCacheDiskStorage->AsyncOpenURI(originKey,
+  cacheDiskStorage->AsyncOpenURI(originKey,
                                   NS_LITERAL_CSTRING(PREDICTOR_ORIGIN_EXTENSION),
                                   originOpenFlags, originAction);
 
   PREDICTOR_LOG(("Predictor::Learn returning"));
   return NS_OK;
 }
 
 void
@@ -1811,17 +1898,18 @@ Predictor::LearnForRedirect(nsICacheEntr
 
   // TODO - not doing redirects for first go around
   PREDICTOR_LOG(("Predictor::LearnForRedirect"));
 }
 
 // This will add a page to our list of startup pages if it's being loaded
 // before our startup window has expired.
 void
-Predictor::MaybeLearnForStartup(nsIURI *uri, bool fullUri)
+Predictor::MaybeLearnForStartup(nsIURI *uri, bool fullUri,
+                                const OriginAttributes& originAttributes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // TODO - not doing startup for first go around
   PREDICTOR_LOG(("Predictor::MaybeLearnForStartup"));
 }
 
 // Add information about a top-level load to our list of startup pages
@@ -1923,17 +2011,17 @@ Predictor::Reset()
 
   if (!mEnabled) {
     PREDICTOR_LOG(("    not enabled"));
     return NS_OK;
   }
 
   RefPtr<Predictor::Resetter> reset = new Predictor::Resetter(this);
   PREDICTOR_LOG(("    created a resetter"));
-  mCacheDiskStorage->AsyncVisitStorage(reset, true);
+  mCacheStorageService->AsyncVisitAllStorages(reset, true);
   PREDICTOR_LOG(("    Cache async launched, returning now"));
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(Predictor::Resetter,
                   nsICacheEntryOpenCallback,
                   nsICacheEntryMetaDataVisitor,
@@ -2019,53 +2107,79 @@ Predictor::Resetter::OnCacheStorageInfo(
 NS_IMETHODIMP
 Predictor::Resetter::OnCacheEntryInfo(nsIURI *uri, const nsACString &idEnhance,
                                       int64_t dataSize, int32_t fetchCount,
                                       uint32_t lastModifiedTime, uint32_t expirationTime,
                                       bool aPinned, nsILoadContextInfo* aInfo)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  nsresult rv;
+
   // The predictor will only ever touch entries with no idEnhance ("") or an
   // idEnhance of PREDICTOR_ORIGIN_EXTENSION, so we filter out any entries that
   // don't match that to avoid doing extra work.
   if (idEnhance.EqualsLiteral(PREDICTOR_ORIGIN_EXTENSION)) {
     // This is an entry we own, so we can just doom it entirely
-    mPredictor->mCacheDiskStorage->AsyncDoomURI(uri, idEnhance, nullptr);
+    nsCOMPtr<nsICacheStorage> cacheDiskStorage;
+
+    rv = mPredictor->mCacheStorageService
+                   ->DiskCacheStorage(aInfo, false,
+                                      getter_AddRefs(cacheDiskStorage));
+
+    NS_ENSURE_SUCCESS(rv, rv);
+    cacheDiskStorage->AsyncDoomURI(uri, idEnhance, nullptr);
   } else if (idEnhance.IsEmpty()) {
     // This is an entry we don't own, so we have to be a little more careful and
     // just get rid of our own metadata entries. Append it to an array of things
     // to operate on and then do the operations later so we don't end up calling
     // Complete() multiple times/too soon.
     ++mEntriesToVisit;
     mURIsToVisit.AppendElement(uri);
+    mInfosToVisit.AppendElement(aInfo);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Predictor::Resetter::OnCacheEntryVisitCompleted()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  nsresult rv;
+
   nsTArray<nsCOMPtr<nsIURI>> urisToVisit;
   urisToVisit.SwapElements(mURIsToVisit);
 
   MOZ_ASSERT(mEntriesToVisit == urisToVisit.Length());
+
+  nsTArray<nsCOMPtr<nsILoadContextInfo>> infosToVisit;
+  infosToVisit.SwapElements(mInfosToVisit);
+
+  MOZ_ASSERT(mEntriesToVisit == infosToVisit.Length());
+
   if (!mEntriesToVisit) {
     Complete();
     return NS_OK;
   }
 
   uint32_t entriesToVisit = urisToVisit.Length();
   for (uint32_t i = 0; i < entriesToVisit; ++i) {
     nsCString u;
+    nsCOMPtr<nsICacheStorage> cacheDiskStorage;
+
+    rv = mPredictor->mCacheStorageService
+                   ->DiskCacheStorage(infosToVisit[i], false,
+                                      getter_AddRefs(cacheDiskStorage));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+
     urisToVisit[i]->GetAsciiSpec(u);
-    mPredictor->mCacheDiskStorage->AsyncOpenURI(
+    cacheDiskStorage->AsyncOpenURI(
         urisToVisit[i], EmptyCString(),
         nsICacheStorage::OPEN_READONLY | nsICacheStorage::OPEN_SECRETLY | nsICacheStorage::CHECK_MULTITHREADED,
         this);
   }
 
   return NS_OK;
 }
 
@@ -2097,49 +2211,50 @@ EnsureGlobalPredictor(nsINetworkPredicto
   NS_ENSURE_SUCCESS(rv, rv);
 
   predictor.forget(aPredictor);
   return NS_OK;
 }
 
 nsresult
 PredictorPredict(nsIURI *targetURI, nsIURI *sourceURI,
-                 PredictorPredictReason reason, nsILoadContext *loadContext,
+                 PredictorPredictReason reason,
+                 const OriginAttributes& originAttributes,
                  nsINetworkPredictorVerifier *verifier)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!IsNullOrHttp(targetURI) || !IsNullOrHttp(sourceURI)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsINetworkPredictor> predictor;
   nsresult rv = EnsureGlobalPredictor(getter_AddRefs(predictor));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return predictor->Predict(targetURI, sourceURI, reason,
-                            loadContext, verifier);
+  return predictor->PredictNative(targetURI, sourceURI, reason,
+                                  originAttributes, verifier);
 }
 
 nsresult
 PredictorLearn(nsIURI *targetURI, nsIURI *sourceURI,
                PredictorLearnReason reason,
-               nsILoadContext *loadContext)
+               const OriginAttributes& originAttributes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!IsNullOrHttp(targetURI) || !IsNullOrHttp(sourceURI)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsINetworkPredictor> predictor;
   nsresult rv = EnsureGlobalPredictor(getter_AddRefs(predictor));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return predictor->Learn(targetURI, sourceURI, reason, loadContext);
+  return predictor->LearnNative(targetURI, sourceURI, reason, originAttributes);
 }
 
 nsresult
 PredictorLearn(nsIURI *targetURI, nsIURI *sourceURI,
                PredictorLearnReason reason,
                nsILoadGroup *loadGroup)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -2148,26 +2263,34 @@ PredictorLearn(nsIURI *targetURI, nsIURI
     return NS_OK;
   }
 
   nsCOMPtr<nsINetworkPredictor> predictor;
   nsresult rv = EnsureGlobalPredictor(getter_AddRefs(predictor));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadContext> loadContext;
+  OriginAttributes originAttributes;
 
   if (loadGroup) {
     nsCOMPtr<nsIInterfaceRequestor> callbacks;
     loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
     if (callbacks) {
       loadContext = do_GetInterface(callbacks);
+
+      if (loadContext) {
+        OriginAttributes dAttrs;
+        loadContext->GetOriginAttributes(dAttrs);
+
+        originAttributes.Inherit(dAttrs);
+      }
     }
   }
 
-  return predictor->Learn(targetURI, sourceURI, reason, loadContext);
+  return predictor->LearnNative(targetURI, sourceURI, reason, originAttributes);
 }
 
 nsresult
 PredictorLearn(nsIURI *targetURI, nsIURI *sourceURI,
                PredictorLearnReason reason,
                nsIDocument *document)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -2175,28 +2298,33 @@ PredictorLearn(nsIURI *targetURI, nsIURI
   if (!IsNullOrHttp(targetURI) || !IsNullOrHttp(sourceURI)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsINetworkPredictor> predictor;
   nsresult rv = EnsureGlobalPredictor(getter_AddRefs(predictor));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsILoadContext> loadContext;
+  OriginAttributes originAttributes;
 
   if (document) {
-    loadContext = document->GetLoadContext();
+    nsCOMPtr<nsIPrincipal> docPrincipal = document->NodePrincipal();
+
+    if (docPrincipal) {
+      originAttributes.Inherit(docPrincipal->OriginAttributesRef());
+    }
+
   }
 
-  return predictor->Learn(targetURI, sourceURI, reason, loadContext);
+  return predictor->LearnNative(targetURI, sourceURI, reason, originAttributes);
 }
 
 nsresult
 PredictorLearnRedirect(nsIURI *targetURI, nsIChannel *channel,
-                       nsILoadContext *loadContext)
+                       const OriginAttributes& originAttributes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIURI> sourceURI;
   nsresult rv = channel->GetOriginalURI(getter_AddRefs(sourceURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool sameUri;
@@ -2210,19 +2338,19 @@ PredictorLearnRedirect(nsIURI *targetURI
   if (!IsNullOrHttp(targetURI) || !IsNullOrHttp(sourceURI)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsINetworkPredictor> predictor;
   rv = EnsureGlobalPredictor(getter_AddRefs(predictor));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return predictor->Learn(targetURI, sourceURI,
-                          nsINetworkPredictor::LEARN_LOAD_REDIRECT,
-                          loadContext);
+  return predictor->LearnNative(targetURI, sourceURI,
+                                nsINetworkPredictor::LEARN_LOAD_REDIRECT,
+                                originAttributes);
 }
 
 // nsINetworkPredictorVerifier
 
 /**
  * Call through to the child's verifier (only during tests)
  */
 NS_IMETHODIMP
@@ -2413,51 +2541,66 @@ Predictor::UpdateCacheability(nsIURI *so
     return;
   }
 
   RefPtr<Predictor> self = sSelf;
   if (self) {
     nsAutoCString method;
     requestHead.Method(method);
     self->UpdateCacheabilityInternal(sourceURI, targetURI, httpStatus,
-                                     method);
+                                     method, *lci->OriginAttributesPtr());
   }
 }
 
 void
 Predictor::UpdateCacheabilityInternal(nsIURI *sourceURI, nsIURI *targetURI,
                                       uint32_t httpStatus,
-                                      const nsCString &method)
+                                      const nsCString &method,
+                                      const OriginAttributes& originAttributes)
 {
   PREDICTOR_LOG(("Predictor::UpdateCacheability httpStatus=%u", httpStatus));
 
+  nsresult rv;
+
   if (!mInitialized) {
     PREDICTOR_LOG(("    not initialized"));
     return;
   }
 
   if (!mEnabled) {
     PREDICTOR_LOG(("    not enabled"));
     return;
   }
 
   if (!mEnablePrefetch) {
     PREDICTOR_LOG(("    prefetch not enabled"));
     return;
   }
 
+  nsCOMPtr<nsICacheStorage> cacheDiskStorage;
+
+  RefPtr<LoadContextInfo> lci =
+    new LoadContextInfo(false, originAttributes);
+
+  rv = mCacheStorageService->DiskCacheStorage(lci, false,
+                                             getter_AddRefs(cacheDiskStorage));
+  if (NS_FAILED(rv)) {
+    PREDICTOR_LOG(("    cannot get disk cache storage"));
+    return;
+  }
+
   uint32_t openFlags = nsICacheStorage::OPEN_READONLY |
                        nsICacheStorage::OPEN_SECRETLY |
                        nsICacheStorage::CHECK_MULTITHREADED;
   RefPtr<Predictor::CacheabilityAction> action =
     new Predictor::CacheabilityAction(targetURI, httpStatus, method, this);
   nsAutoCString uri;
   targetURI->GetAsciiSpec(uri);
   PREDICTOR_LOG(("    uri=%s action=%p", uri.get(), action.get()));
-  mCacheDiskStorage->AsyncOpenURI(sourceURI, EmptyCString(), openFlags, action);
+  cacheDiskStorage->AsyncOpenURI(sourceURI, EmptyCString(), openFlags, action);
 }
 
 NS_IMPL_ISUPPORTS(Predictor::CacheabilityAction,
                   nsICacheEntryOpenCallback,
                   nsICacheEntryMetaDataVisitor);
 
 NS_IMETHODIMP
 Predictor::CacheabilityAction::OnCacheEntryCheck(nsICacheEntry *entry,
--- a/netwerk/base/Predictor.h
+++ b/netwerk/base/Predictor.h
@@ -7,16 +7,17 @@
 #define mozilla_net_Predictor_h
 
 #include "nsINetworkPredictor.h"
 #include "nsINetworkPredictorVerifier.h"
 
 #include "nsCOMPtr.h"
 #include "nsICacheEntry.h"
 #include "nsICacheEntryOpenCallback.h"
+#include "nsICacheStorageService.h"
 #include "nsICacheStorageVisitor.h"
 #include "nsIDNSListener.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIObserver.h"
 #include "nsISpeculativeConnect.h"
 #include "nsIStreamListener.h"
 #include "mozilla/RefPtr.h"
 #include "nsString.h"
@@ -172,16 +173,17 @@ private:
     virtual ~Resetter() { }
 
     void Complete();
 
     uint32_t mEntriesToVisit;
     nsTArray<nsCString> mKeysToDelete;
     RefPtr<Predictor> mPredictor;
     nsTArray<nsCOMPtr<nsIURI>> mURIsToVisit;
+    nsTArray<nsCOMPtr<nsILoadContextInfo>> mInfosToVisit;
   };
 
   class SpaceCleaner : public nsICacheEntryMetaDataVisitor
   {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSICACHEENTRYMETADATAVISITOR
 
@@ -249,19 +251,21 @@ private:
   bool PredictInternal(PredictorPredictReason reason, nsICacheEntry *entry,
                        bool isNew, bool fullUri, nsIURI *targetURI,
                        nsINetworkPredictorVerifier *verifier,
                        uint8_t stackCount);
 
   // Used when predicting because the user's mouse hovered over a link
   //   * targetURI - the URI target of the link
   //   * sourceURI - the URI of the page on which the link appears
+  //   * originAttributes - the originAttributes for this prediction
   //   * verifier - used for testing to verify the expected predictions happen
   void PredictForLink(nsIURI *targetURI,
                       nsIURI *sourceURI,
+                      const OriginAttributes& originAttributes,
                       nsINetworkPredictorVerifier *verifier);
 
   // Used when predicting because a page is being loaded (which may include
   // being the target of a redirect). All arguments are the same as for
   // PredictInternal. Returns true if any predictions were queued up.
   bool PredictForPageload(nsICacheEntry *entry,
                           nsIURI *targetURI,
                           uint8_t stackCount,
@@ -327,24 +331,30 @@ private:
   //   * confidence - value calculated by CalculateConfidence for this resource
   //   * flags - the flags taken from the resource
   //   * uri - the URI of the resource
   void SetupPrediction(int32_t confidence, uint32_t flags, nsIURI *uri);
 
   // Used to kick off a prefetch from RunPredictions if necessary
   //   * uri - the URI to prefetch
   //   * referrer - the URI of the referring page
+  //   * originAttributes - the originAttributes of this prefetch
   //   * verifier - used for testing to ensure the expected prefetch happens
-  nsresult Prefetch(nsIURI *uri, nsIURI *referrer, nsINetworkPredictorVerifier *verifier);
+  nsresult Prefetch(nsIURI *uri, nsIURI *referrer,
+                    const OriginAttributes& originAttributes,
+                    nsINetworkPredictorVerifier *verifier);
 
   // Used to actually perform any predictions set up via SetupPrediction.
   // Returns true if any predictions were performed.
   //   * referrer - the URI we are predicting from
+  //   * originAttributs - the originAttributes we are predicting from
   //   * verifier - used for testing to ensure the expected predictions happen
-  bool RunPredictions(nsIURI *referrer, nsINetworkPredictorVerifier *verifier);
+  bool RunPredictions(nsIURI *referrer,
+                      const OriginAttributes& originAttributes,
+                      nsINetworkPredictorVerifier *verifier);
 
   // Used to guess whether a page will redirect to another page or not. Returns
   // true if a redirection is likely.
   //   * entry - cache entry with all necessary information about this page
   //   * loadCount - number of times this page has been loaded
   //   * lastLoad - timestamp of the last time this page was loaded
   //   * globalDegradation - value calculated by CalculateGlobalDegradation for
   //                         this page
@@ -381,17 +391,19 @@ private:
   //   * targetURI - the URI of the redirect target
   void LearnForRedirect(nsICacheEntry *entry, nsIURI *targetURI);
 
   // Used to learn about pages loaded close to browser startup. This results in
   // LearnForStartup being called if we are, in fact, near browser startup
   //   * uri - the URI of a page that has been loaded (may not have been near
   //           browser startup)
   //   * fullUri - true if this is a full page uri, false if it's an origin
-  void MaybeLearnForStartup(nsIURI *uri, bool fullUri);
+  //   * originAttributes - the originAttributes for this learning.
+  void MaybeLearnForStartup(nsIURI *uri, bool fullUri,
+                            const OriginAttributes& originAttributes);
 
   // Used in conjunction with MaybeLearnForStartup to learn about pages loaded
   // close to browser startup
   //   * entry - the cache entry that stores the startup page list
   //   * targetURI - the URI of a page that was loaded near browser startup
   void LearnForStartup(nsICacheEntry *entry, nsIURI *targetURI);
 
   // Used to parse the data we store in cache metadata
@@ -404,17 +416,18 @@ private:
   bool ParseMetaDataEntry(const char *key, const char *value, nsIURI **uri,
                           uint32_t &hitCount, uint32_t &lastHit,
                           uint32_t &flags);
 
   // Used to update whether a particular URI was cacheable or not.
   // sourceURI and targetURI are the same as the arguments to Learn
   // and httpStatus is the status code we got while loading targetURI.
   void UpdateCacheabilityInternal(nsIURI *sourceURI, nsIURI *targetURI,
-                                  uint32_t httpStatus, const nsCString &method);
+                                  uint32_t httpStatus, const nsCString &method,
+                                  const OriginAttributes& originAttributes);
 
   // Make sure our prefs are in their expected range of values
   void SanitizePrefs();
 
   // Our state
   bool mInitialized;
 
   bool mEnabled;
@@ -444,17 +457,17 @@ private:
   int32_t mMaxResourcesPerEntry;
 
   bool mCleanedUp;
   nsCOMPtr<nsITimer> mCleanupTimer;
 
   nsTArray<nsCString> mKeysToOperateOn;
   nsTArray<nsCString> mValuesToOperateOn;
 
-  nsCOMPtr<nsICacheStorage> mCacheDiskStorage;
+  nsCOMPtr<nsICacheStorageService> mCacheStorageService;
 
   nsCOMPtr<nsIIOService> mIOService;
   nsCOMPtr<nsISpeculativeConnect> mSpeculativeService;
 
   nsCOMPtr<nsIURI> mStartupURI;
   uint32_t mStartupTime;
   uint32_t mLastStartupTime;
   int32_t mStartupCount;
--- a/netwerk/base/nsINetworkPredictor.idl
+++ b/netwerk/base/nsINetworkPredictor.idl
@@ -1,22 +1,23 @@
 /* vim: set ts=2 sts=2 et sw=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 "nsISupports.idl"
 
 interface nsIURI;
-interface nsILoadContext;
 interface nsINetworkPredictorVerifier;
 
 typedef unsigned long PredictorPredictReason;
 typedef unsigned long PredictorLearnReason;
 
+[ref] native OriginAttributes(const mozilla::OriginAttributes);
+
 /**
  * nsINetworkPredictor - learn about pages users visit, and allow us to take
  *                       predictive actions upon future visits.
  *                       NOTE: nsINetworkPredictor should only
  *                       be used on the main thread.
  */
 [scriptable, uuid(acc88e7c-3f39-42c7-ac31-6377c2c3d73e)]
 interface nsINetworkPredictor : nsISupports
@@ -53,28 +54,36 @@ interface nsINetworkPredictor : nsISuppo
    *   any of the PREDICT_* values above.
    *   In the case of PREDICT_LINK, targetURI should be the URI of the link
    *   that is being hovered over, and sourceURI should be the URI of the page
    *   on which the link appears.
    *   In the case of PREDICT_LOAD, targetURI should be the URI of the page that
    *   is being loaded and sourceURI should be null.
    *   In the case of PREDICT_STARTUP, both targetURI and sourceURI should be
    *   null.
-   * @param loadContext - The nsILoadContext of the page load we are predicting
-   *   about.
+   * @param originAttributes - The originAttributes of the page load we are
+   *   predicting about.
    * @param verifier - An nsINetworkPredictorVerifier used in testing to ensure
    *   we're predicting the way we expect to. Not necessary (or desired) for
    *   normal operation.
    */
+  [implicit_jscontext]
   void predict(in nsIURI targetURI,
                in nsIURI sourceURI,
                in PredictorPredictReason reason,
-               in nsILoadContext loadContext,
+               in jsval originAttributes,
                in nsINetworkPredictorVerifier verifier);
 
+  [notxpcom]
+  nsresult predictNative(in nsIURI targetURI,
+                         in nsIURI sourceURI,
+                         in PredictorPredictReason reason,
+                         in OriginAttributes originAttributes,
+                         in nsINetworkPredictorVerifier verifier);
+
 
   /*
    * Reasons we are learning something
    *
    * LEARN_LOAD_TOPLEVEL - we are learning about the toplevel resource of a
    *                       pageload (NOTE: this should ONLY be used by tests)
    *
    * LEARN_LOAD_SUBRESOURCE - we are learning a subresource from a pageload
@@ -102,23 +111,30 @@ interface nsINetworkPredictor : nsISuppo
    *   In the case of LEARN_LOAD_SUBRESOURCE, targetURI should be the URI of a
    *   subresource of a page, and sourceURI should be the top-level URI.
    *   In the case of LEARN_LOAD_REDIRECT, targetURI is the NEW URI of a
    *   top-level resource that was redirected to, and sourceURI is the
    *   ORIGINAL URI of said top-level resource.
    *   In the case of LEARN_STARTUP, targetURI should be the URI of a page
    *   that was loaded immediately after browser startup, and sourceURI should
    *   be null.
-   * @param loadContext - The nsILoadContext for the page load that we are
-   *   learning about.
+   * @param originAttributes - The originAttributes for the page load that we
+   *   are learning about.
    */
+  [implicit_jscontext]
   void learn(in nsIURI targetURI,
              in nsIURI sourceURI,
              in PredictorLearnReason reason,
-             in nsILoadContext loadContext);
+             in jsval originAttributes);
+
+  [notxpcom]
+  nsresult learnNative(in nsIURI targetURI,
+                       in nsIURI sourceURI,
+                       in PredictorLearnReason reason,
+                       in OriginAttributes originAttributes);
 
   /**
    * Clear out all our learned knowledge
    *
    * This removes everything from our database so that any predictions begun
    * after this completes will start from a blank slate.
    */
   void reset();
@@ -133,33 +149,33 @@ class nsILoadGroup;
 class nsINetworkPredictorVerifier;
 
 namespace mozilla {
 namespace net {
 
 nsresult PredictorPredict(nsIURI *targetURI,
                           nsIURI *sourceURI,
                           PredictorPredictReason reason,
-                          nsILoadContext *loadContext,
+                          const OriginAttributes& originAttributes,
                           nsINetworkPredictorVerifier *verifier);
 
 nsresult PredictorLearn(nsIURI *targetURI,
                         nsIURI *sourceURI,
                         PredictorLearnReason reason,
-                        nsILoadContext *loadContext);
+                        const OriginAttributes& originAttributes);
 
 nsresult PredictorLearn(nsIURI *targetURI,
                         nsIURI *sourceURI,
                         PredictorLearnReason reason,
                         nsILoadGroup *loadGroup);
 
 nsresult PredictorLearn(nsIURI *targetURI,
                         nsIURI *sourceURI,
                         PredictorLearnReason reason,
                         nsIDocument *document);
 
 nsresult PredictorLearnRedirect(nsIURI *targetURI,
                                 nsIChannel *channel,
-                                nsILoadContext *loadContext);
+                                const OriginAttributes& originAttributes);
 
 } // mozilla::net
 } // mozilla
 %}
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -818,72 +818,52 @@ NeckoParent::RecvOnAuthCancelled(const u
   return IPC_OK();
 }
 
 /* Predictor Messages */
 mozilla::ipc::IPCResult
 NeckoParent::RecvPredPredict(const ipc::OptionalURIParams& aTargetURI,
                              const ipc::OptionalURIParams& aSourceURI,
                              const uint32_t& aReason,
-                             const SerializedLoadContext& aLoadContext,
+                             const OriginAttributes& aOriginAttributes,
                              const bool& hasVerifier)
 {
   nsCOMPtr<nsIURI> targetURI = DeserializeURI(aTargetURI);
   nsCOMPtr<nsIURI> sourceURI = DeserializeURI(aSourceURI);
 
-  // We only actually care about the loadContext.mPrivateBrowsing, so we'll just
-  // pass dummy params for nestFrameId, and originAttributes.
-  uint64_t nestedFrameId = 0;
-  OriginAttributes attrs(NECKO_UNKNOWN_APP_ID, false);
-  nsCOMPtr<nsILoadContext> loadContext;
-  if (aLoadContext.IsNotNull()) {
-    attrs.SyncAttributesWithPrivateBrowsing(aLoadContext.mOriginAttributes.mPrivateBrowsingId > 0);
-    loadContext = new LoadContext(aLoadContext, nestedFrameId, attrs);
-  }
-
   // Get the current predictor
   nsresult rv = NS_OK;
   nsCOMPtr<nsINetworkPredictor> predictor =
     do_GetService("@mozilla.org/network/predictor;1", &rv);
   NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
 
   nsCOMPtr<nsINetworkPredictorVerifier> verifier;
   if (hasVerifier) {
     verifier = do_QueryInterface(predictor);
   }
-  predictor->Predict(targetURI, sourceURI, aReason, loadContext, verifier);
+  predictor->PredictNative(targetURI, sourceURI, aReason, aOriginAttributes, verifier);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 NeckoParent::RecvPredLearn(const ipc::URIParams& aTargetURI,
                            const ipc::OptionalURIParams& aSourceURI,
                            const uint32_t& aReason,
-                           const SerializedLoadContext& aLoadContext)
+                           const OriginAttributes& aOriginAttributes)
 {
   nsCOMPtr<nsIURI> targetURI = DeserializeURI(aTargetURI);
   nsCOMPtr<nsIURI> sourceURI = DeserializeURI(aSourceURI);
 
-  // We only actually care about the loadContext.mPrivateBrowsing, so we'll just
-  // pass dummy params for nestFrameId, and originAttributes;
-  uint64_t nestedFrameId = 0;
-  OriginAttributes attrs(NECKO_UNKNOWN_APP_ID, false);
-  nsCOMPtr<nsILoadContext> loadContext;
-  if (aLoadContext.IsNotNull()) {
-    attrs.SyncAttributesWithPrivateBrowsing(aLoadContext.mOriginAttributes.mPrivateBrowsingId > 0);
-    loadContext = new LoadContext(aLoadContext, nestedFrameId, attrs);
-  }
-
   // Get the current predictor
   nsresult rv = NS_OK;
   nsCOMPtr<nsINetworkPredictor> predictor =
     do_GetService("@mozilla.org/network/predictor;1", &rv);
   NS_ENSURE_SUCCESS(rv, IPC_FAIL_NO_REASON(this));
 
-  predictor->Learn(targetURI, sourceURI, aReason, loadContext);
+  predictor->LearnNative(targetURI, sourceURI, aReason, aOriginAttributes);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 NeckoParent::RecvPredReset()
 {
   // Get the current predictor
   nsresult rv = NS_OK;
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -204,23 +204,23 @@ protected:
                                                       const nsString& aDomain) override;
   virtual mozilla::ipc::IPCResult RecvOnAuthCancelled(const uint64_t& aCallbackId,
                                                       const bool& aUserCancel) override;
 
   /* Predictor Messages */
   virtual mozilla::ipc::IPCResult RecvPredPredict(const ipc::OptionalURIParams& aTargetURI,
                                                   const ipc::OptionalURIParams& aSourceURI,
                                                   const PredictorPredictReason& aReason,
-                                                  const IPC::SerializedLoadContext& aLoadContext,
+                                                  const OriginAttributes& aOriginAttributes,
                                                   const bool& hasVerifier) override;
 
   virtual mozilla::ipc::IPCResult RecvPredLearn(const ipc::URIParams& aTargetURI,
                                                 const ipc::OptionalURIParams& aSourceURI,
                                                 const PredictorPredictReason& aReason,
-                                                const IPC::SerializedLoadContext& aLoadContext) override;
+                                                const OriginAttributes& aOriginAttributes) override;
   virtual mozilla::ipc::IPCResult RecvPredReset() override;
 
   virtual mozilla::ipc::IPCResult RecvRemoveRequestContext(const nsCString& rcid) override;
 };
 
 } // namespace net
 } // namespace mozilla
 
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -77,20 +77,20 @@ parent:
   async PUDPSocket(Principal principal, nsCString filter);
 
   async PDNSRequest(nsCString hostName, uint32_t flags, nsCString networkInterface);
 
   async PWebSocketEventListener(uint64_t aInnerWindowID);
 
   /* Predictor Methods */
   async PredPredict(OptionalURIParams targetURI, OptionalURIParams sourceURI,
-                    uint32_t reason, SerializedLoadContext loadContext,
+                    uint32_t reason, OriginAttributes originAttributes,
                     bool hasVerifier);
   async PredLearn(URIParams targetURI, OptionalURIParams sourceURI,
-                  uint32_t reason, SerializedLoadContext loadContext);
+                  uint32_t reason, OriginAttributes originAttributes);
   async PredReset();
 
   async SpeculativeConnect(URIParams uri, Principal principal, bool anonymous);
   async HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   async CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
 
   /**
    * channelId is used to establish a connection between redirect channels in