Source/WebCore:
[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::toggleMuted()
139 {
140     if (m_manager)
141         m_manager->toggleMuted(m_contextId);
142 }
143
144 void WebPlaybackSessionModelContext::setPlaybackStartedTime(double playbackStartedTime)
145 {
146     m_playbackStartedTime = playbackStartedTime;
147     m_playbackStartedTimeNeedsUpdate = false;
148 }
149
150 void WebPlaybackSessionModelContext::setDuration(double duration)
151 {
152     m_duration = duration;
153     for (auto* client : m_clients)
154         client->durationChanged(duration);
155 }
156
157 void WebPlaybackSessionModelContext::setCurrentTime(double currentTime)
158 {
159     m_currentTime = currentTime;
160     auto anchorTime = [[NSProcessInfo processInfo] systemUptime];
161     if (m_playbackStartedTimeNeedsUpdate)
162         setPlaybackStartedTime(currentTime);
163
164     for (auto* client : m_clients)
165         client->currentTimeChanged(currentTime, anchorTime);
166 }
167
168 void WebPlaybackSessionModelContext::setBufferedTime(double bufferedTime)
169 {
170     m_bufferedTime = bufferedTime;
171     for (auto* client : m_clients)
172         client->bufferedTimeChanged(bufferedTime);
173 }
174
175 void WebPlaybackSessionModelContext::setRate(bool isPlaying, float playbackRate)
176 {
177     m_isPlaying = isPlaying;
178     m_playbackRate = playbackRate;
179     for (auto* client : m_clients)
180         client->rateChanged(isPlaying, playbackRate);
181 }
182
183 void WebPlaybackSessionModelContext::setSeekableRanges(WebCore::TimeRanges& seekableRanges)
184 {
185     m_seekableRanges = seekableRanges;
186     for (auto* client : m_clients)
187         client->seekableRangesChanged(seekableRanges);
188 }
189
190 void WebPlaybackSessionModelContext::setCanPlayFastReverse(bool canPlayFastReverse)
191 {
192     m_canPlayFastReverse = canPlayFastReverse;
193     for (auto* client : m_clients)
194         client->canPlayFastReverseChanged(canPlayFastReverse);
195 }
196
197 void WebPlaybackSessionModelContext::setAudioMediaSelectionOptions(const Vector<MediaSelectionOption>& audioMediaSelectionOptions, uint64_t audioMediaSelectedIndex)
198 {
199     m_audioMediaSelectionOptions = audioMediaSelectionOptions;
200     m_audioMediaSelectedIndex = audioMediaSelectedIndex;
201     for (auto* client : m_clients)
202         client->audioMediaSelectionOptionsChanged(audioMediaSelectionOptions, audioMediaSelectedIndex);
203 }
204
205 void WebPlaybackSessionModelContext::setLegibleMediaSelectionOptions(const Vector<MediaSelectionOption>& legibleMediaSelectionOptions, uint64_t legibleMediaSelectedIndex)
206 {
207     m_legibleMediaSelectionOptions = legibleMediaSelectionOptions;
208     m_legibleMediaSelectedIndex = legibleMediaSelectedIndex;
209
210     for (auto* client : m_clients)
211         client->legibleMediaSelectionOptionsChanged(legibleMediaSelectionOptions, legibleMediaSelectedIndex);
212 }
213
214 void WebPlaybackSessionModelContext::setAudioMediaSelectionIndex(uint64_t selectedIndex)
215 {
216     m_audioMediaSelectedIndex = selectedIndex;
217
218     for (auto* client : m_clients)
219         client->audioMediaSelectionIndexChanged(selectedIndex);
220 }
221
222 void WebPlaybackSessionModelContext::setLegibleMediaSelectionIndex(uint64_t selectedIndex)
223 {
224     m_legibleMediaSelectedIndex = selectedIndex;
225
226     for (auto* client : m_clients)
227         client->legibleMediaSelectionIndexChanged(selectedIndex);
228 }
229
230 void WebPlaybackSessionModelContext::setExternalPlayback(bool enabled, WebPlaybackSessionModel::ExternalPlaybackTargetType type, const String& localizedName)
231 {
232     m_externalPlaybackEnabled = enabled;
233     m_externalPlaybackTargetType = type;
234     m_externalPlaybackLocalizedDeviceName = localizedName;
235
236     for (auto* client : m_clients)
237         client->externalPlaybackChanged(enabled, type, localizedName);
238 }
239
240 void WebPlaybackSessionModelContext::setWirelessVideoPlaybackDisabled(bool wirelessVideoPlaybackDisabled)
241 {
242     m_wirelessVideoPlaybackDisabled = wirelessVideoPlaybackDisabled;
243     for (auto* client : m_clients)
244         client->wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled);
245 }
246
247 void WebPlaybackSessionModelContext::setMuted(bool muted)
248 {
249     m_muted = muted;
250     for (auto* client : m_clients)
251         client->mutedChanged(muted);
252 }
253
254 #pragma mark - WebPlaybackSessionManagerProxy
255
256 RefPtr<WebPlaybackSessionManagerProxy> WebPlaybackSessionManagerProxy::create(WebPageProxy& page)
257 {
258     return adoptRef(new WebPlaybackSessionManagerProxy(page));
259 }
260
261 WebPlaybackSessionManagerProxy::WebPlaybackSessionManagerProxy(WebPageProxy& page)
262     : m_page(&page)
263 {
264     m_page->process().addMessageReceiver(Messages::WebPlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID(), *this);
265 }
266
267 WebPlaybackSessionManagerProxy::~WebPlaybackSessionManagerProxy()
268 {
269     if (!m_page)
270         return;
271     invalidate();
272 }
273
274 void WebPlaybackSessionManagerProxy::invalidate()
275 {
276     m_page->process().removeMessageReceiver(Messages::WebPlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID());
277     m_page = nullptr;
278
279     for (auto& tuple : m_contextMap.values()) {
280         RefPtr<WebPlaybackSessionModelContext> model;
281         RefPtr<PlatformWebPlaybackSessionInterface> interface;
282         std::tie(model, interface) = tuple;
283
284         interface->invalidate();
285     }
286
287     m_contextMap.clear();
288     m_clientCounts.clear();
289 }
290
291 WebPlaybackSessionManagerProxy::ModelInterfaceTuple WebPlaybackSessionManagerProxy::createModelAndInterface(uint64_t contextId)
292 {
293     Ref<WebPlaybackSessionModelContext> model = WebPlaybackSessionModelContext::create(*this, contextId);
294     Ref<PlatformWebPlaybackSessionInterface> interface = PlatformWebPlaybackSessionInterface::create(model);
295
296     return std::make_tuple(WTFMove(model), WTFMove(interface));
297 }
298
299 WebPlaybackSessionManagerProxy::ModelInterfaceTuple& WebPlaybackSessionManagerProxy::ensureModelAndInterface(uint64_t contextId)
300 {
301     auto addResult = m_contextMap.add(contextId, ModelInterfaceTuple());
302     if (addResult.isNewEntry)
303         addResult.iterator->value = createModelAndInterface(contextId);
304     return addResult.iterator->value;
305 }
306
307 WebPlaybackSessionModelContext& WebPlaybackSessionManagerProxy::ensureModel(uint64_t contextId)
308 {
309     return *std::get<0>(ensureModelAndInterface(contextId));
310 }
311
312 PlatformWebPlaybackSessionInterface& WebPlaybackSessionManagerProxy::ensureInterface(uint64_t contextId)
313 {
314     return *std::get<1>(ensureModelAndInterface(contextId));
315 }
316
317 void WebPlaybackSessionManagerProxy::addClientForContext(uint64_t contextId)
318 {
319     m_clientCounts.add(contextId);
320 }
321
322 void WebPlaybackSessionManagerProxy::removeClientForContext(uint64_t contextId)
323 {
324     if (!m_clientCounts.remove(contextId))
325         return;
326
327     ensureInterface(contextId).invalidate();
328     m_contextMap.remove(contextId);
329 }
330
331 #pragma mark Messages from WebPlaybackSessionManager
332
333 void WebPlaybackSessionManagerProxy::setUpPlaybackControlsManagerWithID(uint64_t contextId)
334 {
335 #if PLATFORM(MAC)
336     if (m_controlsManagerContextId == contextId)
337         return;
338
339     if (m_controlsManagerContextId)
340         removeClientForContext(m_controlsManagerContextId);
341
342     m_controlsManagerContextId = contextId;
343     ensureInterface(m_controlsManagerContextId).ensureControlsManager();
344     addClientForContext(m_controlsManagerContextId);
345
346     m_page->videoControlsManagerDidChange();
347 #else
348     UNUSED_PARAM(contextId);
349 #endif
350 }
351
352 void WebPlaybackSessionManagerProxy::clearPlaybackControlsManager()
353 {
354 #if PLATFORM(MAC)
355     if (!m_controlsManagerContextId)
356         return;
357
358     removeClientForContext(m_controlsManagerContextId);
359     m_controlsManagerContextId = 0;
360     m_page->videoControlsManagerDidChange();
361 #endif
362 }
363
364 void WebPlaybackSessionManagerProxy::resetMediaState(uint64_t contextId)
365 {
366     ensureInterface(contextId).resetMediaState();
367 }
368
369 void WebPlaybackSessionManagerProxy::setCurrentTime(uint64_t contextId, double currentTime, double hostTime)
370 {
371     ensureModel(contextId).setCurrentTime(currentTime);
372 }
373
374 void WebPlaybackSessionManagerProxy::setBufferedTime(uint64_t contextId, double bufferedTime)
375 {
376     ensureModel(contextId).setBufferedTime(bufferedTime);
377 }
378
379 void WebPlaybackSessionManagerProxy::setSeekableRangesVector(uint64_t contextId, Vector<std::pair<double, double>> ranges)
380 {
381     Ref<TimeRanges> timeRanges = TimeRanges::create();
382     for (const auto& range : ranges) {
383         ASSERT(isfinite(range.first));
384         ASSERT(isfinite(range.second));
385         ASSERT(range.second >= range.first);
386         timeRanges->add(range.first, range.second);
387     }
388
389     ensureModel(contextId).setSeekableRanges(timeRanges);
390 }
391
392 void WebPlaybackSessionManagerProxy::setCanPlayFastReverse(uint64_t contextId, bool value)
393 {
394     ensureModel(contextId).setCanPlayFastReverse(value);
395 }
396
397 void WebPlaybackSessionManagerProxy::setAudioMediaSelectionOptions(uint64_t contextId, Vector<MediaSelectionOption> options, uint64_t selectedIndex)
398 {
399     ensureModel(contextId).setAudioMediaSelectionOptions(options, selectedIndex);
400 }
401
402 void WebPlaybackSessionManagerProxy::setLegibleMediaSelectionOptions(uint64_t contextId, Vector<MediaSelectionOption> options, uint64_t selectedIndex)
403 {
404     ensureModel(contextId).setLegibleMediaSelectionOptions(options, selectedIndex);
405 }
406
407 void WebPlaybackSessionManagerProxy::setAudioMediaSelectionIndex(uint64_t contextId, uint64_t selectedIndex)
408 {
409     ensureModel(contextId).setAudioMediaSelectionIndex(selectedIndex);
410 }
411
412 void WebPlaybackSessionManagerProxy::setLegibleMediaSelectionIndex(uint64_t contextId, uint64_t selectedIndex)
413 {
414     ensureModel(contextId).setLegibleMediaSelectionIndex(selectedIndex);
415 }
416
417 void WebPlaybackSessionManagerProxy::setExternalPlaybackProperties(uint64_t contextId, bool enabled, uint32_t targetType, String localizedDeviceName)
418 {
419     WebPlaybackSessionModel::ExternalPlaybackTargetType type = static_cast<WebPlaybackSessionModel::ExternalPlaybackTargetType>(targetType);
420     ASSERT(type == WebPlaybackSessionModel::TargetTypeAirPlay || type == WebPlaybackSessionModel::TargetTypeTVOut || type == WebPlaybackSessionModel::TargetTypeNone);
421
422     ensureModel(contextId).setExternalPlayback(enabled, type, localizedDeviceName);
423 }
424
425 void WebPlaybackSessionManagerProxy::setWirelessVideoPlaybackDisabled(uint64_t contextId, bool disabled)
426 {
427     ensureModel(contextId).setWirelessVideoPlaybackDisabled(disabled);
428 }
429
430 void WebPlaybackSessionManagerProxy::setMuted(uint64_t contextId, bool muted)
431 {
432     ensureModel(contextId).setMuted(muted);
433 }
434
435 void WebPlaybackSessionManagerProxy::setDuration(uint64_t contextId, double duration)
436 {
437     ensureModel(contextId).setDuration(duration);
438 }
439
440 void WebPlaybackSessionManagerProxy::setPlaybackStartedTime(uint64_t contextId, double playbackStartedTime)
441 {
442     ensureModel(contextId).setPlaybackStartedTime(playbackStartedTime);
443 }
444
445 void WebPlaybackSessionManagerProxy::setRate(uint64_t contextId, bool isPlaying, double rate)
446 {
447     ensureModel(contextId).setRate(isPlaying, rate);
448 }
449
450
451 void WebPlaybackSessionManagerProxy::handleControlledElementIDResponse(uint64_t contextId, String identifier) const
452 {
453 #if PLATFORM(MAC)
454     if (contextId == m_controlsManagerContextId)
455         m_page->handleControlledElementIDResponse(identifier);
456 #else
457     UNUSED_PARAM(contextId);
458     UNUSED_PARAM(identifier);
459 #endif
460 }
461
462
463 #pragma mark Messages to WebPlaybackSessionManager
464
465 void WebPlaybackSessionManagerProxy::play(uint64_t contextId)
466 {
467     m_page->send(Messages::WebPlaybackSessionManager::Play(contextId), m_page->pageID());
468 }
469
470 void WebPlaybackSessionManagerProxy::pause(uint64_t contextId)
471 {
472     m_page->send(Messages::WebPlaybackSessionManager::Pause(contextId), m_page->pageID());
473 }
474
475 void WebPlaybackSessionManagerProxy::togglePlayState(uint64_t contextId)
476 {
477     m_page->send(Messages::WebPlaybackSessionManager::TogglePlayState(contextId), m_page->pageID());
478 }
479
480 void WebPlaybackSessionManagerProxy::beginScrubbing(uint64_t contextId)
481 {
482     m_page->send(Messages::WebPlaybackSessionManager::BeginScrubbing(contextId), m_page->pageID());
483 }
484
485 void WebPlaybackSessionManagerProxy::endScrubbing(uint64_t contextId)
486 {
487     m_page->send(Messages::WebPlaybackSessionManager::EndScrubbing(contextId), m_page->pageID());
488 }
489
490 void WebPlaybackSessionManagerProxy::seekToTime(uint64_t contextId, double time)
491 {
492     m_page->send(Messages::WebPlaybackSessionManager::SeekToTime(contextId, time), m_page->pageID());
493 }
494
495 void WebPlaybackSessionManagerProxy::fastSeek(uint64_t contextId, double time)
496 {
497     m_page->send(Messages::WebPlaybackSessionManager::FastSeek(contextId, time), m_page->pageID());
498 }
499
500 void WebPlaybackSessionManagerProxy::beginScanningForward(uint64_t contextId)
501 {
502     m_page->send(Messages::WebPlaybackSessionManager::BeginScanningForward(contextId), m_page->pageID());
503 }
504
505 void WebPlaybackSessionManagerProxy::beginScanningBackward(uint64_t contextId)
506 {
507     m_page->send(Messages::WebPlaybackSessionManager::BeginScanningBackward(contextId), m_page->pageID());
508 }
509
510 void WebPlaybackSessionManagerProxy::endScanning(uint64_t contextId)
511 {
512     m_page->send(Messages::WebPlaybackSessionManager::EndScanning(contextId), m_page->pageID());
513 }
514
515 void WebPlaybackSessionManagerProxy::selectAudioMediaOption(uint64_t contextId, uint64_t index)
516 {
517     m_page->send(Messages::WebPlaybackSessionManager::SelectAudioMediaOption(contextId, index), m_page->pageID());
518 }
519
520 void WebPlaybackSessionManagerProxy::selectLegibleMediaOption(uint64_t contextId, uint64_t index)
521 {
522     m_page->send(Messages::WebPlaybackSessionManager::SelectLegibleMediaOption(contextId, index), m_page->pageID());
523 }
524
525 void WebPlaybackSessionManagerProxy::togglePictureInPicture(uint64_t contextId)
526 {
527     m_page->send(Messages::WebPlaybackSessionManager::TogglePictureInPicture(contextId), m_page->pageID());
528 }
529
530 void WebPlaybackSessionManagerProxy::toggleMuted(uint64_t contextId)
531 {
532     m_page->send(Messages::WebPlaybackSessionManager::ToggleMuted(contextId), m_page->pageID());
533 }
534
535 void WebPlaybackSessionManagerProxy::requestControlledElementID()
536 {
537     if (m_controlsManagerContextId)
538         m_page->send(Messages::WebPlaybackSessionManager::HandleControlledElementIDRequest(m_controlsManagerContextId), m_page->pageID());
539 }
540
541 PlatformWebPlaybackSessionInterface* WebPlaybackSessionManagerProxy::controlsManagerInterface()
542 {
543     if (!m_controlsManagerContextId)
544         return nullptr;
545     
546     auto& interface = ensureInterface(m_controlsManagerContextId);
547     return &interface;
548 }
549
550 } // namespace WebKit
551
552 #endif // PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))