Bug 786419 - Part 2 - Modify calls to NS_IsOffline to check for NS_IsAppOffline as well r=jduell,sicking
authorValentin Gosu <valentin.gosu@gmail.com>
Sat, 23 Aug 2014 06:06:56 +0300
changeset 209169 9474c394d41be2504d3748491d3ab4a7c51b1cf7
parent 209168 7bcb80591690a0b70b8ee1854a7924cddc688003
child 209170 e99c308964f8442e99618ab60be41426081382bc
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjduell, sicking
bugs786419
milestone35.0a1
Bug 786419 - Part 2 - Modify calls to NS_IsOffline to check for NS_IsAppOffline as well r=jduell,sicking
dom/base/Navigator.cpp
dom/base/nsGlobalWindow.cpp
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.cpp
netwerk/base/public/nsNetUtil.h
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -579,16 +579,20 @@ Navigator::CookieEnabled()
   }
 
   return cookieEnabled;
 }
 
 bool
 Navigator::OnLine()
 {
+  if (mWindow && mWindow->GetDoc()) {
+    return !NS_IsAppOffline(mWindow->GetDoc()->NodePrincipal());
+  }
+
   return !NS_IsOffline();
 }
 
 NS_IMETHODIMP
 Navigator::GetBuildID(nsAString& aBuildID)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     const nsAdoptingString& override =
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10738,17 +10738,17 @@ nsGlobalWindow::GetInterface(JSContext* 
 }
 
 void
 nsGlobalWindow::FireOfflineStatusEvent()
 {
   if (!IsCurrentInnerWindow())
     return;
   nsAutoString name;
-  if (NS_IsOffline()) {
+  if (NS_IsOffline() || NS_IsAppOffline(GetPrincipal())) {
     name.AssignLiteral("offline");
   } else {
     name.AssignLiteral("online");
   }
   // The event is fired at the body element, or if there is no body element,
   // at the document.
   nsCOMPtr<EventTarget> eventTarget = mDoc.get();
   nsHTMLDocument* htmlDoc = mDoc->AsHTMLDocument();
@@ -11294,17 +11294,18 @@ nsGlobalWindow::UnregisterIdleObserver(n
 
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
                         const char16_t* aData)
 {
-  if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
+  if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) ||
+      !nsCRT::strcmp(aTopic, NS_IOSERVICE_APP_OFFLINE_STATUS_TOPIC)) {
     if (IsFrozen()) {
       // if an even number of notifications arrive while we're frozen,
       // we don't need to fire.
       mFireOfflineStatusChangeEventOnThaw = !mFireOfflineStatusChangeEventOnThaw;
     } else {
       FireOfflineStatusEvent();
     }
     return NS_OK;
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2595,16 +2595,38 @@ RuntimeService::Observe(nsISupports* aSu
     GarbageCollectAllWorkers(/* shrinking = */ true);
     CycleCollectAllWorkers();
     return NS_OK;
   }
   if (!strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
     SendOfflineStatusChangeEventToAllWorkers(NS_IsOffline());
     return NS_OK;
   }
+  if (!strcmp(aTopic, NS_IOSERVICE_APP_OFFLINE_STATUS_TOPIC)) {
+    nsCOMPtr<nsIAppOfflineInfo> info(do_QueryInterface(aSubject));
+    if (!info) {
+      return NS_OK;
+    }
+    nsIPrincipal * principal = GetPrincipalForAsmJSCacheOp();
+    if (!principal) {
+      return NS_OK;
+    }
+
+    uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
+    principal->GetAppId(&appId);
+
+    uint32_t notificationAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
+    info->GetAppId(&notificationAppId);
+
+    if (appId != notificationAppId) {
+      return NS_OK;
+    }
+
+    SendOfflineStatusChangeEventToAllWorkers(NS_IsAppOffline(appId));
+  }
 
   NS_NOTREACHED("Unknown observer topic!");
   return NS_OK;
 }
 
 /* static */ void
 RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
 {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3575,17 +3575,17 @@ WorkerPrivate::WorkerPrivate(JSContext* 
   if (aParent) {
     aParent->AssertIsOnWorkerThread();
     aParent->GetAllPreferences(mPreferences);
     mOnLine = aParent->OnLine();
   }
   else {
     AssertIsOnMainThread();
     RuntimeService::GetDefaultPreferences(mPreferences);
-    mOnLine = !NS_IsOffline();
+    mOnLine = !NS_IsOffline() && !NS_IsAppOffline(aLoadInfo.mPrincipal);
   }
 }
 
 WorkerPrivate::~WorkerPrivate()
 {
 }
 
 // static
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -70,16 +70,17 @@
 #include "nsIIDNService.h"
 #include "nsIChannelEventSink.h"
 #include "nsIChannelPolicy.h"
 #include "nsISocketProviderService.h"
 #include "nsISocketProvider.h"
 #include "nsIRedirectChannelRegistrar.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsILoadContext.h"
+#include "nsIScriptSecurityManager.h"
 #include "mozilla/Services.h"
 #include "nsIPrivateBrowsingChannel.h"
 #include "mozIApplicationClearPrivateDataParams.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIContentSniffer.h"
 #include "nsCategoryCache.h"
 #include "nsStringStream.h"
 #include "nsIViewSourceChannel.h"
@@ -1895,16 +1896,40 @@ NS_IsOffline()
 {
     bool offline = true;
     nsCOMPtr<nsIIOService> ios = do_GetIOService();
     if (ios)
         ios->GetOffline(&offline);
     return offline;
 }
 
+inline bool
+NS_IsAppOffline(uint32_t appId)
+{
+    bool appOffline = false;
+    nsCOMPtr<nsIIOService> io(
+        do_GetService("@mozilla.org/network/io-service;1"));
+    if (io) {
+        io->IsAppOffline(appId, &appOffline);
+    }
+    return appOffline;
+}
+
+inline bool
+NS_IsAppOffline(nsIPrincipal * principal)
+{
+    if (!principal) {
+        return NS_IsOffline();
+    }
+    uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
+    principal->GetAppId(&appId);
+
+    return NS_IsAppOffline(appId);
+}
+
 /**
  * Helper functions for implementing nsINestedURI::innermostURI.
  *
  * Note that NS_DoImplGetInnermostURI is "private" -- call
  * NS_ImplGetInnermostURI instead.
  */
 inline nsresult
 NS_DoImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result)
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -2509,17 +2509,21 @@ nsFtpState::CheckCache()
                          getter_AddRefs(session));
     if (!session)
         return false;
     session->SetDoomEntriesIfExpired(false);
     session->SetIsPrivate(isPrivate);
 
     // Set cache access requested:
     nsCacheAccessMode accessReq;
-    if (NS_IsOffline()) {
+    uint32_t appId;
+    bool isInBrowser;
+    NS_GetAppInfo(mChannel, &appId, &isInBrowser);
+
+    if (NS_IsOffline() || NS_IsAppOffline(appId)) {
         accessReq = nsICache::ACCESS_READ; // can only read
     } else if (mChannel->HasLoadFlag(nsIRequest::LOAD_BYPASS_CACHE)) {
         accessReq = nsICache::ACCESS_WRITE; // replace cache entry
     } else {
         accessReq = nsICache::ACCESS_READ_WRITE; // normal browsing
     }
 
     // Check to see if we are not allowed to write to the cache: