/* * Copyright (C) 2021 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "GroupActivitiesSessionNotifier.h" #if ENABLE(MEDIA_SESSION_COORDINATOR) && HAVE(GROUP_ACTIVITIES) #import "GroupActivitiesCoordinator.h" #import "WKGroupSession.h" #import "WebPageProxy.h" #import "WebKitSwiftSoftLink.h" namespace WebKit { using namespace PAL; using namespace WebCore; GroupActivitiesSessionNotifier& GroupActivitiesSessionNotifier::sharedNotifier() { static NeverDestroyed notifier; return notifier; } GroupActivitiesSessionNotifier::GroupActivitiesSessionNotifier() : m_sessionObserver(adoptNS([allocWKGroupSessionObserverInstance() init])) , m_stateChangeObserver([this] (auto& session, auto state) { sessionStateChanged(session, state); }) { m_sessionObserver.get().newSessionCallback = [this, weakThis = WeakPtr { *this }] (WKGroupSession *groupSession) { if (!weakThis) return; auto session = GroupActivitiesSession::create(groupSession); session->addStateChangeObserver(m_stateChangeObserver); for (auto& page : copyToVector(m_webPages)) { if (page->mainFrame() && page->mainFrame()->url() == session->fallbackURL()) { auto coordinator = GroupActivitiesCoordinator::create(session); page->createMediaSessionCoordinator(WTFMove(coordinator), [] (bool) { }); return; } } auto result = m_sessions.add(session->fallbackURL(), session.copyRef()); ASSERT_UNUSED(result, result.isNewEntry); [[NSWorkspace sharedWorkspace] openURL:session->fallbackURL()]; }; } void GroupActivitiesSessionNotifier::sessionStateChanged(const GroupActivitiesSession& session, GroupActivitiesSession::State state) { if (state == GroupActivitiesSession::State::Invalidated) m_sessions.remove(session.fallbackURL()); }; void GroupActivitiesSessionNotifier::addWebPage(WebPageProxy& webPage) { ASSERT(!m_webPages.contains(webPage)); m_webPages.add(webPage); auto frame = webPage.mainFrame(); if (!frame) return; auto session = takeSessionForURL(frame->url()); if (!session) return; auto coordinator = GroupActivitiesCoordinator::create(*session); webPage.createMediaSessionCoordinator(WTFMove(coordinator), [] (bool) { }); } void GroupActivitiesSessionNotifier::removeWebPage(WebPageProxy& webPage) { ASSERT(m_webPages.contains(webPage)); m_webPages.remove(webPage); } void GroupActivitiesSessionNotifier::webPageURLChanged(WebPageProxy& webPage) { ASSERT(m_webPages.contains(webPage)); if (!m_webPages.contains(webPage)) return; auto frame = webPage.mainFrame(); if (!frame) return; auto session = takeSessionForURL(frame->url()); if (!session) return; auto coordinator = GroupActivitiesCoordinator::create(*session); webPage.createMediaSessionCoordinator(WTFMove(coordinator), [] (bool) { }); } bool GroupActivitiesSessionNotifier::hasSessionForURL(const URL& url) { return m_sessions.contains(url); } RefPtr GroupActivitiesSessionNotifier::takeSessionForURL(const URL& url) { return m_sessions.take(url); } } #endif