Remove dead code: resetMediaState.
[WebKit-https.git] / Source / WebKit / WebProcess / cocoa / PlaybackSessionManager.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 "PlaybackSessionManager.h"
28
29 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
30
31 #import "Attachment.h"
32 #import "PlaybackSessionManagerMessages.h"
33 #import "PlaybackSessionManagerProxyMessages.h"
34 #import "WebCoreArgumentCoders.h"
35 #import "WebPage.h"
36 #import "WebProcess.h"
37 #import <WebCore/Color.h>
38 #import <WebCore/Event.h>
39 #import <WebCore/EventNames.h>
40 #import <WebCore/HTMLMediaElement.h>
41 #import <WebCore/Settings.h>
42 #import <WebCore/TimeRanges.h>
43 #import <WebCore/UserGestureIndicator.h>
44 #import <mach/mach_port.h>
45
46 namespace WebKit {
47 using namespace WebCore;
48
49 static uint64_t nextContextId()
50 {
51     static uint64_t contextId = 0;
52     return ++contextId;
53 }
54
55 #pragma mark - PlaybackSessionInterfaceContext
56
57 PlaybackSessionInterfaceContext::PlaybackSessionInterfaceContext(PlaybackSessionManager& manager, uint64_t contextId)
58     : m_manager(&manager)
59     , m_contextId(contextId)
60 {
61 }
62
63 PlaybackSessionInterfaceContext::~PlaybackSessionInterfaceContext()
64 {
65 }
66
67 void PlaybackSessionInterfaceContext::durationChanged(double duration)
68 {
69     if (m_manager)
70         m_manager->durationChanged(m_contextId, duration);
71 }
72
73 void PlaybackSessionInterfaceContext::currentTimeChanged(double currentTime, double anchorTime)
74 {
75     if (m_manager)
76         m_manager->currentTimeChanged(m_contextId, currentTime, anchorTime);
77 }
78
79 void PlaybackSessionInterfaceContext::bufferedTimeChanged(double bufferedTime)
80 {
81     if (m_manager)
82         m_manager->bufferedTimeChanged(m_contextId, bufferedTime);
83 }
84
85 void PlaybackSessionInterfaceContext::rateChanged(bool isPlaying, float playbackRate)
86 {
87     if (m_manager)
88         m_manager->rateChanged(m_contextId, isPlaying, playbackRate);
89 }
90
91 void PlaybackSessionInterfaceContext::playbackStartedTimeChanged(double playbackStartedTime)
92 {
93     if (m_manager)
94         m_manager->playbackStartedTimeChanged(m_contextId, playbackStartedTime);
95 }
96
97 void PlaybackSessionInterfaceContext::seekableRangesChanged(const WebCore::TimeRanges& ranges, double lastModifiedTime, double liveUpdateInterval)
98 {
99     if (m_manager)
100         m_manager->seekableRangesChanged(m_contextId, ranges, lastModifiedTime, liveUpdateInterval);
101 }
102
103 void PlaybackSessionInterfaceContext::canPlayFastReverseChanged(bool value)
104 {
105     if (m_manager)
106         m_manager->canPlayFastReverseChanged(m_contextId, value);
107 }
108
109 void PlaybackSessionInterfaceContext::audioMediaSelectionOptionsChanged(const Vector<MediaSelectionOption>& options, uint64_t selectedIndex)
110 {
111     if (m_manager)
112         m_manager->audioMediaSelectionOptionsChanged(m_contextId, options, selectedIndex);
113 }
114
115 void PlaybackSessionInterfaceContext::legibleMediaSelectionOptionsChanged(const Vector<MediaSelectionOption>& options, uint64_t selectedIndex)
116 {
117     if (m_manager)
118         m_manager->legibleMediaSelectionOptionsChanged(m_contextId, options, selectedIndex);
119 }
120
121 void PlaybackSessionInterfaceContext::audioMediaSelectionIndexChanged(uint64_t selectedIndex)
122 {
123     if (m_manager)
124         m_manager->audioMediaSelectionIndexChanged(m_contextId, selectedIndex);
125 }
126
127 void PlaybackSessionInterfaceContext::legibleMediaSelectionIndexChanged(uint64_t selectedIndex)
128 {
129     if (m_manager)
130         m_manager->legibleMediaSelectionIndexChanged(m_contextId, selectedIndex);
131 }
132
133 void PlaybackSessionInterfaceContext::externalPlaybackChanged(bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType type, const String& localizedDeviceName)
134 {
135     if (m_manager)
136         m_manager->externalPlaybackChanged(m_contextId, enabled, type, localizedDeviceName);
137 }
138
139 void PlaybackSessionInterfaceContext::wirelessVideoPlaybackDisabledChanged(bool disabled)
140 {
141     if (m_manager)
142         m_manager->wirelessVideoPlaybackDisabledChanged(m_contextId, disabled);
143 }
144
145 void PlaybackSessionInterfaceContext::mutedChanged(bool muted)
146 {
147     if (m_manager)
148         m_manager->mutedChanged(m_contextId, muted);
149 }
150
151 void PlaybackSessionInterfaceContext::isPictureInPictureSupportedChanged(bool supported)
152 {
153     if (m_manager)
154         m_manager->isPictureInPictureSupportedChanged(m_contextId, supported);
155 }
156
157 void PlaybackSessionInterfaceContext::volumeChanged(double volume)
158 {
159     if (m_manager)
160         m_manager->volumeChanged(m_contextId, volume);
161 }
162
163 #pragma mark - PlaybackSessionManager
164
165 Ref<PlaybackSessionManager> PlaybackSessionManager::create(WebPage& page)
166 {
167     return adoptRef(*new PlaybackSessionManager(page));
168 }
169
170 PlaybackSessionManager::PlaybackSessionManager(WebPage& page)
171     : m_page(&page)
172 {
173     WebProcess::singleton().addMessageReceiver(Messages::PlaybackSessionManager::messageReceiverName(), page.pageID(), *this);
174 }
175
176 PlaybackSessionManager::~PlaybackSessionManager()
177 {
178     for (auto& tuple : m_contextMap.values()) {
179         RefPtr<PlaybackSessionModelMediaElement> model;
180         RefPtr<PlaybackSessionInterfaceContext> interface;
181         std::tie(model, interface) = tuple;
182         model->removeClient(*interface);
183         model->setMediaElement(nullptr);
184
185         interface->invalidate();
186     }
187
188     m_contextMap.clear();
189     m_mediaElements.clear();
190     m_clientCounts.clear();
191
192     if (m_page)
193         WebProcess::singleton().removeMessageReceiver(Messages::PlaybackSessionManager::messageReceiverName(), m_page->pageID());
194 }
195
196 void PlaybackSessionManager::invalidate()
197 {
198     ASSERT(m_page);
199     WebProcess::singleton().removeMessageReceiver(Messages::PlaybackSessionManager::messageReceiverName(), m_page->pageID());
200     m_page = nullptr;
201 }
202
203 PlaybackSessionManager::ModelInterfaceTuple PlaybackSessionManager::createModelAndInterface(uint64_t contextId)
204 {
205     RefPtr<PlaybackSessionModelMediaElement> model = PlaybackSessionModelMediaElement::create();
206     RefPtr<PlaybackSessionInterfaceContext> interface = PlaybackSessionInterfaceContext::create(*this, contextId);
207     model->addClient(*interface);
208
209     return std::make_tuple(WTFMove(model), WTFMove(interface));
210 }
211
212 PlaybackSessionManager::ModelInterfaceTuple& PlaybackSessionManager::ensureModelAndInterface(uint64_t contextId)
213 {
214     auto addResult = m_contextMap.add(contextId, ModelInterfaceTuple());
215     if (addResult.isNewEntry)
216         addResult.iterator->value = createModelAndInterface(contextId);
217     return addResult.iterator->value;
218 }
219
220 WebCore::PlaybackSessionModelMediaElement& PlaybackSessionManager::ensureModel(uint64_t contextId)
221 {
222     return *std::get<0>(ensureModelAndInterface(contextId));
223 }
224
225 PlaybackSessionInterfaceContext& PlaybackSessionManager::ensureInterface(uint64_t contextId)
226 {
227     return *std::get<1>(ensureModelAndInterface(contextId));
228 }
229
230 void PlaybackSessionManager::removeContext(uint64_t contextId)
231 {
232     RefPtr<PlaybackSessionModelMediaElement> model;
233     RefPtr<PlaybackSessionInterfaceContext> interface;
234     std::tie(model, interface) = ensureModelAndInterface(contextId);
235
236     RefPtr<HTMLMediaElement> mediaElement = model->mediaElement();
237     model->setMediaElement(nullptr);
238     model->removeClient(*interface);
239     interface->invalidate();
240     m_mediaElements.remove(mediaElement.get());
241     m_contextMap.remove(contextId);
242 }
243
244 void PlaybackSessionManager::addClientForContext(uint64_t contextId)
245 {
246     m_clientCounts.add(contextId);
247 }
248
249 void PlaybackSessionManager::removeClientForContext(uint64_t contextId)
250 {
251     ASSERT(m_clientCounts.contains(contextId));
252     if (m_clientCounts.remove(contextId))
253         removeContext(contextId);
254 }
255
256 void PlaybackSessionManager::setUpPlaybackControlsManager(WebCore::HTMLMediaElement& mediaElement)
257 {
258     auto foundIterator = m_mediaElements.find(&mediaElement);
259     if (foundIterator != m_mediaElements.end()) {
260         uint64_t contextId = foundIterator->value;
261         if (m_controlsManagerContextId == contextId)
262             return;
263
264         auto previousContextId = m_controlsManagerContextId;
265         m_controlsManagerContextId = contextId;
266         if (previousContextId)
267             removeClientForContext(previousContextId);
268     } else {
269         auto contextId = m_mediaElements.ensure(&mediaElement, [&] { return nextContextId(); }).iterator->value;
270
271         auto previousContextId = m_controlsManagerContextId;
272         m_controlsManagerContextId = contextId;
273         if (previousContextId)
274             removeClientForContext(previousContextId);
275
276         ensureModel(contextId).setMediaElement(&mediaElement);
277     }
278
279     addClientForContext(m_controlsManagerContextId);
280
281     m_page->videoControlsManagerDidChange();
282     m_page->send(Messages::PlaybackSessionManagerProxy::SetUpPlaybackControlsManagerWithID(m_controlsManagerContextId), m_page->pageID());
283 }
284
285 void PlaybackSessionManager::clearPlaybackControlsManager()
286 {
287     if (!m_controlsManagerContextId)
288         return;
289
290     removeClientForContext(m_controlsManagerContextId);
291     m_controlsManagerContextId = 0;
292
293     m_page->videoControlsManagerDidChange();
294     m_page->send(Messages::PlaybackSessionManagerProxy::ClearPlaybackControlsManager(), m_page->pageID());
295 }
296
297 uint64_t PlaybackSessionManager::contextIdForMediaElement(WebCore::HTMLMediaElement& mediaElement)
298 {
299     auto addResult = m_mediaElements.ensure(&mediaElement, [&] { return nextContextId(); });
300     uint64_t contextId = addResult.iterator->value;
301     ensureModel(contextId).setMediaElement(&mediaElement);
302     return contextId;
303 }
304
305 WebCore::HTMLMediaElement* PlaybackSessionManager::currentPlaybackControlsElement() const
306 {
307     if (!m_controlsManagerContextId)
308         return nullptr;
309
310     auto iter = m_contextMap.find(m_controlsManagerContextId);
311     if (iter == m_contextMap.end())
312         return nullptr;
313
314     return std::get<0>(iter->value)->mediaElement();
315 }
316
317 #pragma mark Interface to PlaybackSessionInterfaceContext:
318
319 void PlaybackSessionManager::durationChanged(uint64_t contextId, double duration)
320 {
321     m_page->send(Messages::PlaybackSessionManagerProxy::DurationChanged(contextId, duration), m_page->pageID());
322 }
323
324 void PlaybackSessionManager::currentTimeChanged(uint64_t contextId, double currentTime, double anchorTime)
325 {
326     m_page->send(Messages::PlaybackSessionManagerProxy::CurrentTimeChanged(contextId, currentTime, anchorTime), m_page->pageID());
327 }
328
329 void PlaybackSessionManager::bufferedTimeChanged(uint64_t contextId, double bufferedTime)
330 {
331     m_page->send(Messages::PlaybackSessionManagerProxy::BufferedTimeChanged(contextId, bufferedTime), m_page->pageID());
332 }
333
334 void PlaybackSessionManager::playbackStartedTimeChanged(uint64_t contextId, double playbackStartedTime)
335 {
336     m_page->send(Messages::PlaybackSessionManagerProxy::PlaybackStartedTimeChanged(contextId, playbackStartedTime), m_page->pageID());
337 }
338
339 void PlaybackSessionManager::rateChanged(uint64_t contextId, bool isPlaying, float playbackRate)
340 {
341     m_page->send(Messages::PlaybackSessionManagerProxy::RateChanged(contextId, isPlaying, playbackRate), m_page->pageID());
342 }
343
344 void PlaybackSessionManager::seekableRangesChanged(uint64_t contextId, const WebCore::TimeRanges& timeRanges, double lastModifiedTime, double liveUpdateInterval)
345 {
346     Vector<std::pair<double, double>> rangesVector;
347     for (unsigned i = 0; i < timeRanges.length(); i++) {
348         double start = timeRanges.ranges().start(i).toDouble();
349         double end = timeRanges.ranges().end(i).toDouble();
350         rangesVector.append({ start, end });
351     }
352     m_page->send(Messages::PlaybackSessionManagerProxy::SeekableRangesVectorChanged(contextId, WTFMove(rangesVector), lastModifiedTime, liveUpdateInterval), m_page->pageID());
353 }
354
355 void PlaybackSessionManager::canPlayFastReverseChanged(uint64_t contextId, bool value)
356 {
357     m_page->send(Messages::PlaybackSessionManagerProxy::CanPlayFastReverseChanged(contextId, value), m_page->pageID());
358 }
359
360 void PlaybackSessionManager::audioMediaSelectionOptionsChanged(uint64_t contextId, const Vector<MediaSelectionOption>& options, uint64_t selectedIndex)
361 {
362     m_page->send(Messages::PlaybackSessionManagerProxy::AudioMediaSelectionOptionsChanged(contextId, options, selectedIndex), m_page->pageID());
363 }
364
365 void PlaybackSessionManager::legibleMediaSelectionOptionsChanged(uint64_t contextId, const Vector<MediaSelectionOption>& options, uint64_t selectedIndex)
366 {
367     m_page->send(Messages::PlaybackSessionManagerProxy::LegibleMediaSelectionOptionsChanged(contextId, options, selectedIndex), m_page->pageID());
368 }
369
370 void PlaybackSessionManager::externalPlaybackChanged(uint64_t contextId, bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType targetType, String localizedDeviceName)
371 {
372     m_page->send(Messages::PlaybackSessionManagerProxy::ExternalPlaybackPropertiesChanged(contextId, enabled, static_cast<uint32_t>(targetType), localizedDeviceName), m_page->pageID());
373 }
374
375 void PlaybackSessionManager::audioMediaSelectionIndexChanged(uint64_t contextId, uint64_t selectedIndex)
376 {
377     m_page->send(Messages::PlaybackSessionManagerProxy::AudioMediaSelectionIndexChanged(contextId, selectedIndex), m_page->pageID());
378 }
379
380 void PlaybackSessionManager::legibleMediaSelectionIndexChanged(uint64_t contextId, uint64_t selectedIndex)
381 {
382     m_page->send(Messages::PlaybackSessionManagerProxy::LegibleMediaSelectionIndexChanged(contextId, selectedIndex), m_page->pageID());
383 }
384
385 void PlaybackSessionManager::wirelessVideoPlaybackDisabledChanged(uint64_t contextId, bool disabled)
386 {
387     m_page->send(Messages::PlaybackSessionManagerProxy::WirelessVideoPlaybackDisabledChanged(contextId, disabled));
388 }
389
390 void PlaybackSessionManager::mutedChanged(uint64_t contextId, bool muted)
391 {
392     m_page->send(Messages::PlaybackSessionManagerProxy::MutedChanged(contextId, muted));
393 }
394
395 void PlaybackSessionManager::volumeChanged(uint64_t contextId, double volume)
396 {
397     m_page->send(Messages::PlaybackSessionManagerProxy::VolumeChanged(contextId, volume));
398 }
399
400 void PlaybackSessionManager::isPictureInPictureSupportedChanged(uint64_t contextId, bool supported)
401 {
402     m_page->send(Messages::PlaybackSessionManagerProxy::PictureInPictureSupportedChanged(contextId, supported));
403 }
404
405 #pragma mark Messages from PlaybackSessionManagerProxy:
406
407 void PlaybackSessionManager::play(uint64_t contextId)
408 {
409     UserGestureIndicator indicator(ProcessingUserGesture);
410     ensureModel(contextId).play();
411 }
412
413 void PlaybackSessionManager::pause(uint64_t contextId)
414 {
415     UserGestureIndicator indicator(ProcessingUserGesture);
416     ensureModel(contextId).pause();
417 }
418
419 void PlaybackSessionManager::togglePlayState(uint64_t contextId)
420 {
421     UserGestureIndicator indicator(ProcessingUserGesture);
422     ensureModel(contextId).togglePlayState();
423 }
424
425 void PlaybackSessionManager::beginScrubbing(uint64_t contextId)
426 {
427     UserGestureIndicator indicator(ProcessingUserGesture);
428     ensureModel(contextId).beginScrubbing();
429 }
430
431 void PlaybackSessionManager::endScrubbing(uint64_t contextId)
432 {
433     UserGestureIndicator indicator(ProcessingUserGesture);
434     ensureModel(contextId).endScrubbing();
435 }
436
437 void PlaybackSessionManager::seekToTime(uint64_t contextId, double time, double toleranceBefore, double toleranceAfter)
438 {
439     UserGestureIndicator indicator(ProcessingUserGesture);
440     ensureModel(contextId).seekToTime(time, toleranceBefore, toleranceAfter);
441 }
442
443 void PlaybackSessionManager::fastSeek(uint64_t contextId, double time)
444 {
445     UserGestureIndicator indicator(ProcessingUserGesture);
446     ensureModel(contextId).fastSeek(time);
447 }
448
449 void PlaybackSessionManager::beginScanningForward(uint64_t contextId)
450 {
451     UserGestureIndicator indicator(ProcessingUserGesture);
452     ensureModel(contextId).beginScanningForward();
453 }
454
455 void PlaybackSessionManager::beginScanningBackward(uint64_t contextId)
456 {
457     UserGestureIndicator indicator(ProcessingUserGesture);
458     ensureModel(contextId).beginScanningBackward();
459 }
460
461 void PlaybackSessionManager::endScanning(uint64_t contextId)
462 {
463     UserGestureIndicator indicator(ProcessingUserGesture);
464     ensureModel(contextId).endScanning();
465 }
466
467 void PlaybackSessionManager::selectAudioMediaOption(uint64_t contextId, uint64_t index)
468 {
469     UserGestureIndicator indicator(ProcessingUserGesture);
470     ensureModel(contextId).selectAudioMediaOption(index);
471 }
472
473 void PlaybackSessionManager::selectLegibleMediaOption(uint64_t contextId, uint64_t index)
474 {
475     UserGestureIndicator indicator(ProcessingUserGesture);
476     ensureModel(contextId).selectLegibleMediaOption(index);
477 }
478
479 void PlaybackSessionManager::handleControlledElementIDRequest(uint64_t contextId)
480 {
481     auto element = ensureModel(contextId).mediaElement();
482     if (element)
483         m_page->send(Messages::PlaybackSessionManagerProxy::HandleControlledElementIDResponse(contextId, element->getIdAttribute()));
484 }
485
486 void PlaybackSessionManager::togglePictureInPicture(uint64_t contextId)
487 {
488     UserGestureIndicator indicator(ProcessingUserGesture);
489     ensureModel(contextId).togglePictureInPicture();
490 }
491
492 void PlaybackSessionManager::toggleMuted(uint64_t contextId)
493 {
494     UserGestureIndicator indicator(ProcessingUserGesture);
495     ensureModel(contextId).toggleMuted();
496 }
497
498 void PlaybackSessionManager::setMuted(uint64_t contextId, bool muted)
499 {
500     UserGestureIndicator indicator(ProcessingUserGesture);
501     ensureModel(contextId).setMuted(muted);
502 }
503
504 void PlaybackSessionManager::setVolume(uint64_t contextId, double volume)
505 {
506     UserGestureIndicator indicator(ProcessingUserGesture);
507     ensureModel(contextId).setVolume(volume);
508 }
509
510 void PlaybackSessionManager::setPlayingOnSecondScreen(uint64_t contextId, bool value)
511 {
512     UserGestureIndicator indicator(ProcessingUserGesture);
513     ensureModel(contextId).setPlayingOnSecondScreen(value);
514 }
515
516 } // namespace WebKit
517
518 #endif // PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))