Skip to content

Commit 077e903

Browse files
committed
Bug 786419 - Provide way to "set network offline" per app r=jduell
1 parent 9623afb commit 077e903

38 files changed

+1122
-24
lines changed

content/html/content/src/nsHTMLDNSPrefetch.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ nsHTMLDNSPrefetch::Shutdown()
9494
bool
9595
nsHTMLDNSPrefetch::IsAllowed (nsIDocument *aDocument)
9696
{
97+
if (NS_IsAppOffline(aDocument->NodePrincipal())) {
98+
return false;
99+
}
100+
97101
// There is no need to do prefetch on non UI scenarios such as XMLHttpRequest.
98102
return aDocument->IsDNSPrefetchAllowed() && aDocument->GetWindow();
99103
}

dom/base/Navigator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,10 @@ Navigator::CookieEnabled()
593593
bool
594594
Navigator::OnLine()
595595
{
596+
if (mWindow && mWindow->GetDoc()) {
597+
return !NS_IsAppOffline(mWindow->GetDoc()->NodePrincipal());
598+
}
599+
596600
return !NS_IsOffline();
597601
}
598602

dom/base/nsGlobalWindow.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10745,7 +10745,7 @@ nsGlobalWindow::FireOfflineStatusEvent()
1074510745
if (!IsCurrentInnerWindow())
1074610746
return;
1074710747
nsAutoString name;
10748-
if (NS_IsOffline()) {
10748+
if (NS_IsOffline() || NS_IsAppOffline(GetPrincipal())) {
1074910749
name.AssignLiteral("offline");
1075010750
} else {
1075110751
name.AssignLiteral("online");
@@ -11301,7 +11301,8 @@ nsresult
1130111301
nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
1130211302
const char16_t* aData)
1130311303
{
11304-
if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
11304+
if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) ||
11305+
!nsCRT::strcmp(aTopic, NS_IOSERVICE_APP_OFFLINE_STATUS_TOPIC)) {
1130511306
if (IsFrozen()) {
1130611307
// if an even number of notifications arrive while we're frozen,
1130711308
// we don't need to fire.

dom/ipc/PBrowser.ipdl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,11 @@ child:
521521
*/
522522
UIResolutionChanged();
523523

524+
/**
525+
* Tell the child of an app's offline status
526+
*/
527+
AppOfflineStatus(uint32_t id, bool offline);
528+
524529
/*
525530
* FIXME: write protocol!
526531

dom/ipc/TabChild.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
#include "UnitTransforms.h"
8181
#include "ClientLayerManager.h"
8282
#include "LayersLogging.h"
83+
#include "nsIOService.h"
8384

8485
#include "nsColorPickerProxy.h"
8586

@@ -2445,6 +2446,18 @@ TabChild::RecvAsyncMessage(const nsString& aMessage,
24452446
return true;
24462447
}
24472448

2449+
bool
2450+
TabChild::RecvAppOfflineStatus(const uint32_t& aId, const bool& aOffline)
2451+
{
2452+
// Instantiate the service to make sure gIOService is initialized
2453+
nsCOMPtr<nsIIOService> ioService = mozilla::services::GetIOService();
2454+
if (gIOService && ioService) {
2455+
gIOService->SetAppOfflineInternal(aId, aOffline ?
2456+
nsIAppOfflineInfo::OFFLINE : nsIAppOfflineInfo::ONLINE);
2457+
}
2458+
return true;
2459+
}
2460+
24482461
class UnloadScriptEvent : public nsRunnable
24492462
{
24502463
public:

dom/ipc/TabChild.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ class TabChild MOZ_FINAL : public TabChildBase,
368368
const InfallibleTArray<CpowEntry>& aCpows,
369369
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
370370

371+
virtual bool RecvAppOfflineStatus(const uint32_t& aId, const bool& aOffline) MOZ_OVERRIDE;
372+
371373
virtual PDocumentRendererChild*
372374
AllocPDocumentRendererChild(const nsRect& documentRect, const gfx::Matrix& transform,
373375
const nsString& bgcolor,

dom/ipc/TabParent.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ TabParent::TabParent(nsIContentParent* aManager, const TabContext& aContext, uin
237237
, mMarkedDestroying(false)
238238
, mIsDestroyed(false)
239239
, mAppPackageFileDescriptorSent(false)
240+
, mSendOfflineStatus(true)
240241
, mChromeFlags(aChromeFlags)
241242
{
242243
MOZ_ASSERT(aManager);
@@ -502,6 +503,14 @@ TabParent::LoadURL(nsIURI* aURI)
502503
return;
503504
}
504505

506+
uint32_t appId = OwnOrContainingAppId();
507+
if (mSendOfflineStatus && NS_IsAppOffline(appId)) {
508+
// If the app is offline in the parent process
509+
// pass that state to the child process as well
510+
unused << SendAppOfflineStatus(appId, true);
511+
}
512+
mSendOfflineStatus = false;
513+
505514
unused << SendLoadURL(spec);
506515

507516
// If this app is a packaged app then we can speed startup by sending over

dom/ipc/TabParent.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ class TabParent : public PBrowserParent
416416
// Whether we have already sent a FileDescriptor for the app package.
417417
bool mAppPackageFileDescriptorSent;
418418

419+
// Whether we need to send the offline status to the TabChild
420+
// This is true, until the first call of LoadURL
421+
bool mSendOfflineStatus;
422+
419423
uint32_t mChromeFlags;
420424

421425
nsCOMPtr<nsILoadContext> mLoadContext;

dom/media/PeerConnection.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ GlobalPCList.prototype = {
150150
} else if (data == "online") {
151151
this._networkdown = false;
152152
}
153+
} else if (topic == "network:app-offline-status-changed") {
154+
// App just went offline. The subject also contains the appId,
155+
// but navigator.onLine checks that for us
156+
if (!this._networkdown && !this._win.navigator.onLine) {
157+
for (let winId in this._list) {
158+
cleanupWinId(this._list, winId);
159+
}
160+
}
161+
this._networkdown = !this._win.navigator.onLine;
153162
} else if (topic == "gmp-plugin-crash") {
154163
// a plugin crashed; if it's associated with any of our PCs, fire an
155164
// event to the DOM window
@@ -331,7 +340,7 @@ RTCPeerConnection.prototype = {
331340
}
332341
this._mustValidateRTCConfiguration(rtcConfig,
333342
"RTCPeerConnection constructor passed invalid RTCConfiguration");
334-
if (_globalPCList._networkdown) {
343+
if (_globalPCList._networkdown || !this._win.navigator.onLine) {
335344
throw new this._win.DOMError("",
336345
"Can't create RTCPeerConnections when the network is down");
337346
}

dom/network/src/TCPSocketParent.cpp

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,55 @@ NS_INTERFACE_MAP_END
5050
TCPSocketParentBase::TCPSocketParentBase()
5151
: mIPCOpen(false)
5252
{
53+
mObserver = new mozilla::net::OfflineObserver(this);
5354
}
5455

5556
TCPSocketParentBase::~TCPSocketParentBase()
5657
{
58+
if (mObserver) {
59+
mObserver->RemoveObserver();
60+
}
61+
}
62+
63+
uint32_t
64+
TCPSocketParent::GetAppId()
65+
{
66+
uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
67+
const PContentParent *content = Manager()->Manager();
68+
const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
69+
if (browsers.Length() > 0) {
70+
TabParent *tab = static_cast<TabParent*>(browsers[0]);
71+
appId = tab->OwnAppId();
72+
}
73+
return appId;
74+
};
75+
76+
nsresult
77+
TCPSocketParent::OfflineNotification(nsISupports *aSubject)
78+
{
79+
nsCOMPtr<nsIAppOfflineInfo> info(do_QueryInterface(aSubject));
80+
if (!info) {
81+
return NS_OK;
82+
}
83+
84+
uint32_t targetAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
85+
info->GetAppId(&targetAppId);
86+
87+
// Obtain App ID
88+
uint32_t appId = GetAppId();
89+
if (appId != targetAppId) {
90+
return NS_OK;
91+
}
92+
93+
// If the app is offline, close the socket
94+
if (mSocket && NS_IsAppOffline(appId)) {
95+
mSocket->Close();
96+
mSocket = nullptr;
97+
mIntermediaryObj = nullptr;
98+
mIntermediary = nullptr;
99+
}
100+
101+
return NS_OK;
57102
}
58103

59104
void
@@ -95,12 +140,12 @@ TCPSocketParent::RecvOpen(const nsString& aHost, const uint16_t& aPort, const bo
95140
}
96141

97142
// Obtain App ID
98-
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
99-
const PContentParent *content = Manager()->Manager();
100-
const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
101-
if (browsers.Length() > 0) {
102-
TabParent *tab = static_cast<TabParent*>(browsers[0]);
103-
appId = tab->OwnAppId();
143+
uint32_t appId = GetAppId();
144+
145+
if (NS_IsAppOffline(appId)) {
146+
NS_ERROR("Can't open socket because app is offline");
147+
FireInteralError(this, __LINE__);
148+
return true;
104149
}
105150

106151
nsresult rv;

dom/network/src/TCPSocketParent.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "nsCOMPtr.h"
1212
#include "nsIDOMTCPSocket.h"
1313
#include "js/TypeDecls.h"
14+
#include "mozilla/net/OfflineObserver.h"
1415

1516
#define TCPSOCKETPARENT_CID \
1617
{ 0x4e7246c6, 0xa8b3, 0x426d, { 0x9c, 0x17, 0x76, 0xda, 0xb1, 0xe1, 0xe1, 0x4a } }
@@ -21,6 +22,7 @@ namespace dom {
2122
class PBrowserParent;
2223

2324
class TCPSocketParentBase : public nsITCPSocketParent
25+
, public mozilla::net::DisconnectableParent
2426
{
2527
public:
2628
NS_DECL_CYCLE_COLLECTION_CLASS(TCPSocketParentBase)
@@ -35,6 +37,7 @@ class TCPSocketParentBase : public nsITCPSocketParent
3537

3638
nsCOMPtr<nsITCPSocketIntermediary> mIntermediary;
3739
nsCOMPtr<nsIDOMTCPSocket> mSocket;
40+
nsRefPtr<mozilla::net::OfflineObserver> mObserver;
3841
bool mIPCOpen;
3942
};
4043

@@ -58,6 +61,8 @@ class TCPSocketParent : public mozilla::net::PTCPSocketParent
5861
const uint32_t& aTrackingNumber) MOZ_OVERRIDE;
5962
virtual bool RecvRequestDelete() MOZ_OVERRIDE;
6063

64+
virtual nsresult OfflineNotification(nsISupports *) MOZ_OVERRIDE;
65+
virtual uint32_t GetAppId() MOZ_OVERRIDE;
6166
private:
6267
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
6368

dom/network/src/UDPSocketParent.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include "nsINetAddr.h"
1212
#include "mozilla/unused.h"
1313
#include "mozilla/net/DNS.h"
14+
#include "nsNetUtil.h"
15+
#include "mozilla/dom/ContentParent.h"
16+
#include "mozilla/dom/TabParent.h"
17+
#include "mozilla/net/PNeckoParent.h"
1418

1519
namespace mozilla {
1620
namespace dom {
@@ -58,10 +62,60 @@ ConvertNetAddrToString(mozilla::net::NetAddr &netAddr, nsACString *address, uint
5862

5963
NS_IMPL_ISUPPORTS(UDPSocketParent, nsIUDPSocketListener)
6064

65+
UDPSocketParent::UDPSocketParent(nsIUDPSocketFilter *filter)
66+
: mIPCOpen(true)
67+
, mFilter(filter)
68+
{
69+
mObserver = new mozilla::net::OfflineObserver(this);
70+
}
71+
6172
UDPSocketParent::~UDPSocketParent()
6273
{
74+
if (mObserver) {
75+
mObserver->RemoveObserver();
76+
}
6377
}
6478

79+
uint32_t
80+
UDPSocketParent::GetAppId()
81+
{
82+
uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
83+
const PContentParent *content = Manager()->Manager();
84+
const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
85+
if (browsers.Length() > 0) {
86+
TabParent *tab = static_cast<TabParent*>(browsers[0]);
87+
appId = tab->OwnAppId();
88+
}
89+
return appId;
90+
};
91+
92+
nsresult
93+
UDPSocketParent::OfflineNotification(nsISupports *aSubject)
94+
{
95+
nsCOMPtr<nsIAppOfflineInfo> info(do_QueryInterface(aSubject));
96+
if (!info) {
97+
return NS_OK;
98+
}
99+
100+
uint32_t targetAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
101+
info->GetAppId(&targetAppId);
102+
103+
// Obtain App ID
104+
uint32_t appId = GetAppId();
105+
106+
if (appId != targetAppId) {
107+
return NS_OK;
108+
}
109+
110+
// If the app is offline, close the socket
111+
if (mSocket && NS_IsAppOffline(appId)) {
112+
mSocket->Close();
113+
}
114+
115+
return NS_OK;
116+
}
117+
118+
65119
// PUDPSocketParent methods
66120

67121
bool

dom/network/src/UDPSocketParent.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111
#include "nsCOMPtr.h"
1212
#include "nsIUDPSocket.h"
1313
#include "nsIUDPSocketFilter.h"
14+
#include "mozilla/net/OfflineObserver.h"
1415

1516
namespace mozilla {
1617
namespace dom {
1718

1819
class UDPSocketParent : public mozilla::net::PUDPSocketParent
1920
, public nsIUDPSocketListener
21+
, public mozilla::net::DisconnectableParent
2022
{
2123
public:
2224
NS_DECL_THREADSAFE_ISUPPORTS
2325
NS_DECL_NSIUDPSOCKETLISTENER
2426

25-
explicit UDPSocketParent(nsIUDPSocketFilter* filter) :
26-
mIPCOpen(true),
27-
mFilter(filter) {}
27+
explicit UDPSocketParent(nsIUDPSocketFilter* filter);
2828

2929
bool Init(const nsCString& aHost, const uint16_t aPort);
3030

@@ -36,6 +36,8 @@ class UDPSocketParent : public mozilla::net::PUDPSocketParent
3636
const mozilla::net::NetAddr& addr);
3737
virtual bool RecvRequestDelete() MOZ_OVERRIDE;
3838

39+
virtual nsresult OfflineNotification(nsISupports *) MOZ_OVERRIDE;
40+
virtual uint32_t GetAppId() MOZ_OVERRIDE;
3941
private:
4042
virtual ~UDPSocketParent();
4143

@@ -44,6 +46,7 @@ class UDPSocketParent : public mozilla::net::PUDPSocketParent
4446
bool mIPCOpen;
4547
nsCOMPtr<nsIUDPSocket> mSocket;
4648
nsCOMPtr<nsIUDPSocketFilter> mFilter;
49+
nsRefPtr<mozilla::net::OfflineObserver> mObserver;
4750
};
4851

4952
} // namespace dom

dom/workers/RuntimeService.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,6 +2476,28 @@ RuntimeService::Observe(nsISupports* aSubject, const char* aTopic,
24762476
SendOfflineStatusChangeEventToAllWorkers(NS_IsOffline());
24772477
return NS_OK;
24782478
}
2479+
if (!strcmp(aTopic, NS_IOSERVICE_APP_OFFLINE_STATUS_TOPIC)) {
2480+
nsCOMPtr<nsIAppOfflineInfo> info(do_QueryInterface(aSubject));
2481+
if (!info) {
2482+
return NS_OK;
2483+
}
2484+
nsIPrincipal * principal = GetPrincipalForAsmJSCacheOp();
2485+
if (!principal) {
2486+
return NS_OK;
2487+
}
2488+
2489+
uint32_t appId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
2490+
principal->GetAppId(&appId);
2491+
2492+
uint32_t notificationAppId = nsIScriptSecurityManager::UNKNOWN_APP_ID;
2493+
info->GetAppId(&notificationAppId);
2494+
2495+
if (appId != notificationAppId) {
2496+
return NS_OK;
2497+
}
2498+
2499+
SendOfflineStatusChangeEventToAllWorkers(NS_IsAppOffline(appId));
2500+
}
24792501

24802502
NS_NOTREACHED("Unknown observer topic!");
24812503
return NS_OK;

0 commit comments

Comments
 (0)