Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/presentation/PresentationCallbacks.cpp
Line
Count
Source (jump to first uncovered line)
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 "mozilla/dom/Promise.h"
8
#include "nsIDocShell.h"
9
#include "nsIInterfaceRequestorUtils.h"
10
#include "nsIPresentationService.h"
11
#include "nsIWebProgress.h"
12
#include "nsServiceManagerUtils.h"
13
#include "nsThreadUtils.h"
14
#include "PresentationCallbacks.h"
15
#include "PresentationRequest.h"
16
#include "PresentationConnection.h"
17
#include "PresentationTransportBuilderConstructor.h"
18
19
using namespace mozilla;
20
using namespace mozilla::dom;
21
22
/*
23
 * Implementation of PresentationRequesterCallback
24
 */
25
26
NS_IMPL_ISUPPORTS(PresentationRequesterCallback, nsIPresentationServiceCallback)
27
28
PresentationRequesterCallback::PresentationRequesterCallback(PresentationRequest* aRequest,
29
                                                             const nsAString& aSessionId,
30
                                                             Promise* aPromise)
31
  : mRequest(aRequest)
32
  , mSessionId(aSessionId)
33
  , mPromise(aPromise)
34
0
{
35
0
  MOZ_ASSERT(mRequest);
36
0
  MOZ_ASSERT(mPromise);
37
0
  MOZ_ASSERT(!mSessionId.IsEmpty());
38
0
}
39
40
PresentationRequesterCallback::~PresentationRequesterCallback()
41
0
{
42
0
}
43
44
// nsIPresentationServiceCallback
45
NS_IMETHODIMP
46
PresentationRequesterCallback::NotifySuccess(const nsAString& aUrl)
47
0
{
48
0
  MOZ_ASSERT(NS_IsMainThread());
49
0
50
0
  if (aUrl.IsEmpty()) {
51
0
    return NotifyError(NS_ERROR_DOM_OPERATION_ERR);
52
0
  }
53
0
54
0
  RefPtr<PresentationConnection> connection =
55
0
    PresentationConnection::Create(mRequest->GetOwner(), mSessionId, aUrl,
56
0
                                   nsIPresentationService::ROLE_CONTROLLER);
57
0
  if (NS_WARN_IF(!connection)) {
58
0
    return NotifyError(NS_ERROR_DOM_OPERATION_ERR);
59
0
  }
60
0
61
0
  mRequest->NotifyPromiseSettled();
62
0
  mPromise->MaybeResolve(connection);
63
0
64
0
  return mRequest->DispatchConnectionAvailableEvent(connection);
65
0
}
66
67
NS_IMETHODIMP
68
PresentationRequesterCallback::NotifyError(nsresult aError)
69
0
{
70
0
  MOZ_ASSERT(NS_IsMainThread());
71
0
72
0
  mRequest->NotifyPromiseSettled();
73
0
  mPromise->MaybeReject(aError);
74
0
  return NS_OK;
75
0
}
76
77
/*
78
 * Implementation of PresentationRequesterCallback
79
 */
80
81
PresentationReconnectCallback::PresentationReconnectCallback(
82
                                           PresentationRequest* aRequest,
83
                                           const nsAString& aSessionId,
84
                                           Promise* aPromise,
85
                                           PresentationConnection* aConnection)
86
  : PresentationRequesterCallback(aRequest, aSessionId, aPromise)
87
  , mConnection(aConnection)
88
0
{
89
0
}
90
91
PresentationReconnectCallback::~PresentationReconnectCallback()
92
0
{
93
0
}
94
95
NS_IMETHODIMP
96
PresentationReconnectCallback::NotifySuccess(const nsAString& aUrl)
97
0
{
98
0
  MOZ_ASSERT(NS_IsMainThread());
99
0
100
0
  nsCOMPtr<nsIPresentationService> service =
101
0
    do_GetService(PRESENTATION_SERVICE_CONTRACTID);
102
0
  if (NS_WARN_IF(!service)) {
103
0
    return NS_ERROR_NOT_AVAILABLE;
104
0
  }
105
0
106
0
  nsresult rv = NS_OK;
107
0
  // We found a matched connection with the same window ID, URL, and
108
0
  // the session ID. Resolve the promise with this connection and dispatch
109
0
  // the event.
110
0
  if (mConnection) {
111
0
    mConnection->NotifyStateChange(
112
0
      mSessionId,
113
0
      nsIPresentationSessionListener::STATE_CONNECTING,
114
0
      NS_OK);
115
0
    mPromise->MaybeResolve(mConnection);
116
0
    rv = mRequest->DispatchConnectionAvailableEvent(mConnection);
117
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
118
0
      return rv;
119
0
    }
120
0
  } else {
121
0
    // Use |PresentationRequesterCallback::NotifySuccess| to create a new
122
0
    // connection since we don't find one that can be reused.
123
0
    rv = PresentationRequesterCallback::NotifySuccess(aUrl);
124
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
125
0
      return rv;
126
0
    }
127
0
128
0
    rv = service->UpdateWindowIdBySessionId(mSessionId,
129
0
                                            nsIPresentationService::ROLE_CONTROLLER,
130
0
                                            mRequest->GetOwner()->WindowID());
131
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
132
0
      return rv;
133
0
    }
134
0
  }
135
0
136
0
  nsString sessionId = nsString(mSessionId);
137
0
  return NS_DispatchToMainThread(NS_NewRunnableFunction(
138
0
    "dom::PresentationReconnectCallback::NotifySuccess",
139
0
    [sessionId, service]() -> void {
140
0
      service->BuildTransport(sessionId,
141
0
                              nsIPresentationService::ROLE_CONTROLLER);
142
0
    }));
