Attachment #8788571: Part 8: OnlineObserver for bug #1217544

View | Details | Raw Unified | Return to bug 1217544
Collapse All | Expand All

(-)a/dom/backgroundsync/OnlineStateObserver.cpp (+186 lines)
Line     Link Here 
Line 0    Link Here 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "OnlineStateObserver.h"
8
9
#include "mozilla/ipc/BackgroundParent.h"
10
#include "nsIOService.h"
11
12
namespace mozilla {
13
namespace dom {
14
15
/**
16
 * ShutdownRunnable
17
 */
18
class ShutdownRunnable final : public Runnable
19
{
20
public:
21
  explicit ShutdownRunnable(OnlineStateObserver* aObserver)
22
    : mObserver(aObserver)
23
  {}
24
25
  NS_IMETHOD
26
  Run() override
27
  {
28
    AssertIsOnMainThread();
29
30
    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
31
    if (obs) {
32
      obs->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
33
      obs->RemoveObserver(mObserver, "xpcom-shutdown");
34
    }
35
    return NS_OK;
36
  }
37
38
private:
39
  ~ShutdownRunnable() {};
40
41
  RefPtr<OnlineStateObserver> mObserver;
42
};
43
44
/**
45
 * OnlineStateChangeNotification
46
 */
47
class OnlineStateChangeNotification final : public Runnable
48
{
49
public:
50
  OnlineStateChangeNotification(OnlineStateObserver::Listener* aListener,
51
                                const OnlineStateObserver::OnlineState aState)
52
    : mListener(aListener)
53
    , mState(aState)
54
  {
55
    MOZ_ASSERT(mListener);
56
  }
57
58
  NS_IMETHOD
59
  Run() override
60
  {
61
    AssertIsOnBackgroundThread();
62
    MOZ_ASSERT(mListener);
63
64
    mListener->OnOnlineStateChanged(mState);
65
66
    return NS_OK;
67
  }
68
69
private:
70
  ~OnlineStateChangeNotification() {}
71
72
  OnlineStateObserver::Listener* mListener;
73
  OnlineStateObserver::OnlineState mState;
74
};
75
76
/**
77
 * OnlineStateObserver
78
 */
79
80
// static
81
already_AddRefed<OnlineStateObserver>
82
OnlineStateObserver::Init(Listener* aListener)
83
{
84
  AssertIsOnBackgroundThread();
85
86
  RefPtr<OnlineStateObserver> observer = new OnlineStateObserver(aListener);
87
88
  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(observer));
89
90
  return observer.forget();
91
}
92
93
OnlineStateObserver::OnlineStateObserver(Listener* aListener)
94
  : mListener(aListener)
95
  , mInitiatingThread(NS_GetCurrentThread())
96
  , mShuttingDown(false)
97
{
98
  AssertIsOnBackgroundThread();
99
  MOZ_ASSERT(mInitiatingThread);
100
  MOZ_ASSERT(mListener);
101
}
102
103
OnlineStateObserver::~OnlineStateObserver()
104
{
105
  MOZ_ASSERT(!mListener);
106
}
107
108
void
109
OnlineStateObserver::Shutdown(Listener* aListener)
110
{
111
  MOZ_ASSERT(aListener == mListener);
112
  mShuttingDown = true;
113
  mListener = nullptr;
114
115
  // We need to remove the observers so we can be destroyed.
116
  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(new ShutdownRunnable(this)));
117
}
118
119
NS_IMETHODIMP
120
OnlineStateObserver::Observe(nsISupports* aSubject, const char* aTopic,
121
                             const char16_t* aData)
122
{
123
  AssertIsOnMainThread();
124
  MOZ_ASSERT(!strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) ||
125
             !strcmp(aTopic, "xpcom-shutdown"));
126
127
  // During xpcom-shutdown we do a nsIOService:SetOffline that
128
  // triggers a notification that we should ignore cause the
129
  // listener might already be gone.
130
  if (!strcmp(aTopic, "xpcom-shutdown")) {
131
    mShuttingDown = true;
132
  }
133
134
  if (mShuttingDown) {
135
    return NS_OK;
136
  }
137
138
  // Here aTopic is NS_IOSERVICE_OFFLINE_STATUS_TOPIC
139
140
  OnlineState state = eOffline;
141
  if (nsDependentString(aData).EqualsLiteral(NS_IOSERVICE_ONLINE)) {
142
    state = eOnline;
143
  }
144
145
  mInitiatingThread->Dispatch(
146
      new OnlineStateChangeNotification(mListener, state), NS_DISPATCH_NORMAL);
147
148
  return NS_OK;
149
}
150
151
NS_IMETHODIMP
152
OnlineStateObserver::Run()
153
{
154
  AssertIsOnMainThread();
155
156
  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
157
  if (NS_WARN_IF(!os)) {
158
    return NS_ERROR_FAILURE;
159
  }
160
161
  nsresult rv = os->AddObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
162
                                /* holdsWeak */ false);
163
  NS_ENSURE_SUCCESS(rv, rv);
