Bug 1312954 - Part 5: Have the network predictor use OriginAttributes to properly partition connections it creates like non-predictive connections. r=nwgh
authorTim Huang <tihuang@mozilla.com>
Thu, 02 Feb 2017 22:16:00 -0500
changeset 340735 0d4dd7cb34bef13cdce945a351c2383e5b45644c
parent 340734 aa73e382ed7c92c81224a58e0ff7841a9756170a
child 340736 8f1437a1332d660c08799836cb73dbf46ccfbcd2
push id31308
push userkwierso@gmail.com
push dateSat, 04 Feb 2017 01:04:28 +0000
treeherdermozilla-central@09b28b955a47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnwgh
bugs1312954
milestone54.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 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