143
0
}
144
145
NS_IMETHODIMP
146
PresentationReconnectCallback::NotifyError(nsresult aError)
147
0
{
148
0
  if (mConnection) {
149
0
    mConnection->NotifyStateChange(
150
0
      mSessionId,
151
0
      nsIPresentationSessionListener::STATE_CLOSED,
152
0
      aError);
153
0
  }
154
0
  return PresentationRequesterCallback::NotifyError(aError);
155
0
}
156
157
NS_IMPL_ISUPPORTS(PresentationResponderLoadingCallback,
158
                  nsIWebProgressListener,
159
                  nsISupportsWeakReference)
160
161
PresentationResponderLoadingCallback::PresentationResponderLoadingCallback(const nsAString& aSessionId)
162
  : mSessionId(aSessionId)
163
0
{
164
0
}
165
166
PresentationResponderLoadingCallback::~PresentationResponderLoadingCallback()
167
0
{
168
0
  if (mProgress) {
169
0
    mProgress->RemoveProgressListener(this);
170
0
    mProgress = nullptr;
171
0
  }
172
0
}
173
174
nsresult
175
PresentationResponderLoadingCallback::Init(nsIDocShell* aDocShell)
176
0
{
177
0
  mProgress = do_GetInterface(aDocShell);
178
0
  if (NS_WARN_IF(!mProgress)) {
179
0
    return NS_ERROR_NOT_AVAILABLE;
180
0
  }
181
0
182
0
  uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
183
0
  nsresult rv = aDocShell->GetBusyFlags(&busyFlags);
184
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
185
0
    return rv;
186
0
  }
187
0
188
0
  if ((busyFlags == nsIDocShell::BUSY_FLAGS_NONE) ||
189
0
      (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) {
190
0
    // The docshell has finished loading or is receiving data (|STATE_TRANSFERRING|
191
0
    // has already been fired), so the page is ready for presentation use.
192
0
    return NotifyReceiverReady(/* isLoading = */ true);
193
0
  }
194
0
195
0
  // Start to listen to document state change event |STATE_TRANSFERRING|.
196
0
  return mProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
197
0
}
198
199
nsresult
200
PresentationResponderLoadingCallback::NotifyReceiverReady(bool aIsLoading)
201
0
{
202
0
  nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(mProgress);
203
0
  if (NS_WARN_IF(!window || !window->GetCurrentInnerWindow())) {
204
0
    return NS_ERROR_NOT_AVAILABLE;
205
0
  }
206
0
  uint64_t windowId = window->GetCurrentInnerWindow()->WindowID();
207
0
208
0
  nsCOMPtr<nsIPresentationService> service =
209
0
    do_GetService(PRESENTATION_SERVICE_CONTRACTID);
210
0
  if (NS_WARN_IF(!service)) {
211
0
    return NS_ERROR_NOT_AVAILABLE;
212
0
  }
213
0
214
0
  nsCOMPtr<nsIPresentationTransportBuilderConstructor> constructor =
215
0
    PresentationTransportBuilderConstructor::Create();
216
0
  return service->NotifyReceiverReady(mSessionId,
217
0
                                      windowId,aIsLoading,
218
0
                                      constructor);
219
0
}
220
221
// nsIWebProgressListener
222
NS_IMETHODIMP
223
PresentationResponderLoadingCallback::OnStateChange(nsIWebProgress* aWebProgress,
224
                                                    nsIRequest* aRequest,
225
                                                    uint32_t aStateFlags,
226
                                                    nsresult aStatus)
227
0
{
228
0
  MOZ_ASSERT(NS_IsMainThread());
229
0
230
0
  if (aStateFlags & (nsIWebProgressListener::STATE_TRANSFERRING |
231
0
                     nsIWebProgressListener::STATE_STOP)) {
232
0
    mProgress->RemoveProgressListener(this);
233
0
234
0
    bool isLoading = aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING;
235
0
    return NotifyReceiverReady(isLoading);
236
0
  }
237
0
238
0
  return NS_OK;
239
0
}
240
241
NS_IMETHODIMP
242
PresentationResponderLoadingCallback::OnProgressChange(nsIWebProgress* aWebProgress,
243
                                                       nsIRequest* aRequest,
244
                                                       int32_t aCurSelfProgress,
245
                                                       int32_t aMaxSelfProgress,
246
                                                       int32_t aCurTotalProgress,
247
                                                       int32_t aMaxTotalProgress)
248
0
{
249
0
  // Do nothing.
250
0
  return NS_OK;
251
0
}
252
253
NS_IMETHODIMP
254
PresentationResponderLoadingCallback::OnLocationChange(nsIWebProgress* aWebProgress,
255
                                                       nsIRequest* aRequest,
256
                                                       nsIURI* aURI,
257
                                                       uint32_t aFlags)
258
0
{
259
0
  // Do nothing.
260
0
  return NS_OK;
261
0
}
262
263
NS_IMETHODIMP
264
PresentationResponderLoadingCallback::OnStatusChange(nsIWebProgress* aWebProgress,
265
                                                     nsIRequest* aRequest,
266
                                                     nsresult aStatus,
267
                                                     const char16_t* aMessage)
268
0
{
269
0
  // Do nothing.
270
0
  return NS_OK;
271
0
}
272
273
NS_IMETHODIMP
274
PresentationResponderLoadingCallback::OnSecurityChange(nsIWebProgress* aWebProgress,
275
                                                       nsIRequest* aRequest,
276
                                                       uint32_t state)
277
0
{
278
0
  // Do nothing.
279
0
  return NS_OK;
280
0
}