164
165
  rv = os->AddObserver(this, "xpcom-shutdown", /* holdsWeak */ false);
166
  NS_ENSURE_SUCCESS(rv, rv);
167
168
  nsCOMPtr<nsIIOService> ioService = services::GetIOService();
169
  NS_ENSURE_STATE(ioService);
170
171
  bool offline = true;
172
  OnlineState state = eUnknown;
173
  if (NS_SUCCEEDED(ioService->GetOffline(&offline))) {
174
    state = offline ? eOffline : eOnline;
175
  }
176
177
  mInitiatingThread->Dispatch(
178
      new OnlineStateChangeNotification(mListener, state), NS_DISPATCH_NORMAL);
179
180
  return NS_OK;
181
}
182
183
NS_IMPL_ISUPPORTS(OnlineStateObserver, nsIRunnable, nsIObserver)
184
185
} // namespace dom
186
} // namespace mozilla
(-)a/dom/backgroundsync/OnlineStateObserver.h (+66 lines)
Line     Link Here 
Line 0    Link Here 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_dom_OnlineStateObserver_h
8
#define mozilla_dom_OnlineStateObserver_h
9
10
#include "nsIObserver.h"
11
#include "nsIRunnable.h"
12
#include "nsIThread.h"
13
14
namespace mozilla {
15
namespace dom {
16
17
class OnlineStateObserver final : public nsIRunnable
18
                                , public nsIObserver
19
{
20
public:
21
  NS_DECL_THREADSAFE_ISUPPORTS
22
  NS_DECL_NSIRUNNABLE
23
  NS_DECL_NSIOBSERVER
24
25
  typedef enum {
26
    eOnline,
27
    eOffline,
28
    eUnknown
29
  } OnlineState;
30
31
  // An interface to be implemented by code wishing to use the
32
  // OnlineStateObserver.
33
  // Note, the Listener implementation is responsible for calling
34
  // Shutdown() on the OnlineStateObserver to clear the weak
35
  // reference.
36
  class Listener
37
  {
38
  public:
39
    virtual void OnOnlineStateChanged(OnlineState aState) = 0;
40
  };
41
42
  static already_AddRefed<OnlineStateObserver>
43
  Init(Listener* aListener);
44
45
  // The Listener must call Shutdown() when it no
46
  // longer need to receive online state change notifications.
47
  void Shutdown(Listener* aListener);
48
49
private:
50
  OnlineStateObserver(Listener* aListener);
51
  ~OnlineStateObserver();
52
53
  // Weak reference cleared by Shutdown().
54
  Listener* MOZ_NON_OWNING_REF mListener;
55
  RefPtr<nsIThread> mInitiatingThread;
56
57
  // On xpcom-shutdown we do a nsIOService:SetOffline that
58
  // triggers a notification that we should ignore cause the
59
  // listener might already be gone.
60
  bool mShuttingDown;
61
};
62
63
} // namespace dom
64
} // namespace mozilla
65
66
#endif // mozilla_dom_OnlineStateObserver_h
(-)a/dom/backgroundsync/moz.build (-1 / +3 lines)
Line     Link Here 
 Lines 14-38   UNIFIED_SOURCES += [ Link Here 
14
    'BackgroundSyncChild.cpp',
14
    'BackgroundSyncChild.cpp',
15
    'BackgroundSyncParent.cpp',
15
    'BackgroundSyncParent.cpp',
16
    'ChromeDBSchema.cpp',
16
    'ChromeDBSchema.cpp',
17
    'ChromeStorageManager.cpp',
17
    'ChromeStorageManager.cpp',
18
    'DBAction.cpp',
18
    'DBAction.cpp',
19
    'DBConnection.cpp',
19
    'DBConnection.cpp',
20
    'DBSchema.cpp',
20
    'DBSchema.cpp',
21
    'DBSchemaUtils.cpp',
21
    'DBSchemaUtils.cpp',
22
    'OnlineStateObserver.cpp',
22
    'QuotaClient.cpp',
23
    'QuotaClient.cpp',
23
    'StorageManager.cpp',
24
    'StorageManager.cpp',
24
    'StorageManagerId.cpp'
25
    'StorageManagerId.cpp'
25
]
26
]
26
27
27
IPDL_SOURCES += [
28
IPDL_SOURCES += [
28
    'BackgroundSyncIPCTypes.ipdlh',
29
    'BackgroundSyncIPCTypes.ipdlh',
29
    'PBackgroundSync.ipdl'
30
    'PBackgroundSync.ipdl'
30
]
31
]
31
32
32
LOCAL_INCLUDES += [
33
LOCAL_INCLUDES += [
33
    '/dom/workers'
34
    '/dom/workers',
35
    '/netwerk/base'
34
]
36
]
35
37
36
include('/ipc/chromium/chromium-config.mozbuild')
38
include('/ipc/chromium/chromium-config.mozbuild')
37
39
38
FINAL_LIBRARY = 'xul'
40
FINAL_LIBRARY = 'xul'

Return to bug 1217544