dffdc63fac30f89d1caa148ab08229c02efe5da1
[WebKit-https.git] / Source / WebKit2 / UIProcess / Cocoa / WebPlaybackSessionManagerProxy.mm
1 /*
2  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WebPlaybackSessionManagerProxy.h"
28
29 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
30
31 #import "WebPageProxy.h"
32 #import "WebPlaybackSessionManagerMessages.h"
33 #import "WebPlaybackSessionManagerProxyMessages.h"
34 #import "WebProcessProxy.h"
35 #import <WebKitSystemInterface.h>
36
37 using namespace WebCore;
38
39 namespace WebKit {
40
41 #pragma mark - WebPlaybackSessionModelContext
42
43 void WebPlaybackSessionModelContext::addClient(WebPlaybackSessionModelClient& client)
44 {
45     ASSERT(!m_clients.contains(&client));
46     m_clients.add(&client);
47 }
48
49 void WebPlaybackSessionModelContext::removeClient(WebPlaybackSessionModelClient& client)
50 {
51     ASSERT(m_clients.contains(&client));
52     m_clients.remove(&client);
53 }
54
55 void WebPlaybackSessionModelContext::play()
56 {
57     if (m_manager)
58         m_manager->play(m_contextId);
59 }
60
61 void WebPlaybackSessionModelContext::pause()
62 {
63     if (m_manager)
64         m_manager->pause(m_contextId);
65 }
66
67 void WebPlaybackSessionModelContext::togglePlayState()
68 {
69     if (m_manager)
70         m_manager->togglePlayState(m_contextId);
71 }
72
73 void WebPlaybackSessionModelContext::beginScrubbing()
74 {
75     if (m_manager)
76         m_manager->beginScrubbing(m_contextId);
77
78     m_isScrubbing = true;
79 }
80
81 void WebPlaybackSessionModelContext::endScrubbing()
82 {
83     if (m_manager)
84         m_manager->endScrubbing(m_contextId);
85
86     m_isScrubbing = false;
87     m_playbackStartedTimeNeedsUpdate = isPlaying();
88 }
89
90 void WebPlaybackSessionModelContext::seekToTime(double time)
91 {
92     if (m_manager)
93         m_manager->seekToTime(m_contextId, time);
94 }
95
96 void WebPlaybackSessionModelContext::fastSeek(double time)
97 {
98     if (m_manager)
99         m_manager->fastSeek(m_contextId, time);
100 }
101
102 void WebPlaybackSessionModelContext::beginScanningForward()
103 {
104     if (m_manager)
105         m_manager->beginScanningForward(m_contextId);
106 }
107
108 void WebPlaybackSessionModelContext::beginScanningBackward()
109 {
110     if (m_manager)
111         m_manager->beginScanningBackward(m_contextId);
112 }
113
114 void WebPlaybackSessionModelContext::endScanning()
115 {
116     if (m_manager)
117         m_manager->endScanning(m_contextId);
118 }
119
120 void WebPlaybackSessionModelContext::selectAudioMediaOption(uint64_t optionId)
121 {
122     if (m_manager)
123         m_manager->selectAudioMediaOption(m_contextId, optionId);
124 }
125
126 void WebPlaybackSessionModelContext::selectLegibleMediaOption(uint64_t optionId)
127 {
128     if (m_manager)
129         m_manager->selectLegibleMediaOption(m_contextId, optionId);
130 }
131
132 void WebPlaybackSessionModelContext::togglePictureInPicture()
133 {
134     if (m_manager)
135         m_manager->togglePictureInPicture(m_contextId);
136 }
137
138 void WebPlaybackSessionModelContext::setPlaybackStartedTime(double playbackStartedTime)
139 {
140     m_playbackStartedTime = playbackStartedTime;
141     m_playbackStartedTimeNeedsUpdate = false;
142 }
143
144 void WebPlaybackSessionModelContext::setDuration(double duration)
145 {
146     m_duration = duration;
147     for (auto* client : m_clients)
148         client->durationChanged(duration);
149 }
150
151 void WebPlaybackSessionModelContext::setCurrentTime(double currentTime)
152 {
153     m_currentTime = currentTime;
154     auto anchorTime = [[NSProcessInfo processInfo] systemUptime];
155     if (m_playbackStartedTimeNeedsUpdate)
156         setPlaybackStartedTime(currentTime);
157
158     for (auto* client : m_clients)
159         client->currentTimeChanged(currentTime, anchorTime);
160 }
161
162 void WebPlaybackSessionModelContext::setBufferedTime(double bufferedTime)
163 {
164     m_bufferedTime = bufferedTime;
165     for (auto* client : m_clients)
166         client->bufferedTimeChanged(bufferedTime);
167 }
168
169 void WebPlaybackSessionModelContext::setRate(bool isPlaying, float playbackRate)
170 {
171     m_isPlaying = isPlaying;
172     m_playbackRate = playbackRate;
173     for (auto* client : m_clients)
174         client->rateChanged(isPlaying, playbackRate);
175 }
176
177 void WebPlaybackSessionModelContext::setSeekableRanges(WebCore::TimeRanges& seekableRanges)
178 {
179     m_seekableRanges = seekableRanges;
180     for (auto* client : m_clients)
181         client->seekableRangesChanged(seekableRanges);
182 }
183
184 void WebPlaybackSessionModelContext::setCanPlayFastReverse(bool canPlayFastReverse)
185 {
186     m_canPlayFastReverse = canPlayFastReverse;
187     for (auto* client : m_clients)
188         client->canPlayFastReverseChanged(canPlayFastReverse);
189 }
190
191 void WebPlaybackSessionModelContext::setAudioMediaSelectionOptions(const Vector<MediaSelectionOption>& audioMediaSelectionOptions, uint64_t audioMediaSelectedIndex)
192 {
193     m_audioMediaSelectionOptions = audioMediaSelectionOptions;
194     m_audioMediaSelectedIndex = audioMediaSelectedIndex;
195     for (auto* client : m_clients)
196         client->audioMediaSelectionOptionsChanged(audioMediaSelectionOptions, audioMediaSelectedIndex);
197 }
198
199 void WebPlaybackSessionModelContext::setLegibleMediaSelectionOptions(const Vector<MediaSelectionOption>& legibleMediaSelectionOptions, uint64_t legibleMediaSelectedIndex)
200 {
201     m_legibleMediaSelectionOptions = legibleMediaSelectionOptions;
202     m_legibleMediaSelectedIndex = legibleMediaSelectedIndex;
203
204     for (auto* client : m_clients)
205         client->legibleMediaSelectionOptionsChanged(legibleMediaSelectionOptions, legibleMediaSelectedIndex);
206 }
207
208 void WebPlaybackSessionModelContext::setAudioMediaSelectionIndex(uint64_t selectedIndex)
209 {
210     m_audioMediaSelectedIndex = selectedIndex;
211
212     for (auto* client : m_clients)
213         client->audioMediaSelectionIndexChanged(selectedIndex);
214 }
215
216 void WebPlaybackSessionModelContext::setLegibleMediaSelectionIndex(uint64_t selectedIndex)
217 {
218     m_legibleMediaSelectedIndex = selectedIndex;
219
220     for (auto* client : m_clients)
221         client->legibleMediaSelectionIndexChanged(selectedIndex);
222 }
223
224 void WebPlaybackSessionModelContext::setExternalPlayback(bool enabled, WebPlaybackSessionModel::ExternalPlaybackTargetType type, const String& localizedName)
225 {
226     m_externalPlaybackEnabled = enabled;
227     m_externalPlaybackTargetType = type;
228     m_externalPlaybackLocalizedDeviceName = localizedName;
229
230     for (auto* client : m_clients)
231         client->externalPlaybackChanged(enabled, type, localizedName);
232 }
233
234 void WebPlaybackSessionModelContext::setWirelessVideoPlaybackDisabled(bool wirelessVideoPlaybackDisabled)
235 {
236     m_wirelessVideoPlaybackDisabled = wirelessVideoPlaybackDisabled;
237     for (auto* client : m_clients)
238         client->wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled);
239 }
240
241 #pragma mark - WebPlaybackSessionManagerProxy
242
243 RefPtr<WebPlaybackSessionManagerProxy> WebPlaybackSessionManagerProxy::create(WebPageProxy& page)
244 {
245     return adoptRef(new WebPlaybackSessionManagerProxy(page));
246 }
247
248 WebPlaybackSessionManagerProxy::WebPlaybackSessionManagerProxy(WebPageProxy& page)
249     : m_page(&page)
250 {
251     m_page->process().addMessageReceiver(Messages::WebPlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID(), *this);
252 }
253
254 WebPlaybackSessionManagerProxy::~WebPlaybackSessionManagerProxy()
255 {
256     if (!m_page)
257         return;
258     invalidate();
259 }
260
261 void WebPlaybackSessionManagerProxy::invalidate()
262 {
263     m_page->process().removeMessageReceiver(Messages::WebPlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID());
264     m_page = nullptr;
265
266     for (auto& tuple : m_contextMap.values()) {
267         RefPtr<WebPlaybackSessionModelContext> model;
268         RefPtr<PlatformWebPlaybackSessionInterface> interface;
269         std::tie(model, interface) = tuple;
270
271         interface->invalidate();
272     }
273
274     m_contextMap.clear();
275     m_clientCounts.clear();
276 }
277
278 WebPlaybackSessionManagerProxy::ModelInterfaceTuple WebPlaybackSessionManagerProxy::createModelAndInterface(uint64_t contextId)
279 {
280     Ref<WebPlaybackSessionModelContext> model = WebPlaybackSessionModelContext::create(*this, contextId);
281     Ref<PlatformWebPlaybackSessionInterface> interface = PlatformWebPlaybackSessionInterface::create(model);
282
283     return std::make_tuple(WTFMove(model), WTFMove(interface));
284 }
285
286 WebPlaybackSessionManagerProxy::ModelInterfaceTuple& WebPlaybackSessionManagerProxy::ensureModelAndInterface(uint64_t contextId)
287 {
288     auto addResult = m_contextMap.add(contextId, ModelInterfaceTuple());
289     if (addResult.isNewEntry)
290         addResult.iterator->value = createModelAndInterface(contextId);
291     return addResult.iterator->value;
292 }
293
294 WebPlaybackSessionModelContext& WebPlaybackSessionManagerProxy::ensureModel(uint64_t contextId)
295 {
296     return *std::get<0>(ensureModelAndInterface(contextId));
297 }
298
299 PlatformWebPlaybackSessionInterface& WebPlaybackSessionManagerProxy::ensureInterface(uint64_t contextId)
300 {
301     return *std::get<1>(ensureModelAndInterface(contextId));
302 }
303
304 void WebPlaybackSessionManagerProxy::addClientForContext(uint64_t contextId)
305 {
306     m_clientCounts.add(contextId);
307 }
308
309 void WebPlaybackSessionManagerProxy::removeClientForContext(uint64_t contextId)
310 {
311     if (!m_clientCounts.remove(contextId))
312         return;
313
314     ensureInterface(contextId).invalidate();
315     m_contextMap.remove(contextId);
316 }
317
318 #pragma mark Messages from WebPlaybackSessionManager
319
320 void WebPlaybackSessionManagerProxy::setUpPlaybackControlsManagerWithID(uint64_t contextId)
321 {
322 #if PLATFORM(MAC)
323     if (m_controlsManagerContextId == contextId)
324         return;
325
326     if (m_controlsManagerContextId)
327         removeClientForContext(m_controlsManagerContextId);
328
329     m_controlsManagerContextId = contextId;
330     ensureInterface(m_controlsManagerContextId).ensureControlsManager();
331     addClientForContext(m_controlsManagerContextId);
332
333     m_page->videoControlsManagerDidChange();
334 #else
335     UNUSED_PARAM(contextId);
336 #endif
337 }
338
339 void WebPlaybackSessionManagerProxy::clearPlaybackControlsManager()
340 {
341 #if PLATFORM(MAC)
342     if (!m_controlsManagerContextId)
343         return;
344
345     removeClientForContext(m_controlsManagerContextId);
346     m_controlsManagerContextId = 0;
347     m_page->videoControlsManagerDidChange();
348 #endif
349 }
350
351 void WebPlaybackSessionManagerProxy::resetMediaState(uint64_t contextId)
352 {
353     ensureInterface(contextId).resetMediaState();
354 }
355
356 void WebPlaybackSessionManagerProxy::setCurrentTime(uint64_t contextId, double currentTime, double hostTime)
357 {
358     ensureModel(contextId).setCurrentTime(currentTime);
359 }
360
361 void WebPlaybackSessionManagerProxy::setBufferedTime(uint64_t contextId, double bufferedTime)
362 {
363     ensureModel(contextId).setBufferedTime(bufferedTime);
364 }
365
366 void WebPlaybackSessionManagerProxy::setSeekableRangesVector(uint64_t contextId, Vector<std::pair<double, double>> ranges)
367 {
368     Ref<TimeRanges> timeRanges = TimeRanges::create();
369     for (const auto& range : ranges) {
370         ASSERT(isfinite(range.first));
371         ASSERT(isfinite(range.second));
372         ASSERT(range.second >= range.first);
373         timeRanges->add(range.first, range.second);
374     }
375
376     ensureModel(contextId).setSeekableRanges(timeRanges);
377 }
378
379 void WebPlaybackSessionManagerProxy::setCanPlayFastReverse(uint64_t contextId, bool value)
380 {
381     ensureModel(contextId).setCanPlayFastReverse(value);
382 }
383
384 void WebPlaybackSessionManagerProxy::setAudioMediaSelectionOptions(uint64_t contextId, Vector<MediaSelectionOption> options, uint64_t selectedIndex)
385 {
386     ensureModel(contextId).setAudioMediaSelectionOptions(options, selectedIndex);
387 }
388
389 void WebPlaybackSessionManagerProxy::setLegibleMediaSelectionOptions(uint64_t contextId, Vector<MediaSelectionOption> options, uint64_t selectedIndex)
390 {
391     ensureModel(contextId).setLegibleMediaSelectionOptions(options, selectedIndex);
392 }
393
394 void WebPlaybackSessionManagerProxy::setAudioMediaSelectionIndex(uint64_t contextId, uint64_t selectedIndex)
395 {
396     ensureModel(contextId).setAudioMediaSelectionIndex(selectedIndex);
397 }
398
399 void WebPlaybackSessionManagerProxy::setLegibleMediaSelectionIndex(uint64_t contextId, uint64_t selectedIndex)
400 {
401     ensureModel(contextId).setLegibleMediaSelectionIndex(selectedIndex);
402 }
403
404 void WebPlaybackSessionManagerProxy::setExternalPlaybackProperties(uint64_t contextId, bool enabled, uint32_t targetType, String localizedDeviceName)
405 {
406     WebPlaybackSessionModel::ExternalPlaybackTargetType type = static_cast<WebPlaybackSessionModel::ExternalPlaybackTargetType>(targetType);
407     ASSERT(type == WebPlaybackSessionModel::TargetTypeAirPlay || type == WebPlaybackSessionModel::TargetTypeTVOut || type == WebPlaybackSessionModel::TargetTypeNone);
408
409     ensureModel(contextId).setExternalPlayback(enabled, type, localizedDeviceName);
410 }
411
412 void WebPlaybackSessionManagerProxy::setWirelessVideoPlaybackDisabled(uint64_t contextId, bool disabled)
413 {
414     ensureModel(contextId).setWirelessVideoPlaybackDisabled(disabled);
415 }
416
417 void WebPlaybackSessionManagerProxy::setDuration(uint64_t contextId, double duration)
418 {
419     ensureModel(contextId).setDuration(duration);
420 }
421
422 void WebPlaybackSessionManagerProxy::setPlaybackStartedTime(uint64_t contextId, double playbackStartedTime)
423 {
424     ensureModel(contextId).setPlaybackStartedTime(playbackStartedTime);
425 }
426
427 void WebPlaybackSessionManagerProxy::setRate(uint64_t contextId, bool isPlaying, double rate)
428 {
429     ensureModel(contextId).setRate(isPlaying, rate);
430 }
431
432
433 void WebPlaybackSessionManagerProxy::handleControlledElementIDResponse(uint64_t contextId, String identifier) const
434 {
435 #if PLATFORM(MAC)
436     if (contextId == m_controlsManagerContextId)
437         m_page->handleControlledElementIDResponse(identifier);
438 #else
439     UNUSED_PARAM(contextId);
440     UNUSED_PARAM(identifier);
441 #endif
442 }
443
444
445 #pragma mark Messages to WebPlaybackSessionManager
446
447 void WebPlaybackSessionManagerProxy::play(uint64_t contextId)
448 {
449     m_page->send(Messages::WebPlaybackSessionManager::Play(contextId), m_page->pageID());
450 }
451
452 void WebPlaybackSessionManagerProxy::pause(uint64_t contextId)
453 {
454     m_page->send(Messages::WebPlaybackSessionManager::Pause(contextId), m_page->pageID());
455 }
456
457 void WebPlaybackSessionManagerProxy::togglePlayState(uint64_t contextId)
458 {
459     m_page->send(Messages::WebPlaybackSessionManager::TogglePlayState(contextId), m_page->pageID());
460 }
461
462 void WebPlaybackSessionManagerProxy::beginScrubbing(uint64_t contextId)
463 {
464     m_page->send(Messages::WebPlaybackSessionManager::BeginScrubbing(contextId), m_page->pageID());
465 }
466
467 void WebPlaybackSessionManagerProxy::endScrubbing(uint64_t contextId)
468 {
469     m_page->send(Messages::WebPlaybackSessionManager::EndScrubbing(contextId), m_page->pageID());
470 }
471
472 void WebPlaybackSessionManagerProxy::seekToTime(uint64_t contextId, double time)
473 {
474     m_page->send(Messages::WebPlaybackSessionManager::SeekToTime(contextId, time), m_page->pageID());
475 }
476
477 void WebPlaybackSessionManagerProxy::fastSeek(uint64_t contextId, double time)
478 {
479     m_page->send(Messages::WebPlaybackSessionManager::FastSeek(contextId, time), m_page->pageID());
480 }
481
482 void WebPlaybackSessionManagerProxy::beginScanningForward(uint64_t contextId)
483 {
484     m_page->send(Messages::WebPlaybackSessionManager::BeginScanningForward(contextId), m_page->pageID());
485 }
486
487 void WebPlaybackSessionManagerProxy::beginScanningBackward(uint64_t contextId)
488 {
489     m_page->send(Messages::WebPlaybackSessionManager::BeginScanningBackward(contextId), m_page->pageID());
490 }
491
492 void WebPlaybackSessionManagerProxy::endScanning(uint64_t contextId)
493 {
494     m_page->send(Messages::WebPlaybackSessionManager::EndScanning(contextId), m_page->pageID());
495 }
496
497 void WebPlaybackSessionManagerProxy::selectAudioMediaOption(uint64_t contextId, uint64_t index)
498 {
499     m_page->send(Messages::WebPlaybackSessionManager::SelectAudioMediaOption(contextId, index), m_page->pageID());
500 }
501
502 void WebPlaybackSessionManagerProxy::selectLegibleMediaOption(uint64_t contextId, uint64_t index)
503 {
504     m_page->send(Messages::WebPlaybackSessionManager::SelectLegibleMediaOption(contextId, index), m_page->pageID());
505 }
506
507 void WebPlaybackSessionManagerProxy::togglePictureInPicture(uint64_t contextId)
508 {
509     m_page->send(Messages::WebPlaybackSessionManager::TogglePictureInPicture(contextId), m_page->pageID());
510 }
511
512 void WebPlaybackSessionManagerProxy::requestControlledElementID()
513 {
514     if (m_controlsManagerContextId)
515         m_page->send(Messages::WebPlaybackSessionManager::HandleControlledElementIDRequest(m_controlsManagerContextId), m_page->pageID());
516 }
517
518 PlatformWebPlaybackSessionInterface* WebPlaybackSessionManagerProxy::controlsManagerInterface()
519 {
520     if (!m_controlsManagerContextId)
521         return nullptr;
522     
523     auto& interface = ensureInterface(m_controlsManagerContextId);
524     return &interface;
525 }
526
527 } // namespace WebKit
528
529 #endif // PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))