Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 "PresentationReceiver.h"
8 :
9 : #include "mozilla/dom/PresentationReceiverBinding.h"
10 : #include "mozilla/dom/Promise.h"
11 : #include "nsContentUtils.h"
12 : #include "nsIPresentationService.h"
13 : #include "nsPIDOMWindow.h"
14 : #include "nsServiceManagerUtils.h"
15 : #include "nsThreadUtils.h"
16 : #include "PresentationConnection.h"
17 : #include "PresentationConnectionList.h"
18 : #include "PresentationLog.h"
19 :
20 : namespace mozilla {
21 : namespace dom {
22 :
23 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PresentationReceiver,
24 : mOwner,
25 : mGetConnectionListPromise,
26 : mConnectionList)
27 :
28 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationReceiver)
29 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationReceiver)
30 :
31 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationReceiver)
32 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
33 0 : NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
34 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
35 0 : NS_INTERFACE_MAP_END
36 :
37 : /* static */ already_AddRefed<PresentationReceiver>
38 0 : PresentationReceiver::Create(nsPIDOMWindowInner* aWindow)
39 : {
40 0 : RefPtr<PresentationReceiver> receiver = new PresentationReceiver(aWindow);
41 0 : return NS_WARN_IF(!receiver->Init()) ? nullptr : receiver.forget();
42 : }
43 :
44 0 : PresentationReceiver::PresentationReceiver(nsPIDOMWindowInner* aWindow)
45 0 : : mOwner(aWindow)
46 : {
47 0 : MOZ_ASSERT(aWindow);
48 0 : }
49 :
50 0 : PresentationReceiver::~PresentationReceiver()
51 : {
52 0 : Shutdown();
53 0 : }
54 :
55 : bool
56 0 : PresentationReceiver::Init()
57 : {
58 0 : if (NS_WARN_IF(!mOwner)) {
59 0 : return false;
60 : }
61 0 : mWindowId = mOwner->WindowID();
62 :
63 0 : nsCOMPtr<nsIDocShell> docShell = mOwner->GetDocShell();
64 0 : MOZ_ASSERT(docShell);
65 :
66 0 : nsContentUtils::GetPresentationURL(docShell, mUrl);
67 0 : return !mUrl.IsEmpty();
68 : }
69 :
70 0 : void PresentationReceiver::Shutdown()
71 : {
72 0 : PRES_DEBUG("receiver shutdown:windowId[%" PRId64 "]\n", mWindowId);
73 :
74 : // Unregister listener for incoming sessions.
75 : nsCOMPtr<nsIPresentationService> service =
76 0 : do_GetService(PRESENTATION_SERVICE_CONTRACTID);
77 0 : if (NS_WARN_IF(!service)) {
78 0 : return;
79 : }
80 :
81 : Unused <<
82 0 : NS_WARN_IF(NS_FAILED(service->UnregisterRespondingListener(mWindowId)));
83 : }
84 :
85 : /* virtual */ JSObject*
86 0 : PresentationReceiver::WrapObject(JSContext* aCx,
87 : JS::Handle<JSObject*> aGivenProto)
88 : {
89 0 : return PresentationReceiverBinding::Wrap(aCx, this, aGivenProto);
90 : }
91 :
92 : NS_IMETHODIMP
93 0 : PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
94 : const nsAString& aSessionId)
95 : {
96 0 : PRES_DEBUG("receiver session connect:id[%s], windowId[%" PRIx64 "]\n",
97 : NS_ConvertUTF16toUTF8(aSessionId).get(), aWindowId);
98 :
99 0 : if (NS_WARN_IF(!mOwner)) {
100 0 : return NS_ERROR_FAILURE;
101 : }
102 :
103 0 : if (NS_WARN_IF(aWindowId != mWindowId)) {
104 0 : return NS_ERROR_INVALID_ARG;
105 : }
106 :
107 0 : if (NS_WARN_IF(!mConnectionList)) {
108 0 : return NS_ERROR_FAILURE;
109 : }
110 :
111 : RefPtr<PresentationConnection> connection =
112 0 : PresentationConnection::Create(mOwner, aSessionId, mUrl,
113 : nsIPresentationService::ROLE_RECEIVER,
114 0 : mConnectionList);
115 0 : if (NS_WARN_IF(!connection)) {
116 0 : return NS_ERROR_NOT_AVAILABLE;
117 : }
118 :
119 0 : return NS_OK;
120 : }
121 :
122 : already_AddRefed<Promise>
123 0 : PresentationReceiver::GetConnectionList(ErrorResult& aRv)
124 : {
125 0 : nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mOwner);
126 0 : if (NS_WARN_IF(!global)) {
127 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
128 0 : return nullptr;
129 : }
130 :
131 0 : if (!mGetConnectionListPromise) {
132 0 : mGetConnectionListPromise = Promise::Create(global, aRv);
133 0 : if (NS_WARN_IF(aRv.Failed())) {
134 0 : return nullptr;
135 : }
136 :
137 0 : RefPtr<PresentationReceiver> self = this;
138 0 : nsresult rv = NS_DispatchToMainThread(NS_NewRunnableFunction(
139 : "dom::PresentationReceiver::GetConnectionList",
140 0 : [self]() -> void { self->CreateConnectionList(); }));
141 0 : if (NS_FAILED(rv)) {
142 0 : aRv.Throw(rv);
143 0 : return nullptr;
144 : }
145 : }
146 :
147 0 : RefPtr<Promise> promise = mGetConnectionListPromise;
148 0 : return promise.forget();
149 : }
150 :
151 : void
152 0 : PresentationReceiver::CreateConnectionList()
153 : {
154 0 : MOZ_ASSERT(mGetConnectionListPromise);
155 :
156 0 : if (mConnectionList) {
157 0 : return;
158 : }
159 :
160 : mConnectionList = new PresentationConnectionList(mOwner,
161 0 : mGetConnectionListPromise);
162 :
163 : // Register listener for incoming sessions.
164 : nsCOMPtr<nsIPresentationService> service =
165 0 : do_GetService(PRESENTATION_SERVICE_CONTRACTID);
166 0 : if (NS_WARN_IF(!service)) {
167 0 : mGetConnectionListPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
168 0 : return;
169 : }
170 :
171 0 : nsresult rv = service->RegisterRespondingListener(mWindowId, this);
172 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
173 0 : mGetConnectionListPromise->MaybeReject(rv);
174 : }
175 : }
176 :
177 : } // namespace dom
178 : } // namespace mozilla
|