[Mac] Add a mock AppleTV device for testing
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Nov 2015 06:24:34 +0000 (06:24 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Nov 2015 06:24:34 +0000 (06:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148912
<rdar://problem/22596272>

Reviewed by Tim Horton.

Source/WebCore:

No new tests, updated media/controls/airplay-picker.html.

* Modules/mediasession/WebMediaSessionManager.cpp:
(WebCore::WebMediaSessionManager::setMockMediaPlaybackTargetPickerEnabled): New, enable or disable
  the mock picker.
(WebCore::WebMediaSessionManager::setMockMediaPlaybackTargetPickerState): New, set mock picker state.
(WebCore::WebMediaSessionManager::mockPicker): New.
(WebCore::WebMediaSessionManager::targetPicker): Return the platform or mock picker, as per settings.
(WebCore::webMediaSessionManagerOverride): Deleted.
(WebCore::WebMediaSessionManager::shared): Deleted.
(WebCore::WebMediaSessionManager::setWebMediaSessionManagerOverride): Deleted.
* Modules/mediasession/WebMediaSessionManager.h:

* WebCore.xcodeproj/project.pbxproj: Add MediaPlaybackTargetPickerMock.* and MediaPlaybackTargetMock.*.

* page/ChromeClient.h: add setMockMediaPlaybackTargetPickerEnabled and setMockMediaPlaybackTargetPickerState.

* page/Page.cpp:
(WebCore::Page::playbackTargetPickerClientStateDidChange):
(WebCore::Page::setMockMediaPlaybackTargetPickerEnabled): New.
(WebCore::Page::setMockMediaPlaybackTargetPickerState): New.
(WebCore::Page::setPlaybackTarget):
* page/Page.h:

* platform/graphics/MediaPlaybackTarget.h:
(WebCore::noMediaPlaybackTargetContext):
(WebCore::MediaPlaybackTarget::~MediaPlaybackTarget):
(WebCore::MediaPlaybackTarget::deviceName):
(WebCore::MediaPlaybackTarget::MediaPlaybackTarget):

* platform/graphics/MediaPlaybackTargetContext.h: Make a class instead of a struct.
(WebCore::MediaPlaybackTargetContext::MediaPlaybackTargetContext):
(WebCore::MediaPlaybackTargetContext::type):
(WebCore::MediaPlaybackTargetContext::mockDeviceName):
(WebCore::MediaPlaybackTargetContext::mockState):
(WebCore::MediaPlaybackTargetContext::avOutputContext):
(WebCore::MediaPlaybackTargetContext::encodingRequiresPlatformData):

* platform/graphics/MediaPlaybackTargetPicker.cpp: Move much of the code from MediaPlaybackTargetMac.mm
  here so it can be the base class.
(WebCore::MediaPlaybackTargetPicker::MediaPlaybackTargetPicker):
(WebCore::MediaPlaybackTargetPicker::~MediaPlaybackTargetPicker):
(WebCore::MediaPlaybackTargetPicker::pendingActionTimerFired):
(WebCore::MediaPlaybackTargetPicker::addPendingAction):
(WebCore::MediaPlaybackTargetPicker::showPlaybackTargetPicker):
* platform/graphics/MediaPlaybackTargetPicker.h:
(WebCore::MediaPlaybackTargetPicker::availableDevicesDidChange):
(WebCore::MediaPlaybackTargetPicker::currentDeviceDidChange):
(WebCore::MediaPlaybackTargetPicker::client):
(WebCore::MediaPlaybackTargetPicker::setClient):

* platform/graphics/avfoundation/MediaPlaybackTargetMac.h:
(WebCore::MediaPlaybackTargetMac::outputContext):
(WebCore::MediaPlaybackTargetMac::targetType): Deleted.
* platform/graphics/avfoundation/MediaPlaybackTargetMac.mm:
(WebCore::MediaPlaybackTargetMac::targetContext):
(WebCore::MediaPlaybackTargetMac::hasActiveRoute):
(WebCore::MediaPlaybackTargetMac::deviceName):

* platform/graphics/avfoundation/WebMediaSessionManagerMac.cpp:
(WebCore::WebMediaSessionManager::shared): Renamed from platformManager.
(WebCore::WebMediaSessionManagerMac::platformPicker): Renamed from targetPicker.
(WebCore::WebMediaSessionManager::platformManager): Deleted.
(WebCore::WebMediaSessionManagerMac::targetPicker): Deleted.
* platform/graphics/avfoundation/WebMediaSessionManagerMac.h:

* platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h:
* platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm:
(WebCore::MediaPlaybackTargetPickerMac::MediaPlaybackTargetPickerMac):
(WebCore::MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac):
(WebCore::MediaPlaybackTargetPickerMac::externalOutputDeviceAvailable):
(WebCore::MediaPlaybackTargetPickerMac::playbackTarget):
(WebCore::MediaPlaybackTargetPickerMac::devicePicker):
(WebCore::MediaPlaybackTargetPickerMac::showPlaybackTargetPicker):
(WebCore::MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMac::pendingActionTimerFired): Deleted.
(WebCore::MediaPlaybackTargetPickerMac::availableDevicesDidChange): Deleted.
(WebCore::MediaPlaybackTargetPickerMac::addPendingAction): Deleted.
(WebCore::MediaPlaybackTargetPickerMac::currentDeviceDidChange): Deleted.

* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless): Add support for
  mock target.
(WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessPlaybackTargetName): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationObjC::setShouldPlayToPlaybackTarget): Ditto.

* platform/mock/MediaPlaybackTargetMock.cpp: Added.
(WebCore::MediaPlaybackTargetMock::create):
(WebCore::MediaPlaybackTargetMock::MediaPlaybackTargetMock):
(WebCore::MediaPlaybackTargetMock::~MediaPlaybackTargetMock):
(WebCore::MediaPlaybackTargetMock::targetContext):
(WebCore::toMediaPlaybackTargetMock):
* platform/mock/MediaPlaybackTargetMock.h: Added.

* platform/mock/MediaPlaybackTargetPickerMock.cpp: Added.
(WebCore::MediaPlaybackTargetPickerMock::create):
(WebCore::MediaPlaybackTargetPickerMock::MediaPlaybackTargetPickerMock):
(WebCore::MediaPlaybackTargetPickerMock::~MediaPlaybackTargetPickerMock):
(WebCore::MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable):
(WebCore::MediaPlaybackTargetPickerMock::playbackTarget):
(WebCore::MediaPlaybackTargetPickerMock::timerFired):
(WebCore::MediaPlaybackTargetPickerMock::showPlaybackTargetPicker):
(WebCore::MediaPlaybackTargetPickerMock::startingMonitoringPlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMock::stopMonitoringPlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMock::invalidatePlaybackTargets):
(WebCore::MediaPlaybackTargetPickerMock::setState):
* platform/mock/MediaPlaybackTargetPickerMock.h: Added.

* testing/Internals.cpp:
(WebCore::Internals::Internals):
(WebCore::Internals::setMockMediaPlaybackTargetPickerEnabled):
(WebCore::Internals::setMockMediaPlaybackTargetPickerState):
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit/mac:

* WebCoreSupport/WebChromeClient.h:
* WebCoreSupport/WebChromeClient.mm:
(WebChromeClient::setMockMediaPlaybackTargetPickerEnabled): New.
(WebChromeClient::setMockMediaPlaybackTargetPickerState): Ditto.

* WebView/WebMediaPlaybackTargetPicker.h:
* WebView/WebMediaPlaybackTargetPicker.mm:
(WebMediaPlaybackTargetPicker::setMockMediaPlaybackTargetPickerEnabled): New.
(WebMediaPlaybackTargetPicker::setMockMediaPlaybackTargetPickerState): Ditto.

* WebView/WebView.mm:
(-[WebView _setMockMediaPlaybackTargetPickerEnabled:]): New.
(-[WebView _setMockMediaPlaybackTargetPickerName:state:]): Ditto.
* WebView/WebViewInternal.h:

Source/WebKit2:

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<MediaPlaybackTargetContext>::encode): Update for MediaPlaybackTargetContext changes.
(IPC::ArgumentCoder<MediaPlaybackTargetContext>::decode): Ditto.
* Shared/WebCoreArgumentCoders.h:

* Shared/mac/WebCoreArgumentCodersMac.mm:
(IPC::ArgumentCoder<MediaPlaybackTargetContext>::encodePlatformData): Ditto.
(IPC::ArgumentCoder<MediaPlaybackTargetContext>::decodePlatformData): Ditto.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::setMockMediaPlaybackTargetPickerEnabled): New.
(WebKit::WebPageProxy::setMockMediaPlaybackTargetPickerState): Ditto.
* UIProcess/WebPageProxy.h:

* UIProcess/WebPageProxy.messages.in: Add SetMockMediaPlaybackTargetPickerEnabled and
  SetMockMediaPlaybackTargetPickerState.

* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::setMockMediaPlaybackTargetPickerEnabled): New.
(WebKit::WebChromeClient::setMockMediaPlaybackTargetPickerState): Ditto.
* WebProcess/WebCoreSupport/WebChromeClient.h:

* WebProcess/WebPage/WebPage.h: MediaPlaybackTargetContext is a class, not a struct.

* WebProcess/WebPage/WebPage.messages.in: Ditto.

* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::playbackTargetSelected): Support mock target.

LayoutTests:

* media/controls/airplay-picker-expected.txt: Updated.
* media/controls/airplay-picker.html: Test button state when there is a device available.

* media/controls/controls-test-helpers.js:
(ControlsTest.prototype.stateForControlsElement): Add an optional parameter to force the flushed
  state to be flushed.
(ControlsTest.prototype.contains): New.
(ControlsTest.prototype.doesNotContain): Ditto.

* platform/mac/TestExpectations: Skipped new tests on older versions of OS X.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@192200 268f45cc-cd09-0410-ab3c-d52691b4dbfc

50 files changed:
LayoutTests/ChangeLog
LayoutTests/media/controls/airplay-picker-expected.txt
LayoutTests/media/controls/airplay-picker.html
LayoutTests/media/controls/controls-test-helpers.js
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp
Source/WebCore/Modules/mediasession/WebMediaSessionManager.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/page/ChromeClient.h
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/platform/graphics/MediaPlaybackTarget.h
Source/WebCore/platform/graphics/MediaPlaybackTargetContext.h
Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.cpp
Source/WebCore/platform/graphics/MediaPlaybackTargetPicker.h
Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetMac.h
Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetMac.mm
Source/WebCore/platform/graphics/avfoundation/WebMediaSessionManagerMac.cpp
Source/WebCore/platform/graphics/avfoundation/WebMediaSessionManagerMac.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
Source/WebCore/platform/mock/MediaPlaybackTargetMock.cpp [new file with mode: 0644]
Source/WebCore/platform/mock/MediaPlaybackTargetMock.h [new file with mode: 0644]
Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp [new file with mode: 0644]
Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h [new file with mode: 0644]
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/WebChromeClient.h
Source/WebKit/mac/WebCoreSupport/WebChromeClient.mm
Source/WebKit/mac/WebView/WebMediaPlaybackTargetPicker.h
Source/WebKit/mac/WebView/WebMediaPlaybackTargetPicker.mm
Source/WebKit/mac/WebView/WebView.mm
Source/WebKit/mac/WebView/WebViewInternal.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/Shared/mac/WebCoreArgumentCodersMac.mm
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm

index dfc2b22..339098d 100644 (file)
@@ -1,3 +1,22 @@
+2015-11-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] Add a mock AppleTV device for testing
+        https://bugs.webkit.org/show_bug.cgi?id=148912
+        <rdar://problem/22596272>
+
+        Reviewed by Tim Horton.
+
+        * media/controls/airplay-picker-expected.txt: Updated.
+        * media/controls/airplay-picker.html: Test button state when there is a device available.
+
+        * media/controls/controls-test-helpers.js:
+        (ControlsTest.prototype.stateForControlsElement): Add an optional parameter to force the flushed
+          state to be flushed.
+        (ControlsTest.prototype.contains): New.
+        (ControlsTest.prototype.doesNotContain): Ditto.
+
+        * platform/mac/TestExpectations: Skipped new tests on older versions of OS X.
+
 2015-11-09  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Sometimes unable to scroll fixed div when the body is scrollable
index 7392a71..7db67e8 100644 (file)
@@ -1,4 +1,4 @@
-This tests for the wireless device picker icon.
+This tests the wireless device picker icon.
 
 This test only runs in DRT!
 
@@ -6,12 +6,18 @@ This test only runs in DRT!
 EVENT: canplaythrough
 PASS: We are using the apple idiom
 
-Get the wireless device picker button
+Test the AppleTV picker button
 
 PASS: Name is 'AppleTV Device Picker'
 PASS: Has hidden class
 PASS: CSS display: none
 PASS: Aria label is 'Choose Wireless Display'
 
+Simulate an available AppleTV
+
+PASS: Name is 'AppleTV Device Picker'
+PASS: Does not have hidden class
+PASS: CSS display: block
+
 Testing finished.
 
index 212e1de..a33060c 100644 (file)
@@ -4,18 +4,19 @@
         <script src="../media-file.js"></script>
         <script src="controls-test-helpers.js"></script>
         <script>
+            internals.setMockMediaPlaybackTargetPickerEnabled(false);
             var tester = new ControlsTest()
-                .whenReady(runTests)
+                .whenReady(runTestsWithoutDevice)
                 .start();
 
-            function runTests()
+            function runTestsWithoutDevice()
             {
                 var currentState = tester.currentState;
                 tester.test("We are using the apple idiom")
                     .value(currentState.idiom)
                     .isEqualTo("apple");
 
-                tester.startNewSection("Get the wireless device picker button");
+                tester.startNewSection("Test the AppleTV picker button");
                 var statusState = tester.stateForControlsElement("AppleTV Device Picker");
 
                 tester.test("Name is 'AppleTV Device Picker'")
                     .value(statusState.ariaLabel)
                     .isEqualTo("Choose Wireless Display");
 
+                internals.setMockMediaPlaybackTargetPickerEnabled(true);
+                internals.setMockMediaPlaybackTargetPickerState("Sleepy TV", "DeviceAvailable");
+                window.setTimeout(runTestsWithDevice, 100);
+            }
+
+            function runTestsWithDevice()
+            {
+                tester.startNewSection("Simulate an available AppleTV");
+                var statusState = tester.stateForControlsElement("AppleTV Device Picker", true);
+
+                tester.test("Name is 'AppleTV Device Picker'")
+                    .value(statusState.name)
+                    .isEqualTo("AppleTV Device Picker");
+
+                tester.test("Does not have hidden class")
+                    .value(statusState.className)
+                    .doesNotContain("hidden");
+
+                tester.test("CSS display: block")
+                    .value(statusState.computedStyle.display)
+                    .isEqualTo("block");
+
                 tester.end();
             }
 
         </script>
     </head>
     <body>
-        <p>This tests for the wireless device picker icon.</p>
+        <p>This tests the wireless device picker icon.</p>
         <p>This test only runs in DRT!</p>
         <video controls></video>
     </body>
index 0fc481a..2a1ca49 100644 (file)
@@ -35,8 +35,11 @@ ControlsTest = class ControlsTest {
         return { idiom: "apple", status: "fail" };
     }
 
-    stateForControlsElement(elementName)
+    stateForControlsElement(elementName, flushCachedState)
     {
+        if (flushCachedState)
+            this.cachedCurrentState = null;
+            
         var state = this.cachedCurrentState || this.currentState;
         if (state.elements && state.elements.length) {
             for (var i = 0; i < state.elements.length; i++) {
@@ -146,6 +149,22 @@ ControlsTest = class ControlsTest {
             this.logFailure(`${this.currentMessage} Expected: "${value}". Actual: "${this.currentValue}"`);
     }
 
+    contains(value)
+    {
+        if (this.currentValue.indexOf(value) >= 0)
+            this.logSuccess(this.currentMessage);
+        else
+            this.logFailure(`${this.currentMessage} Expected to contain "${value}". Actual: "${this.currentValue}"`);
+    }
+
+    doesNotContain(value)
+    {
+        if (this.currentValue.indexOf(value) < 0)
+            this.logSuccess(this.currentMessage);
+        else
+            this.logFailure(`${this.currentMessage} Expected to not contain "${value}". Actual: "${this.currentValue}"`);
+    }
+
     isEmptyString()
     {
         if (!this.currentValue && typeof this.currentValue == "string")
index 5d1e564..c2b5237 100644 (file)
@@ -1362,6 +1362,9 @@ webkit.org/b/150823 imported/w3c/web-platform-tests/XMLHttpRequest/getresponsehe
 # WOFF2 is only supported on certain Operating Systems.
 webkit.org/b/150830 [ Mavericks Yosemite ElCapitan ] fast/text/woff2.html [ ImageOnlyFailure ]
 
+# AppleTV not supported on Mavericks or Yosemite
+[ Mavericks Yosemite ] media/controls/airplay-picker.html
+
 webkit.org/b/150956 imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata.html [ Pass Timeout ]
 
 webkit.org/b/144938 crypto/subtle/rsa-export-generated-keys.html [ Slow ]
index de6d020..79e7b06 100644 (file)
@@ -1,3 +1,128 @@
+2015-11-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] Add a mock AppleTV device for testing
+        https://bugs.webkit.org/show_bug.cgi?id=148912
+        <rdar://problem/22596272>
+
+        Reviewed by Tim Horton.
+
+        No new tests, updated media/controls/airplay-picker.html.
+
+        * Modules/mediasession/WebMediaSessionManager.cpp:
+        (WebCore::WebMediaSessionManager::setMockMediaPlaybackTargetPickerEnabled): New, enable or disable
+          the mock picker.
+        (WebCore::WebMediaSessionManager::setMockMediaPlaybackTargetPickerState): New, set mock picker state.
+        (WebCore::WebMediaSessionManager::mockPicker): New.
+        (WebCore::WebMediaSessionManager::targetPicker): Return the platform or mock picker, as per settings.
+        (WebCore::webMediaSessionManagerOverride): Deleted.
+        (WebCore::WebMediaSessionManager::shared): Deleted.
+        (WebCore::WebMediaSessionManager::setWebMediaSessionManagerOverride): Deleted.
+        * Modules/mediasession/WebMediaSessionManager.h:
+
+        * WebCore.xcodeproj/project.pbxproj: Add MediaPlaybackTargetPickerMock.* and MediaPlaybackTargetMock.*.
+
+        * page/ChromeClient.h: add setMockMediaPlaybackTargetPickerEnabled and setMockMediaPlaybackTargetPickerState.
+
+        * page/Page.cpp:
+        (WebCore::Page::playbackTargetPickerClientStateDidChange):
+        (WebCore::Page::setMockMediaPlaybackTargetPickerEnabled): New.
+        (WebCore::Page::setMockMediaPlaybackTargetPickerState): New.
+        (WebCore::Page::setPlaybackTarget):
+        * page/Page.h:
+
+        * platform/graphics/MediaPlaybackTarget.h:
+        (WebCore::noMediaPlaybackTargetContext):
+        (WebCore::MediaPlaybackTarget::~MediaPlaybackTarget):
+        (WebCore::MediaPlaybackTarget::deviceName):
+        (WebCore::MediaPlaybackTarget::MediaPlaybackTarget):
+
+        * platform/graphics/MediaPlaybackTargetContext.h: Make a class instead of a struct.
+        (WebCore::MediaPlaybackTargetContext::MediaPlaybackTargetContext):
+        (WebCore::MediaPlaybackTargetContext::type):
+        (WebCore::MediaPlaybackTargetContext::mockDeviceName):
+        (WebCore::MediaPlaybackTargetContext::mockState):
+        (WebCore::MediaPlaybackTargetContext::avOutputContext):
+        (WebCore::MediaPlaybackTargetContext::encodingRequiresPlatformData):
+
+        * platform/graphics/MediaPlaybackTargetPicker.cpp: Move much of the code from MediaPlaybackTargetMac.mm
+          here so it can be the base class.
+        (WebCore::MediaPlaybackTargetPicker::MediaPlaybackTargetPicker):
+        (WebCore::MediaPlaybackTargetPicker::~MediaPlaybackTargetPicker):
+        (WebCore::MediaPlaybackTargetPicker::pendingActionTimerFired):
+        (WebCore::MediaPlaybackTargetPicker::addPendingAction):
+        (WebCore::MediaPlaybackTargetPicker::showPlaybackTargetPicker):
+        * platform/graphics/MediaPlaybackTargetPicker.h:
+        (WebCore::MediaPlaybackTargetPicker::availableDevicesDidChange):
+        (WebCore::MediaPlaybackTargetPicker::currentDeviceDidChange):
+        (WebCore::MediaPlaybackTargetPicker::client):
+        (WebCore::MediaPlaybackTargetPicker::setClient):
+
+        * platform/graphics/avfoundation/MediaPlaybackTargetMac.h:
+        (WebCore::MediaPlaybackTargetMac::outputContext):
+        (WebCore::MediaPlaybackTargetMac::targetType): Deleted.
+        * platform/graphics/avfoundation/MediaPlaybackTargetMac.mm:
+        (WebCore::MediaPlaybackTargetMac::targetContext):
+        (WebCore::MediaPlaybackTargetMac::hasActiveRoute):
+        (WebCore::MediaPlaybackTargetMac::deviceName):
+
+        * platform/graphics/avfoundation/WebMediaSessionManagerMac.cpp:
+        (WebCore::WebMediaSessionManager::shared): Renamed from platformManager.
+        (WebCore::WebMediaSessionManagerMac::platformPicker): Renamed from targetPicker.
+        (WebCore::WebMediaSessionManager::platformManager): Deleted.
+        (WebCore::WebMediaSessionManagerMac::targetPicker): Deleted.
+        * platform/graphics/avfoundation/WebMediaSessionManagerMac.h:
+
+        * platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.h:
+        * platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm:
+        (WebCore::MediaPlaybackTargetPickerMac::MediaPlaybackTargetPickerMac):
+        (WebCore::MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac):
+        (WebCore::MediaPlaybackTargetPickerMac::externalOutputDeviceAvailable):
+        (WebCore::MediaPlaybackTargetPickerMac::playbackTarget):
+        (WebCore::MediaPlaybackTargetPickerMac::devicePicker):
+        (WebCore::MediaPlaybackTargetPickerMac::showPlaybackTargetPicker):
+        (WebCore::MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMac::pendingActionTimerFired): Deleted.
+        (WebCore::MediaPlaybackTargetPickerMac::availableDevicesDidChange): Deleted.
+        (WebCore::MediaPlaybackTargetPickerMac::addPendingAction): Deleted.
+        (WebCore::MediaPlaybackTargetPickerMac::currentDeviceDidChange): Deleted.
+
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless): Add support for
+          mock target.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::wirelessPlaybackTargetName): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setShouldPlayToPlaybackTarget): Ditto.
+
+        * platform/mock/MediaPlaybackTargetMock.cpp: Added.
+        (WebCore::MediaPlaybackTargetMock::create): 
+        (WebCore::MediaPlaybackTargetMock::MediaPlaybackTargetMock):
+        (WebCore::MediaPlaybackTargetMock::~MediaPlaybackTargetMock):
+        (WebCore::MediaPlaybackTargetMock::targetContext):
+        (WebCore::toMediaPlaybackTargetMock):
+        * platform/mock/MediaPlaybackTargetMock.h: Added.
+
+        * platform/mock/MediaPlaybackTargetPickerMock.cpp: Added.
+        (WebCore::MediaPlaybackTargetPickerMock::create):
+        (WebCore::MediaPlaybackTargetPickerMock::MediaPlaybackTargetPickerMock):
+        (WebCore::MediaPlaybackTargetPickerMock::~MediaPlaybackTargetPickerMock):
+        (WebCore::MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable):
+        (WebCore::MediaPlaybackTargetPickerMock::playbackTarget):
+        (WebCore::MediaPlaybackTargetPickerMock::timerFired):
+        (WebCore::MediaPlaybackTargetPickerMock::showPlaybackTargetPicker):
+        (WebCore::MediaPlaybackTargetPickerMock::startingMonitoringPlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMock::stopMonitoringPlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMock::invalidatePlaybackTargets):
+        (WebCore::MediaPlaybackTargetPickerMock::setState):
+        * platform/mock/MediaPlaybackTargetPickerMock.h: Added.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::Internals):
+        (WebCore::Internals::setMockMediaPlaybackTargetPickerEnabled):
+        (WebCore::Internals::setMockMediaPlaybackTargetPickerState):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2015-11-09  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Unreviewed, fix the windows build
index dacaff1..c8dae60 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "FloatRect.h"
 #include "Logging.h"
-#include "MediaPlaybackTargetPickerMac.h"
+#include "MediaPlaybackTargetPickerMock.h"
 #include "WebMediaSessionManagerClient.h"
 #include <wtf/text/StringBuilder.h>
 
@@ -89,23 +89,37 @@ static String mediaProducerStateString(MediaProducer::MediaStateFlags flags)
 }
 #endif
 
-static WebMediaSessionManager*& webMediaSessionManagerOverride()
+void WebMediaSessionManager::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
 {
-    static WebMediaSessionManager* override;
-    return override;
+    LOG(Media, "WebMediaSessionManager::setMockMediaPlaybackTargetPickerEnabled - enabled = %i", (int)enabled);
+
+    if (m_mockPickerEnabled == enabled)
+        return;
+
+    m_mockPickerEnabled = enabled;
+}
+
+void WebMediaSessionManager::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
+{
+    LOG(Media, "WebMediaSessionManager::setMockMediaPlaybackTargetPickerState - name = %s, state = %i", name.utf8().data(), (int)state);
+
+    mockPicker().setState(name, state);
 }
 
-WebMediaSessionManager& WebMediaSessionManager::shared()
+MediaPlaybackTargetPickerMock& WebMediaSessionManager::mockPicker()
 {
-    if (WebMediaSessionManager* override = webMediaSessionManagerOverride())
-        return *override;
+    if (!m_pickerOverride)
+        m_pickerOverride = MediaPlaybackTargetPickerMock::create(*this);
 
-    return WebMediaSessionManager::platformManager();
+    return *m_pickerOverride.get();
 }
 
-void WebMediaSessionManager::setWebMediaSessionManagerOverride(WebMediaSessionManager* manager)
+WebCore::MediaPlaybackTargetPicker& WebMediaSessionManager::targetPicker()
 {
-    webMediaSessionManagerOverride() = manager;
+    if (m_mockPickerEnabled)
+        return mockPicker();
+
+    return platformPicker();
 }
 
 WebMediaSessionManager::WebMediaSessionManager()
index cdb080c..0577556 100644 (file)
@@ -28,7 +28,9 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
 
+#include "MediaPlaybackTargetContext.h"
 #include "MediaPlaybackTargetPicker.h"
+#include "MediaPlaybackTargetPickerMock.h"
 #include "MediaProducer.h"
 #include "Timer.h"
 #include <wtf/Ref.h>
@@ -46,7 +48,9 @@ class WebMediaSessionManager : public MediaPlaybackTargetPicker::Client {
 public:
 
     WEBCORE_EXPORT static WebMediaSessionManager& shared();
-    WEBCORE_EXPORT static void setWebMediaSessionManagerOverride(WebMediaSessionManager*);
+
+    WEBCORE_EXPORT void setMockMediaPlaybackTargetPickerEnabled(bool);
+    WEBCORE_EXPORT void setMockMediaPlaybackTargetPickerState(const String&, MediaPlaybackTargetContext::State);
 
     WEBCORE_EXPORT uint64_t addPlaybackTargetPickerClient(WebMediaSessionManagerClient&, uint64_t);
     WEBCORE_EXPORT void removePlaybackTargetPickerClient(WebMediaSessionManagerClient&, uint64_t);
@@ -58,11 +62,14 @@ protected:
     WebMediaSessionManager();
     virtual ~WebMediaSessionManager();
 
-    virtual WebCore::MediaPlaybackTargetPicker& targetPicker() = 0;
+    virtual WebCore::MediaPlaybackTargetPicker& platformPicker() = 0;
     static WebMediaSessionManager& platformManager();
 
 private:
 
+    WebCore::MediaPlaybackTargetPicker& targetPicker();
+    WebCore::MediaPlaybackTargetPickerMock& mockPicker();
+
     // MediaPlaybackTargetPicker::Client
     virtual void setPlaybackTarget(Ref<WebCore::MediaPlaybackTarget>&&) override;
     virtual void externalOutputDeviceAvailableDidChange(bool) override;
@@ -94,10 +101,12 @@ private:
 
     Vector<std::unique_ptr<ClientState>> m_clientState;
     RefPtr<MediaPlaybackTarget> m_playbackTarget;
+    std::unique_ptr<WebCore::MediaPlaybackTargetPickerMock> m_pickerOverride;
     ConfigurationTasks m_taskFlags { NoTask };
     double m_currentWatchdogInterval { 0 };
     bool m_externalOutputDeviceAvailable { false };
     bool m_targetChanged { false };
+    bool m_mockPickerEnabled { false };
 };
 
 } // namespace WebCore
index 322815f..ab2dafd 100644 (file)
                077AF14318F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */; };
                077AF14418F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */; };
                077B640F1B8F5D6B003E9AD5 /* JSMediaSessionCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 077B640E1B8F5375003E9AD5 /* JSMediaSessionCustom.cpp */; };
+               077B64121B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 077B64101B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.cpp */; };
+               077B64131B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 077B64111B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               077B64161B95F703003E9AD5 /* MediaPlaybackTargetMock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 077B64141B95F703003E9AD5 /* MediaPlaybackTargetMock.cpp */; };
+               077B64171B95F703003E9AD5 /* MediaPlaybackTargetMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 077B64151B95F703003E9AD5 /* MediaPlaybackTargetMock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0783228418013ED800999E0C /* MediaStreamAudioSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0783228218013ED700999E0C /* MediaStreamAudioSource.cpp */; };
                0783228518013ED800999E0C /* MediaStreamAudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 0783228318013ED800999E0C /* MediaStreamAudioSource.h */; };
                07846342145B151A00A58DF1 /* JSTrackEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07846340145B151A00A58DF1 /* JSTrackEvent.cpp */; };
                077AF14118F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SerializedPlatformRepresentationMac.h; sourceTree = "<group>"; };
                077AF14218F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SerializedPlatformRepresentationMac.mm; sourceTree = "<group>"; };
                077B640E1B8F5375003E9AD5 /* JSMediaSessionCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaSessionCustom.cpp; sourceTree = "<group>"; };
+               077B64101B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaPlaybackTargetPickerMock.cpp; sourceTree = "<group>"; };
+               077B64111B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTargetPickerMock.h; sourceTree = "<group>"; };
+               077B64141B95F703003E9AD5 /* MediaPlaybackTargetMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaPlaybackTargetMock.cpp; sourceTree = "<group>"; };
+               077B64151B95F703003E9AD5 /* MediaPlaybackTargetMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTargetMock.h; sourceTree = "<group>"; };
                0783228218013ED700999E0C /* MediaStreamAudioSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamAudioSource.cpp; sourceTree = "<group>"; };
                0783228318013ED800999E0C /* MediaStreamAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamAudioSource.h; sourceTree = "<group>"; };
                07846340145B151A00A58DF1 /* JSTrackEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTrackEvent.cpp; sourceTree = "<group>"; };
                                59309A1211F4AE6A00250603 /* DeviceOrientationClientMock.h */,
                                073794DF19EE2D1B00E5A045 /* MediaConstraintsMock.cpp */,
                                073794E019EE2D1B00E5A045 /* MediaConstraintsMock.h */,
+                               077B64141B95F703003E9AD5 /* MediaPlaybackTargetMock.cpp */,
+                               077B64151B95F703003E9AD5 /* MediaPlaybackTargetMock.h */,
+                               077B64101B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.cpp */,
+                               077B64111B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.h */,
                                07D6A4F11BED5F8800174146 /* MockRealtimeAudioSource.cpp */,
                                07D6A4F21BED5F8800174146 /* MockRealtimeAudioSource.h */,
                                07D6A4ED1BECF2D200174146 /* MockRealtimeMediaSource.cpp */,
                                A81369D0097374F600D74463 /* HTMLFormElement.h in Headers */,
                                A871DE2B0A152AC800B12A68 /* HTMLFrameElement.h in Headers */,
                                14FFE31D0AE1963300136BF5 /* HTMLFrameElementBase.h in Headers */,
+                               077B64171B95F703003E9AD5 /* MediaPlaybackTargetMock.h in Headers */,
                                93E241FF0B2B4E4000C732A1 /* HTMLFrameOwnerElement.h in Headers */,
                                A871DE280A152AC800B12A68 /* HTMLFrameSetElement.h in Headers */,
                                A871DE2D0A152AC800B12A68 /* HTMLHeadElement.h in Headers */,
                                49C7B9941042D2D30009D447 /* JSWebGLBuffer.h in Headers */,
                                7EA30F6A16DFFE7500257D0B /* JSWebGLCompressedTextureATC.h in Headers */,
                                7EA30F6A17EFFE7500257D0B /* JSWebGLCompressedTexturePVRTC.h in Headers */,
+                               077B64131B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.h in Headers */,
                                6E3FAD3914733F4000E42306 /* JSWebGLCompressedTextureS3TC.h in Headers */,
                                6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */,
                                BC2CBF4E140F1ABD003879BE /* JSWebGLContextEvent.h in Headers */,
                                F3D4C47812E07663003DA150 /* InspectorDOMDebuggerAgent.cpp in Sources */,
                                7A74ECBA101839A600BF939E /* InspectorDOMStorageAgent.cpp in Sources */,
                                F344C75811294FF600F26EEE /* InspectorFrontendClientLocal.cpp in Sources */,
+                               077B64161B95F703003E9AD5 /* MediaPlaybackTargetMock.cpp in Sources */,
                                7A0E770E10C00A8800A0276E /* InspectorFrontendHost.cpp in Sources */,
                                7A54857F14E02D51006AE05A /* InspectorHistory.cpp in Sources */,
                                7ACD88D314C08BD60084EDD2 /* InspectorIndexedDBAgent.cpp in Sources */,
                                070334D9145A006F008D8D45 /* TrackBase.cpp in Sources */,
                                070334D31459FFAD008D8D45 /* TrackEvent.cpp in Sources */,
                                BE88E0C11715CE2600658D98 /* TrackListBase.cpp in Sources */,
+                               077B64121B94F12E003E9AD5 /* MediaPlaybackTargetPickerMock.cpp in Sources */,
                                FFAC30FF184FB145008C4F1E /* TrailingObjects.cpp in Sources */,
                                49E911C30EF86D47009D0CAF /* TransformationMatrix.cpp in Sources */,
                                494BC40D12AEDD9E00743BD2 /* TransformationMatrixCA.cpp in Sources */,
index 52b3fad..8c806ce 100644 (file)
@@ -51,6 +51,10 @@ class MediaSessionMetadata;
 }
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "MediaPlaybackTargetContext.h"
+#endif
+
 #if PLATFORM(IOS)
 #include "PlatformLayer.h"
 #define NSResponder WAKResponder
@@ -449,6 +453,8 @@ public:
     virtual void removePlaybackTargetPickerClient(uint64_t /*contextId*/) { }
     virtual void showPlaybackTargetPicker(uint64_t /*contextId*/, const WebCore::IntPoint&, bool /* isVideo */) { }
     virtual void playbackTargetPickerClientStateDidChange(uint64_t /*contextId*/, MediaProducer::MediaStateFlags) { }
+    virtual void setMockMediaPlaybackTargetPickerEnabled(bool)  { }
+    virtual void setMockMediaPlaybackTargetPickerState(const String&, WebCore::MediaPlaybackTargetContext::State) { }
 #endif
 
     virtual void imageOrMediaDocumentSizeChanged(const WebCore::IntSize&) { }
index 89f7ef1..efbd754 100644 (file)
@@ -1725,6 +1725,16 @@ void Page::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaPro
     chrome().client().playbackTargetPickerClientStateDidChange(contextId, state);
 }
 
+void Page::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+    chrome().client().setMockMediaPlaybackTargetPickerEnabled(enabled);
+}
+
+void Page::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
+{
+    chrome().client().setMockMediaPlaybackTargetPickerState(name, state);
+}
+
 void Page::setPlaybackTarget(uint64_t contextId, Ref<MediaPlaybackTarget>&& target)
 {
     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
index 598836d..5958577 100644 (file)
 #include "MediaSessionEvents.h"
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "MediaPlaybackTargetContext.h"
+#endif
+
 namespace JSC {
 class Debugger;
 }
@@ -455,8 +459,10 @@ public:
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     void addPlaybackTargetPickerClient(uint64_t);
     void removePlaybackTargetPickerClient(uint64_t);
-    void showPlaybackTargetPicker(uint64_t, const WebCore::IntPoint&, bool);
+    void showPlaybackTargetPicker(uint64_t, const IntPoint&, bool);
     void playbackTargetPickerClientStateDidChange(uint64_t, MediaProducer::MediaStateFlags);
+    WEBCORE_EXPORT void setMockMediaPlaybackTargetPickerEnabled(bool);
+    WEBCORE_EXPORT void setMockMediaPlaybackTargetPickerState(const String&, MediaPlaybackTargetContext::State);
 
     WEBCORE_EXPORT void setPlaybackTarget(uint64_t, Ref<MediaPlaybackTarget>&&);
     WEBCORE_EXPORT void playbackTargetAvailabilityDidChange(uint64_t, bool);
index 34f59a6..1619aff 100644 (file)
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 
 #include "MediaPlaybackTargetContext.h"
+#include <wtf/NeverDestroyed.h>
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
 
+static const MediaPlaybackTargetContext& noMediaPlaybackTargetContext()
+{
+    static NeverDestroyed<MediaPlaybackTargetContext> context;
+    return context;
+}
+
 class MediaPlaybackTarget : public RefCounted<MediaPlaybackTarget> {
 public:
     virtual ~MediaPlaybackTarget() { }
@@ -40,11 +47,13 @@ public:
     enum TargetType {
         None,
         AVFoundation,
+        Mock,
     };
     virtual TargetType targetType() const { return None; }
 
-    virtual const MediaPlaybackTargetContext& targetContext() const { return NoMediaPlaybackTargetContext; }
+    virtual const MediaPlaybackTargetContext& targetContext() const { return noMediaPlaybackTargetContext(); }
     virtual bool hasActiveRoute() const { return false; }
+    virtual String deviceName() const { return emptyString(); }
 
 protected:
     MediaPlaybackTarget() { }
index b76f07c..027fb68 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 
+#include <wtf/text/WTFString.h>
+
 OBJC_CLASS AVOutputContext;
 
 #if PLATFORM(COCOA)
@@ -37,21 +39,66 @@ OBJC_CLASS NSKeyedUnarchiver;
 
 namespace WebCore {
 
-struct MediaPlaybackTargetContext {
-
-    enum ContextType : int32_t {
+class MediaPlaybackTargetContext {
+public:
+    enum Type : int32_t {
         None,
         AVOutputContextType,
-    } type;
+        MockType,
+    };
 
-    union {
-        AVOutputContext* avOutputContext;
-    } context;
+    enum ContextState {
+        Unavailable = 0,
+        OutputDeviceAvailable = 1 << 0,
+    };
+    typedef unsigned State;
 
-    bool encodingRequiresPlatformData() const { return type == AVOutputContextType; }
-};
+    MediaPlaybackTargetContext()
+        : m_type(None)
+    {
+    }
+
+    MediaPlaybackTargetContext(AVOutputContext *outputContext)
+        : m_type(AVOutputContextType)
+        , m_outputContext(outputContext)
+    {
+    }
+
+    MediaPlaybackTargetContext(const String& name, State state)
+        : m_type(MockType)
+        , m_name(name)
+        , m_state(state)
+    {
+    }
 
-const MediaPlaybackTargetContext NoMediaPlaybackTargetContext = { MediaPlaybackTargetContext::None, {nullptr} };
+    Type type() const { return m_type; }
+
+    const String& mockDeviceName() const
+    {
+        ASSERT(m_type == MockType);
+        return m_name;
+    }
+
+    State mockState() const
+    {
+        ASSERT(m_type == MockType);
+        return m_state;
+    }
+
+    AVOutputContext *avOutputContext() const
+    {
+        ASSERT(m_type == AVOutputContextType);
+        return m_outputContext;
+    }
+
+    bool encodingRequiresPlatformData() const { return m_type == AVOutputContextType; }
+    
+private:
+    Type m_type { None };
+    AVOutputContext *m_outputContext { nullptr };
+    String m_name;
+    State m_state { Unavailable };
+};
 
 }
 
index 438be75..4931686 100644 (file)
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 
+#include "Logging.h"
+#include "MediaPlaybackTarget.h"
+
 namespace WebCore {
 
+static const double pendingActionInterval = 1.0 / 10.0;
+
 MediaPlaybackTargetPicker::MediaPlaybackTargetPicker(Client& client)
     : m_client(&client)
+    , m_pendingActionTimer(RunLoop::main(), this, &MediaPlaybackTargetPicker::pendingActionTimerFired)
 {
 }
 
 MediaPlaybackTargetPicker::~MediaPlaybackTargetPicker()
 {
+    m_pendingActionTimer.stop();
     m_client = nullptr;
 }
 
+void MediaPlaybackTargetPicker::pendingActionTimerFired()
+{
+    LOG(Media, "MediaPlaybackTargetPicker::pendingActionTimerFired - flags = 0x%x", m_pendingActionFlags);
+
+    PendingActionFlags pendingActions = m_pendingActionFlags;
+    m_pendingActionFlags = 0;
+
+    if (pendingActions & CurrentDeviceDidChange)
+        m_client->setPlaybackTarget(playbackTarget());
+
+    if (pendingActions & OutputDeviceAvailabilityChanged)
+        m_client->externalOutputDeviceAvailableDidChange(externalOutputDeviceAvailable());
+}
+
+void MediaPlaybackTargetPicker::addPendingAction(PendingActionFlags action)
+{
+    if (!m_client)
+        return;
+
+    m_pendingActionFlags |= action;
+    m_pendingActionTimer.startOneShot(pendingActionInterval);
+}
+
 void MediaPlaybackTargetPicker::showPlaybackTargetPicker(const FloatRect&, bool)
 {
     ASSERT_NOT_REACHED();
index 7cabac9..afe0bd3 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 
 #include <wtf/Ref.h>
+#include <wtf/RunLoop.h>
 
 namespace WebCore {
 
@@ -55,10 +56,30 @@ public:
     virtual void stopMonitoringPlaybackTargets();
     virtual void invalidatePlaybackTargets();
 
+    void availableDevicesDidChange() { addPendingAction(OutputDeviceAvailabilityChanged); }
+    void currentDeviceDidChange() { addPendingAction(CurrentDeviceDidChange); }
+
 protected:
     explicit MediaPlaybackTargetPicker(Client&);
 
+    enum ActionType {
+        OutputDeviceAvailabilityChanged = 1 << 0,
+        CurrentDeviceDidChange = 1 << 1,
+    };
+    typedef unsigned PendingActionFlags;
+
+    void addPendingAction(PendingActionFlags);
+    void pendingActionTimerFired();
+    Client* client() const { return m_client; }
+    void setClient(Client* client) { m_client = client; }
+
+private:
+    virtual bool externalOutputDeviceAvailable() = 0;
+    virtual Ref<MediaPlaybackTarget> playbackTarget() = 0;
+
+    PendingActionFlags m_pendingActionFlags { 0 };
     Client* m_client;
+    RunLoop::Timer<MediaPlaybackTargetPicker> m_pendingActionTimer;
 };
 
 } // namespace WebCore
index 61b2a45..7861db6 100644 (file)
@@ -39,10 +39,12 @@ public:
 
     virtual ~MediaPlaybackTargetMac();
 
-    virtual TargetType targetType() const { return AVFoundation; }
+    TargetType targetType() const override { return AVFoundation; }
 
-    virtual const MediaPlaybackTargetContext& targetContext() const;
-    virtual bool hasActiveRoute() const;
+    const MediaPlaybackTargetContext& targetContext() const override;
+    bool hasActiveRoute() const override;
+
+    String deviceName() const override;
 
     AVOutputContext *outputContext() const { return m_outputContext.get(); }
 
@@ -51,6 +53,7 @@ protected:
 
     RetainPtr<AVOutputContext> m_outputContext;
     mutable MediaPlaybackTargetContext m_context;
+    String m_deviceName;
 };
 
 MediaPlaybackTargetMac* toMediaPlaybackTargetMac(MediaPlaybackTarget*);
index b506847..832b4e2 100644 (file)
@@ -54,9 +54,7 @@ MediaPlaybackTargetMac::~MediaPlaybackTargetMac()
 
 const MediaPlaybackTargetContext& MediaPlaybackTargetMac::targetContext() const
 {
-    m_context.type = MediaPlaybackTargetContext::AVOutputContextType;
-    m_context.context.avOutputContext = m_outputContext.get();
-
+    m_context = MediaPlaybackTargetContext(m_outputContext.get());
     return m_context;
 }
 
@@ -65,6 +63,13 @@ bool MediaPlaybackTargetMac::hasActiveRoute() const
     return m_outputContext && m_outputContext.get().deviceName;
 }
 
+String MediaPlaybackTargetMac::deviceName() const
+{
+    if (m_outputContext)
+        return m_outputContext.get().deviceName;
+
+    return emptyString();
+}
 
 MediaPlaybackTargetMac* toMediaPlaybackTargetMac(MediaPlaybackTarget* rep)
 {
index 5a31775..a449881 100644 (file)
@@ -33,7 +33,7 @@
 
 namespace WebCore {
 
-WebMediaSessionManager& WebMediaSessionManager::platformManager()
+WebMediaSessionManager& WebMediaSessionManager::shared()
 {
     static NeverDestroyed<WebMediaSessionManagerMac> sharedManager;
     return sharedManager;
@@ -48,7 +48,7 @@ WebMediaSessionManagerMac::~WebMediaSessionManagerMac()
 {
 }
 
-WebCore::MediaPlaybackTargetPicker& WebMediaSessionManagerMac::targetPicker()
+WebCore::MediaPlaybackTargetPicker& WebMediaSessionManagerMac::platformPicker()
 {
     if (!m_targetPicker)
         m_targetPicker = MediaPlaybackTargetPickerMac::create(*this);
index e779560..f113159 100644 (file)
@@ -40,7 +40,7 @@ private:
     WebMediaSessionManagerMac();
     virtual ~WebMediaSessionManagerMac();
 
-    virtual WebCore::MediaPlaybackTargetPicker& targetPicker();
+    virtual WebCore::MediaPlaybackTargetPicker& platformPicker();
 
     std::unique_ptr<WebCore::MediaPlaybackTargetPicker> m_targetPicker;
 };
index 28159d4..e07faac 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "MediaPlaybackTargetPicker.h"
 #include <wtf/RetainPtr.h>
-#include <wtf/RunLoop.h>
 
 OBJC_CLASS AVOutputDeviceMenuController;
 OBJC_CLASS WebAVOutputDeviceMenuControllerHelper;
@@ -49,27 +48,16 @@ public:
     void stopMonitoringPlaybackTargets() override;
     void invalidatePlaybackTargets() override;
 
-    void availableDevicesDidChange();
-    void currentDeviceDidChange();
-
 private:
     explicit MediaPlaybackTargetPickerMac(MediaPlaybackTargetPicker::Client&);
 
-    AVOutputDeviceMenuController *devicePicker();
-
-    enum ActionType {
-        OutputDeviceAvailabilityChanged = 1 << 0,
-        CurrentDeviceDidChange = 1 << 1,
-    };
-    typedef unsigned PendingActionFlags;
+    bool externalOutputDeviceAvailable() override;
+    Ref<MediaPlaybackTarget> playbackTarget() override;
 
-    void addPendingAction(PendingActionFlags);
-    void pendingActionTimerFired();
+    AVOutputDeviceMenuController *devicePicker();
 
-    PendingActionFlags m_pendingActionFlags { 0 };
     RetainPtr<AVOutputDeviceMenuController> m_outputDeviceMenuController;
     RetainPtr<WebAVOutputDeviceMenuControllerHelper> m_outputDeviceMenuControllerDelegate;
-    RunLoop::Timer<MediaPlaybackTargetPickerMac> m_pendingActionTimer;
     bool m_showingMenu { false };
 };
 
index a126848..c7c88c0 100644 (file)
@@ -67,8 +67,6 @@ static NSString *externalOutputDevicePickedKeyName = @"externalOutputDevicePicke
 
 namespace WebCore {
 
-static const double pendingActionInterval = 1.0 / 10.0;
-
 std::unique_ptr<MediaPlaybackTargetPickerMac> MediaPlaybackTargetPickerMac::create(MediaPlaybackTargetPicker::Client& client)
 {
     return std::unique_ptr<MediaPlaybackTargetPickerMac>(new MediaPlaybackTargetPickerMac(client));
@@ -77,47 +75,25 @@ std::unique_ptr<MediaPlaybackTargetPickerMac> MediaPlaybackTargetPickerMac::crea
 MediaPlaybackTargetPickerMac::MediaPlaybackTargetPickerMac(MediaPlaybackTargetPicker::Client& client)
     : MediaPlaybackTargetPicker(client)
     , m_outputDeviceMenuControllerDelegate(adoptNS([[WebAVOutputDeviceMenuControllerHelper alloc] initWithCallback:this]))
-    , m_pendingActionTimer(RunLoop::main(), this, &MediaPlaybackTargetPickerMac::pendingActionTimerFired)
 {
 }
 
 MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac()
 {
-    m_client = nullptr;
-    m_pendingActionTimer.stop();
+    setClient(nullptr);
     [m_outputDeviceMenuControllerDelegate clearCallback];
-
-    stopMonitoringPlaybackTargets();
 }
 
-void MediaPlaybackTargetPickerMac::pendingActionTimerFired()
+bool MediaPlaybackTargetPickerMac::externalOutputDeviceAvailable()
 {
-    LOG(Media, "MediaPlaybackTargetPickerMac::pendingActionTimerFired - flags = 0x%x", m_pendingActionFlags);
-
-    if (!m_client)
-        return;
-
-    PendingActionFlags pendingActions = m_pendingActionFlags;
-    m_pendingActionFlags = 0;
-
-    if (pendingActions & CurrentDeviceDidChange) {
-        AVOutputContext* context = m_outputDeviceMenuController ? [m_outputDeviceMenuController.get() outputContext] : nullptr;
-        m_client->setPlaybackTarget(WebCore::MediaPlaybackTargetMac::create(context));
-    }
-
-    if (pendingActions & OutputDeviceAvailabilityChanged)
-        m_client->externalOutputDeviceAvailableDidChange(devicePicker().externalOutputDeviceAvailable);
-
+    return devicePicker().externalOutputDeviceAvailable;
 }
 
-void MediaPlaybackTargetPickerMac::availableDevicesDidChange()
+Ref<MediaPlaybackTarget> MediaPlaybackTargetPickerMac::playbackTarget()
 {
-    LOG(Media, "MediaPlaybackTargetPickerMac::availableDevicesDidChange - available = %i", (int)devicePicker().externalOutputDeviceAvailable);
-
-    if (!m_client)
-        return;
+    AVOutputContext* context = m_outputDeviceMenuController ? [m_outputDeviceMenuController.get() outputContext] : nullptr;
 
-    addPendingAction(OutputDeviceAvailabilityChanged);
+    return WebCore::MediaPlaybackTargetMac::create(context);
 }
 
 AVOutputDeviceMenuControllerType *MediaPlaybackTargetPickerMac::devicePicker()
@@ -145,7 +121,7 @@ AVOutputDeviceMenuControllerType *MediaPlaybackTargetPickerMac::devicePicker()
 
 void MediaPlaybackTargetPickerMac::showPlaybackTargetPicker(const FloatRect& location, bool checkActiveRoute)
 {
-    if (!m_client || m_showingMenu)
+    if (!client() || m_showingMenu)
         return;
 
     LOG(Media, "MediaPlaybackTargetPickerMac::showPlaybackTargetPicker - checkActiveRoute = %i", (int)checkActiveRoute);
@@ -162,22 +138,6 @@ void MediaPlaybackTargetPickerMac::showPlaybackTargetPicker(const FloatRect& loc
     m_showingMenu = false;
 }
 
-void MediaPlaybackTargetPickerMac::addPendingAction(PendingActionFlags action)
-{
-    m_pendingActionFlags |= action;
-    m_pendingActionTimer.startOneShot(pendingActionInterval);
-}
-
-void MediaPlaybackTargetPickerMac::currentDeviceDidChange()
-{
-    LOG(Media, "MediaPlaybackTargetPickerMac::currentDeviceDidChange");
-
-    if (!m_client)
-        return;
-
-    addPendingAction(CurrentDeviceDidChange);
-}
-
 void MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets()
 {
     LOG(Media, "MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets");
index f8baddd..f123774 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(VIDEO) && USE(AVFOUNDATION)
 
+#include "MediaPlaybackTarget.h"
 #include "MediaPlayerPrivateAVFoundation.h"
 #include <wtf/HashMap.h>
 
@@ -64,7 +65,6 @@ class AudioSourceProviderAVFObjC;
 class AudioTrackPrivateAVFObjC;
 class InbandMetadataTextTrackPrivateAVF;
 class InbandTextTrackPrivateAVFObjC;
-class MediaPlaybackTarget;
 class MediaSelectionGroupAVFObjC;
 class VideoTrackPrivateAVFObjC;
 class WebCoreAVFResourceLoader;
@@ -362,6 +362,7 @@ private:
 
 #if PLATFORM(MAC) && ENABLE(WIRELESS_PLAYBACK_TARGET)
     RetainPtr<AVOutputContext> m_outputContext;
+    RefPtr<MediaPlaybackTarget> m_playbackTarget { nullptr };
 #endif
 
     mutable RetainPtr<NSArray> m_cachedSeekableRanges;
index 55b3d47..cf6817c 100644 (file)
@@ -48,6 +48,7 @@
 #import "URL.h"
 #import "Logging.h"
 #import "MediaPlaybackTargetMac.h"
+#import "MediaPlaybackTargetMock.h"
 #import "MediaSelectionGroupAVFObjC.h"
 #import "MediaTimeAVFoundation.h"
 #import "PlatformTimeRanges.h"
@@ -2737,10 +2738,19 @@ String MediaPlayerPrivateAVFoundationObjC::languageOfPrimaryAudioTrack() const
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 bool MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless() const
 {
-    if (!m_avPlayer)
-        return false;
+    bool wirelessTarget = false;
+
+#if !PLATFORM(IOS)
+    if (m_playbackTarget) {
+        if (m_playbackTarget->targetType() == MediaPlaybackTarget::AVFoundation)
+            wirelessTarget = m_avPlayer && m_avPlayer.get().externalPlaybackActive;
+        else
+            wirelessTarget = m_shouldPlayToPlaybackTarget && m_playbackTarget->hasActiveRoute();
+    }
+#else
+    wirelessTarget = m_avPlayer && m_avPlayer.get().externalPlaybackActive;
+#endif
 
-    bool wirelessTarget = m_avPlayer.get().externalPlaybackActive;
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::isCurrentPlaybackTargetWireless(%p) - returning %s", this, boolString(wirelessTarget));
 
     return wirelessTarget;
@@ -2776,8 +2786,8 @@ String MediaPlayerPrivateAVFoundationObjC::wirelessPlaybackTargetName() const
 
     String wirelessTargetName;
 #if !PLATFORM(IOS)
-    if (m_outputContext)
-        wirelessTargetName = m_outputContext.get().deviceName;
+    if (m_playbackTarget)
+        wirelessTargetName = m_playbackTarget->deviceName();
 #else
     wirelessTargetName = wkExernalDeviceDisplayNameForPlayer(m_avPlayer.get());
 #endif
@@ -2812,31 +2822,56 @@ void MediaPlayerPrivateAVFoundationObjC::setWirelessVideoPlaybackDisabled(bool d
 #if !PLATFORM(IOS)
 void MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&& target)
 {
-    MediaPlaybackTargetMac* macTarget = toMediaPlaybackTargetMac(&target.get());
+    m_playbackTarget = WTF::move(target);
+
+    m_outputContext = m_playbackTarget->targetType() == MediaPlaybackTarget::AVFoundation ? toMediaPlaybackTargetMac(m_playbackTarget.get())->outputContext() : nullptr;
 
-    m_outputContext = macTarget->outputContext();
-    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget(%p) - target = %p, device name = %s", this, m_outputContext.get(), [m_outputContext.get().deviceName UTF8String]);
+    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setWirelessPlaybackTarget(%p) - target = %p, device name = %s", this, m_outputContext.get(), m_playbackTarget->deviceName().utf8().data());
 
-    if (!m_outputContext || !m_outputContext.get().deviceName)
+    if (!m_playbackTarget->hasActiveRoute())
         setShouldPlayToPlaybackTarget(false);
 }
 
 void MediaPlayerPrivateAVFoundationObjC::setShouldPlayToPlaybackTarget(bool shouldPlay)
 {
-    m_shouldPlayToPlaybackTarget = shouldPlay;
+    if (m_shouldPlayToPlaybackTarget == shouldPlay)
+        return;
 
-    AVOutputContext *newContext = shouldPlay ? m_outputContext.get() : nil;
-    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setShouldPlayToPlaybackTarget(%p) - target = %p, shouldPlay = %s", this, newContext, boolString(shouldPlay));
+    m_shouldPlayToPlaybackTarget = shouldPlay;
 
-    if (!m_avPlayer)
+    if (!m_playbackTarget)
         return;
 
-    RetainPtr<AVOutputContext> currentContext = m_avPlayer.get().outputContext;
-    if ((!newContext && !currentContext.get()) || [currentContext.get() isEqual:newContext])
+    if (m_playbackTarget->targetType() == MediaPlaybackTarget::AVFoundation) {
+        AVOutputContext *newContext = shouldPlay ? m_outputContext.get() : nil;
+
+        LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setShouldPlayToPlaybackTarget(%p) - target = %p, shouldPlay = %s", this, newContext, boolString(shouldPlay));
+
+        if (!m_avPlayer)
+            return;
+
+        RetainPtr<AVOutputContext> currentContext = m_avPlayer.get().outputContext;
+        if ((!newContext && !currentContext.get()) || [currentContext.get() isEqual:newContext])
+            return;
+
+        setDelayCallbacks(true);
+        m_avPlayer.get().outputContext = newContext;
+        setDelayCallbacks(false);
+
         return;
+    }
+
+    ASSERT(m_playbackTarget->targetType() == MediaPlaybackTarget::Mock);
+
+    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setShouldPlayToPlaybackTarget(%p) - target = {Mock}, shouldPlay = %s", this, boolString(shouldPlay));
 
     setDelayCallbacks(true);
-    m_avPlayer.get().outputContext = newContext;
+    auto weakThis = createWeakPtr();
+    scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification([weakThis] {
+        if (!weakThis)
+            return;
+        weakThis->playbackTargetIsWirelessDidChange();
+    }));
     setDelayCallbacks(false);
 }
 #endif // !PLATFORM(IOS)
diff --git a/Source/WebCore/platform/mock/MediaPlaybackTargetMock.cpp b/Source/WebCore/platform/mock/MediaPlaybackTargetMock.cpp
new file mode 100644 (file)
index 0000000..01ff3fa
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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. ``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
+ * 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. 
+ */
+
+#include "config.h"
+#include "MediaPlaybackTargetMock.h"
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+namespace WebCore {
+
+Ref<MediaPlaybackTarget> MediaPlaybackTargetMock::create(const String& name, MediaPlaybackTargetContext::State state)
+{
+    return adoptRef(*new MediaPlaybackTargetMock(name, state));
+}
+
+MediaPlaybackTargetMock::MediaPlaybackTargetMock(const String& name, MediaPlaybackTargetContext::State state)
+    : MediaPlaybackTarget()
+    , m_name(name)
+    , m_state(state)
+{
+}
+
+MediaPlaybackTargetMock::~MediaPlaybackTargetMock()
+{
+}
+
+const MediaPlaybackTargetContext& MediaPlaybackTargetMock::targetContext() const
+{
+    m_context = MediaPlaybackTargetContext(m_name, m_state);
+    return m_context;
+}
+
+MediaPlaybackTargetMock* toMediaPlaybackTargetMock(MediaPlaybackTarget* rep)
+{
+    return const_cast<MediaPlaybackTargetMock*>(toMediaPlaybackTargetMock(const_cast<const MediaPlaybackTarget*>(rep)));
+}
+
+const MediaPlaybackTargetMock* toMediaPlaybackTargetMock(const MediaPlaybackTarget* rep)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(rep->targetType() == MediaPlaybackTarget::Mock);
+    return static_cast<const MediaPlaybackTargetMock*>(rep);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
diff --git a/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h b/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h
new file mode 100644 (file)
index 0000000..9468115
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 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. ``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
+ * 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. 
+ */
+
+#ifndef MediaPlaybackTargetMock_h
+#define MediaPlaybackTargetMock_h
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+#include "MediaPlaybackTarget.h"
+#include "MediaPlaybackTargetContext.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class MediaPlaybackTargetMock : public MediaPlaybackTarget {
+public:
+    WEBCORE_EXPORT static Ref<MediaPlaybackTarget> create(const String&, MediaPlaybackTargetContext::State);
+
+    virtual ~MediaPlaybackTargetMock();
+
+    TargetType targetType() const override { return Mock; }
+
+    const MediaPlaybackTargetContext& targetContext() const override;
+
+    bool hasActiveRoute() const override { return !m_name.isEmpty(); }
+
+    String deviceName() const override { return m_name; }
+
+    MediaPlaybackTargetContext::State state() const;
+
+protected:
+    MediaPlaybackTargetMock(const String&, MediaPlaybackTargetContext::State);
+
+    String m_name;
+    MediaPlaybackTargetContext::State m_state { MediaPlaybackTargetContext::Unavailable };
+    mutable MediaPlaybackTargetContext m_context;
+};
+
+MediaPlaybackTargetMock* toMediaPlaybackTargetMock(MediaPlaybackTarget*);
+const MediaPlaybackTargetMock* toMediaPlaybackTargetMock(const MediaPlaybackTarget*);
+
+}
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+#endif
diff --git a/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp b/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.cpp
new file mode 100644 (file)
index 0000000..e993708
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "config.h"
+#include "MediaPlaybackTargetPickerMock.h"
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+#include "Logging.h"
+#include <WebCore/FloatRect.h>
+#include <WebCore/MediaPlaybackTargetMock.h>
+#include <WebCore/WebMediaSessionManager.h>
+
+using namespace WebCore;
+
+namespace WebCore {
+
+static const double timerInterval = 1.0 / 10.0;
+
+std::unique_ptr<MediaPlaybackTargetPickerMock> MediaPlaybackTargetPickerMock::create(MediaPlaybackTargetPicker::Client& client)
+{
+    return std::unique_ptr<MediaPlaybackTargetPickerMock>(new MediaPlaybackTargetPickerMock(client));
+}
+
+MediaPlaybackTargetPickerMock::MediaPlaybackTargetPickerMock(MediaPlaybackTargetPicker::Client& client)
+    : MediaPlaybackTargetPicker(client)
+    , m_timer(RunLoop::main(), this, &MediaPlaybackTargetPickerMock::timerFired)
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::MediaPlaybackTargetPickerMock");
+}
+
+MediaPlaybackTargetPickerMock::~MediaPlaybackTargetPickerMock()
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::~MediaPlaybackTargetPickerMock");
+    setClient(nullptr);
+}
+
+bool MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable()
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::externalOutputDeviceAvailable");
+    return m_state & MediaPlaybackTargetContext::OutputDeviceAvailable;
+}
+
+Ref<MediaPlaybackTarget> MediaPlaybackTargetPickerMock::playbackTarget()
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::playbackTarget");
+    return WebCore::MediaPlaybackTargetMock::create(m_deviceName, m_state);
+}
+
+void MediaPlaybackTargetPickerMock::timerFired()
+{
+    m_showingMenu = false;
+    currentDeviceDidChange();
+}
+
+void MediaPlaybackTargetPickerMock::showPlaybackTargetPicker(const FloatRect&, bool checkActiveRoute)
+{
+    if (!client() || m_showingMenu)
+        return;
+
+    LOG(Media, "MediaPlaybackTargetPickerMock::showPlaybackTargetPicker - checkActiveRoute = %i", (int)checkActiveRoute);
+
+    m_showingMenu = true;
+    m_timer.startOneShot(timerInterval);
+}
+
+void MediaPlaybackTargetPickerMock::startingMonitoringPlaybackTargets()
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::startingMonitoringPlaybackTargets");
+
+    if (m_state & MediaPlaybackTargetContext::OutputDeviceAvailable)
+        availableDevicesDidChange();
+
+    if (!m_deviceName.isEmpty())
+        currentDeviceDidChange();
+}
+
+void MediaPlaybackTargetPickerMock::stopMonitoringPlaybackTargets()
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::stopMonitoringPlaybackTargets");
+}
+
+void MediaPlaybackTargetPickerMock::invalidatePlaybackTargets()
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::invalidatePlaybackTargets");
+    setState(WTF::emptyString(), MediaPlaybackTargetContext::Unavailable);
+}
+
+void MediaPlaybackTargetPickerMock::setState(const String& deviceName, MediaPlaybackTargetContext::State state)
+{
+    LOG(Media, "MediaPlaybackTargetPickerMock::setState - name = %s, state = 0x%x", deviceName.utf8().data(), (unsigned)state);
+
+    if (deviceName != m_deviceName) {
+        m_deviceName = deviceName;
+        currentDeviceDidChange();
+    }
+
+    if (m_state != state) {
+        m_state = state;
+        availableDevicesDidChange();
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
diff --git a/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h b/Source/WebCore/platform/mock/MediaPlaybackTargetPickerMock.h
new file mode 100644 (file)
index 0000000..615959b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef MediaPlaybackTargetPickerMock_h
+#define MediaPlaybackTargetPickerMock_h
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+#include "MediaPlaybackTargetContext.h"
+#include "MediaPlaybackTargetPicker.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class MediaPlaybackTargetPickerMock final : public MediaPlaybackTargetPicker {
+    WTF_MAKE_NONCOPYABLE(MediaPlaybackTargetPickerMock);
+public:
+    virtual ~MediaPlaybackTargetPickerMock();
+
+    WEBCORE_EXPORT static std::unique_ptr<MediaPlaybackTargetPickerMock> create(MediaPlaybackTargetPicker::Client&);
+
+    void showPlaybackTargetPicker(const FloatRect&, bool checkActiveRoute) override;
+    void startingMonitoringPlaybackTargets() override;
+    void stopMonitoringPlaybackTargets() override;
+    void invalidatePlaybackTargets() override;
+
+    void setState(const String&, MediaPlaybackTargetContext::State);
+
+private:
+    explicit MediaPlaybackTargetPickerMock(MediaPlaybackTargetPicker::Client&);
+
+    bool externalOutputDeviceAvailable() override;
+    Ref<MediaPlaybackTarget> playbackTarget() override;
+
+    void timerFired();
+
+    String m_deviceName;
+    RunLoop::Timer<MediaPlaybackTargetPickerMock> m_timer;
+    MediaPlaybackTargetContext::State m_state { MediaPlaybackTargetContext::Unavailable };
+    bool m_showingMenu { false };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+
+#endif // WebContextMenuProxyMac_h
index 4db6f9d..348a688 100644 (file)
 #include "MediaSessionManager.h"
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "MediaPlaybackTargetContext.h"
+#endif
+
 using JSC::CodeBlock;
 using JSC::FunctionExecutable;
 using JSC::JSFunction;
@@ -400,6 +404,11 @@ Internals::Internals(Document* document)
     MockRealtimeMediaSourceCenter::registerMockRealtimeMediaSourceCenter();
     enableMockRTCPeerConnectionHandler();
 #endif
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    if (document && document->page())
+        document->page()->setMockMediaPlaybackTargetPickerEnabled(true);
+#endif
 }
 
 Document* Internals::contextDocument() const
@@ -2941,6 +2950,33 @@ void Internals::simulateSystemWake() const
 #endif
 }
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+void Internals::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+    Page* page = contextDocument()->frame()->page();
+    ASSERT(page);
+
+    page->setMockMediaPlaybackTargetPickerEnabled(enabled);
+}
+
+void Internals::setMockMediaPlaybackTargetPickerState(const String& deviceName, const String& deviceState, ExceptionCode& ec)
+{
+    Page* page = contextDocument()->frame()->page();
+    ASSERT(page);
+
+    MediaPlaybackTargetContext::State state = MediaPlaybackTargetContext::Unavailable;
+
+    if (equalIgnoringCase(deviceState, "DeviceAvailable"))
+        state = MediaPlaybackTargetContext::OutputDeviceAvailable;
+    else {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+
+    page->setMockMediaPlaybackTargetPickerState(deviceName, state);
+}
+#endif
+
 
 void Internals::installMockPageOverlay(const String& overlayType, ExceptionCode& ec)
 {
index ea8bdc3..0b9e13c 100644 (file)
@@ -403,6 +403,11 @@ public:
     void sendMediaControlEvent(const String&);
 #endif
 
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+    void setMockMediaPlaybackTargetPickerEnabled(bool);
+    void setMockMediaPlaybackTargetPickerState(const String& deviceName, const String& deviceState, ExceptionCode&);
+#endif
+
 #if ENABLE(WEB_AUDIO)
     void setAudioContextRestrictions(AudioContext*, const String& restrictions, ExceptionCode&);
 #endif
index 356e986..72d6c6e 100644 (file)
@@ -377,7 +377,9 @@ enum MediaControlEvent {
     [Conditional=VIDEO, RaisesException] void setMediaElementRestrictions(HTMLMediaElement element, DOMString restrictions);
     [Conditional=WEB_AUDIO, RaisesException] void setAudioContextRestrictions(AudioContext context, DOMString restrictions);
     [Conditional=VIDEO, RaisesException] void postRemoteControlCommand(DOMString command);
-    
+    [Conditional=WIRELESS_PLAYBACK_TARGET] void setMockMediaPlaybackTargetPickerEnabled(boolean enabled);
+    [Conditional=WIRELESS_PLAYBACK_TARGET, RaisesException] void setMockMediaPlaybackTargetPickerState(DOMString deviceName, DOMString deviceState);
+
     [Conditional=VIDEO] void simulateSystemSleep();
     [Conditional=VIDEO] void simulateSystemWake();
     [Conditional=VIDEO] boolean elementIsBlockingDisplaySleep(Element element);
index 7daa82a..17150be 100644 (file)
@@ -1,3 +1,26 @@
+2015-11-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] Add a mock AppleTV device for testing
+        https://bugs.webkit.org/show_bug.cgi?id=148912
+        <rdar://problem/22596272>
+
+        Reviewed by Tim Horton.
+
+        * WebCoreSupport/WebChromeClient.h:
+        * WebCoreSupport/WebChromeClient.mm:
+        (WebChromeClient::setMockMediaPlaybackTargetPickerEnabled): New.
+        (WebChromeClient::setMockMediaPlaybackTargetPickerState): Ditto.
+
+        * WebView/WebMediaPlaybackTargetPicker.h:
+        * WebView/WebMediaPlaybackTargetPicker.mm:
+        (WebMediaPlaybackTargetPicker::setMockMediaPlaybackTargetPickerEnabled): New.
+        (WebMediaPlaybackTargetPicker::setMockMediaPlaybackTargetPickerState): Ditto.
+
+        * WebView/WebView.mm:
+        (-[WebView _setMockMediaPlaybackTargetPickerEnabled:]): New.
+        (-[WebView _setMockMediaPlaybackTargetPickerName:state:]): Ditto.
+        * WebView/WebViewInternal.h:
+
 2015-11-07  Simon Fraser  <simon.fraser@apple.com>
 
         Remove ColorSpace argument to all the drawing calls
index d755fc7..d335218 100644 (file)
@@ -211,10 +211,12 @@ public:
 #endif
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
-    virtual void addPlaybackTargetPickerClient(uint64_t /*contextId*/) override;
-    virtual void removePlaybackTargetPickerClient(uint64_t /*contextId*/) override;
-    virtual void showPlaybackTargetPicker(uint64_t /*contextId*/, const WebCore::IntPoint&, bool /* hasVideo */) override;
-    virtual void playbackTargetPickerClientStateDidChange(uint64_t /*contextId*/, WebCore::MediaProducer::MediaStateFlags) override;
+    void addPlaybackTargetPickerClient(uint64_t /*contextId*/) override;
+    void removePlaybackTargetPickerClient(uint64_t /*contextId*/) override;
+    void showPlaybackTargetPicker(uint64_t /*contextId*/, const WebCore::IntPoint&, bool /* hasVideo */) override;
+    void playbackTargetPickerClientStateDidChange(uint64_t /*contextId*/, WebCore::MediaProducer::MediaStateFlags) override;
+    void setMockMediaPlaybackTargetPickerEnabled(bool) override;
+    void setMockMediaPlaybackTargetPickerState(const String&, WebCore::MediaPlaybackTargetContext::State) override;
 #endif
 
 private:
index 509eb95..db3ab2d 100644 (file)
@@ -1041,4 +1041,15 @@ void WebChromeClient::playbackTargetPickerClientStateDidChange(uint64_t contextI
 {
     [m_webView _playbackTargetPickerClientStateDidChange:contextId state:state];
 }
+
+void WebChromeClient::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+    [m_webView _setMockMediaPlaybackTargetPickerEnabled:enabled];
+}
+
+void WebChromeClient::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
+{
+    [m_webView _setMockMediaPlaybackTargetPickerName:name state:state];
+}
+
 #endif
index 170ac31..dd1ed2c 100644 (file)
@@ -26,6 +26,7 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
 
 #include <WebCore/MediaPlaybackTarget.h>
+#include <WebCore/MediaPlaybackTargetContext.h>
 #include <WebCore/WebMediaSessionManagerClient.h>
 #include <wtf/Ref.h>
 
@@ -46,6 +47,8 @@ public:
     void removePlaybackTargetPickerClient(uint64_t);
     void showPlaybackTargetPicker(uint64_t, const WebCore::FloatRect&, bool hasVideo);
     void playbackTargetPickerClientStateDidChange(uint64_t, WebCore::MediaProducer::MediaStateFlags);
+    void setMockMediaPlaybackTargetPickerEnabled(bool);
+    void setMockMediaPlaybackTargetPickerState(const String&, WebCore::MediaPlaybackTargetContext::State);
 
     // WebMediaSessionManagerClient
     virtual void setPlaybackTarget(uint64_t, Ref<WebCore::MediaPlaybackTarget>&&) override;
index b0ba971..9785313 100644 (file)
@@ -61,6 +61,16 @@ void WebMediaPlaybackTargetPicker::playbackTargetPickerClientStateDidChange(uint
     WebCore::WebMediaSessionManager::shared().clientStateDidChange(*this, contextId, state);
 }
 
+void WebMediaPlaybackTargetPicker::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+    WebCore::WebMediaSessionManager::shared().setMockMediaPlaybackTargetPickerEnabled(enabled);
+}
+
+void WebMediaPlaybackTargetPicker::setMockMediaPlaybackTargetPickerState(const String& name, WebCore::MediaPlaybackTargetContext::State state)
+{
+    WebCore::WebMediaSessionManager::shared().setMockMediaPlaybackTargetPickerState(name, state);
+}
+
 void WebMediaPlaybackTargetPicker::setPlaybackTarget(uint64_t contextId, Ref<WebCore::MediaPlaybackTarget>&& target)
 {
     if (!m_page)
index 0805221..9b9cabb 100644 (file)
@@ -8666,6 +8666,16 @@ bool LayerFlushController::flushLayers()
 {
     [self _devicePicker]->playbackTargetPickerClientStateDidChange(clientId, state);
 }
+
+- (void)_setMockMediaPlaybackTargetPickerEnabled:(bool)enabled
+{
+    [self _devicePicker]->setMockMediaPlaybackTargetPickerEnabled(enabled);
+}
+
+- (void)_setMockMediaPlaybackTargetPickerName:(NSString *)name state:(WebCore::MediaPlaybackTargetContext::State)state
+{
+    [self _devicePicker]->setMockMediaPlaybackTargetPickerState(name, state);
+}
 #endif
 
 @end
index 8057ea7..47d631b 100644 (file)
@@ -65,6 +65,7 @@ class WebMediaPlaybackTargetPicker;
 class WebSelectionServiceController;
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
+#import <WebCore/MediaPlaybackTargetContext.h>
 #import <WebCore/MediaProducer.h>
 #endif
 
@@ -284,6 +285,8 @@ OBJC_CLASS NSTextAlternatives;
 - (void)_removePlaybackTargetPickerClient:(uint64_t)contextId;
 - (void)_showPlaybackTargetPicker:(uint64_t)contextId location:(const WebCore::IntPoint&)location hasVideo:(BOOL)hasVideo;
 - (void)_playbackTargetPickerClientStateDidChange:(uint64_t)contextId state:(WebCore::MediaProducer::MediaStateFlags)state;
+- (void)_setMockMediaPlaybackTargetPickerEnabled:(bool)enabled;
+- (void)_setMockMediaPlaybackTargetPickerName:(NSString *)name state:(WebCore::MediaPlaybackTargetContext::State)state;
 #endif
 
 @end
index 7115dac..6a086bf 100644 (file)
@@ -1,3 +1,40 @@
+2015-11-09  Eric Carlson  <eric.carlson@apple.com>
+
+        [Mac] Add a mock AppleTV device for testing
+        https://bugs.webkit.org/show_bug.cgi?id=148912
+        <rdar://problem/22596272>
+
+        Reviewed by Tim Horton.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<MediaPlaybackTargetContext>::encode): Update for MediaPlaybackTargetContext changes.
+        (IPC::ArgumentCoder<MediaPlaybackTargetContext>::decode): Ditto.
+        * Shared/WebCoreArgumentCoders.h:
+
+        * Shared/mac/WebCoreArgumentCodersMac.mm:
+        (IPC::ArgumentCoder<MediaPlaybackTargetContext>::encodePlatformData): Ditto.
+        (IPC::ArgumentCoder<MediaPlaybackTargetContext>::decodePlatformData): Ditto.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::setMockMediaPlaybackTargetPickerEnabled): New.
+        (WebKit::WebPageProxy::setMockMediaPlaybackTargetPickerState): Ditto.
+        * UIProcess/WebPageProxy.h:
+
+        * UIProcess/WebPageProxy.messages.in: Add SetMockMediaPlaybackTargetPickerEnabled and 
+          SetMockMediaPlaybackTargetPickerState.
+
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::setMockMediaPlaybackTargetPickerEnabled): New.
+        (WebKit::WebChromeClient::setMockMediaPlaybackTargetPickerState): Ditto.
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+
+        * WebProcess/WebPage/WebPage.h: MediaPlaybackTargetContext is a class, not a struct.
+
+        * WebProcess/WebPage/WebPage.messages.in: Ditto.
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::playbackTargetSelected): Support mock target.
+
 2015-11-09  Ryuan Choi  <ryuan.choi@navercorp.com>
 
         [EFL] Crash while opening child webview with EWK_PROCESS_MODEL_MULTIPLE_SECONDARY
index 728f807..11ff994 100644 (file)
@@ -1969,26 +1969,47 @@ bool ArgumentCoder<TextIndicatorData>::decode(ArgumentDecoder& decoder, TextIndi
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 void ArgumentCoder<MediaPlaybackTargetContext>::encode(ArgumentEncoder& encoder, const MediaPlaybackTargetContext& target)
 {
-    int32_t targetType = target.type;
+    bool hasPlatformData = target.encodingRequiresPlatformData();
+    encoder << hasPlatformData;
+
+    int32_t targetType = target.type();
     encoder << targetType;
 
-    if (!target.encodingRequiresPlatformData())
+    if (target.encodingRequiresPlatformData()) {
+        encodePlatformData(encoder, target);
         return;
+    }
 
-    encodePlatformData(encoder, target);
+    ASSERT(targetType == MediaPlaybackTargetContext::MockType);
+    encoder << target.mockDeviceName();
+    encoder << static_cast<int32_t>(target.mockState());
 }
 
 bool ArgumentCoder<MediaPlaybackTargetContext>::decode(ArgumentDecoder& decoder, MediaPlaybackTargetContext& target)
 {
+    bool hasPlatformData;
+    if (!decoder.decode(hasPlatformData))
+        return false;
+
     int32_t targetType;
     if (!decoder.decode(targetType))
         return false;
 
-    target.type = static_cast<MediaPlaybackTargetContext::ContextType>(targetType);
-    if (!target.encodingRequiresPlatformData())
+    if (hasPlatformData)
+        return decodePlatformData(decoder, target);
+
+    ASSERT(targetType == MediaPlaybackTargetContext::MockType);
+
+    String mockDeviceName;
+    if (!decoder.decode(mockDeviceName))
         return false;
 
-    return decodePlatformData(decoder, target);
+    int32_t mockState;
+    if (!decoder.decode(mockState))
+        return false;
+
+    target = MediaPlaybackTargetContext(mockDeviceName, static_cast<MediaPlaybackTargetContext::State>(mockState));
+    return true;
 }
 #endif
 
index 46e7c12..baca34c 100644 (file)
@@ -114,7 +114,7 @@ class ContentFilterUnblockHandler;
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 namespace WebCore {
-struct MediaPlaybackTargetContext;
+class MediaPlaybackTargetContext;
 }
 #endif
 
index ccc6be2..dffb3e0 100644 (file)
@@ -491,14 +491,12 @@ static NSString *deviceContextKey()
 
 void ArgumentCoder<MediaPlaybackTargetContext>::encodePlatformData(ArgumentEncoder& encoder, const MediaPlaybackTargetContext& target)
 {
-    ASSERT(target.type == MediaPlaybackTargetContext::AVOutputContextType);
-
     RetainPtr<NSMutableData> data = adoptNS([[NSMutableData alloc] init]);
     RetainPtr<NSKeyedArchiver> archiver = adoptNS([[NSKeyedArchiver alloc] initForWritingWithMutableData:data.get()]);
     [archiver setRequiresSecureCoding:YES];
 
     if ([getAVOutputContextClass() conformsToProtocol:@protocol(NSSecureCoding)])
-        [archiver encodeObject:target.context.avOutputContext forKey:deviceContextKey()];
+        [archiver encodeObject:target.avOutputContext() forKey:deviceContextKey()];
 
     [archiver finishEncoding];
     IPC::encode(encoder, reinterpret_cast<CFDataRef>(data.get()));
@@ -507,8 +505,6 @@ void ArgumentCoder<MediaPlaybackTargetContext>::encodePlatformData(ArgumentEncod
 
 bool ArgumentCoder<MediaPlaybackTargetContext>::decodePlatformData(ArgumentDecoder& decoder, MediaPlaybackTargetContext& target)
 {
-    ASSERT(target.type == MediaPlaybackTargetContext::AVOutputContextType);
-
     if (![getAVOutputContextClass() conformsToProtocol:@protocol(NSSecureCoding)])
         return false;
 
@@ -523,11 +519,11 @@ bool ArgumentCoder<MediaPlaybackTargetContext>::decodePlatformData(ArgumentDecod
     @try {
         context = [unarchiver decodeObjectOfClass:getAVOutputContextClass() forKey:deviceContextKey()];
     } @catch (NSException *exception) {
-        LOG_ERROR("The target picker being decoded is not a AVOutputContext.");
+        LOG_ERROR("The target picker being decoded is not an AVOutputContext.");
         return false;
     }
 
-    target.context.avOutputContext = context;
+    target = MediaPlaybackTargetContext(context);
     
     [unarchiver finishDecoding];
     return true;
index d5a8701..c712a1a 100644 (file)
@@ -6017,6 +6017,16 @@ void WebPageProxy::playbackTargetPickerClientStateDidChange(uint64_t contextId,
     m_pageClient.mediaSessionManager().clientStateDidChange(*this, contextId, state);
 }
 
+void WebPageProxy::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+    m_pageClient.mediaSessionManager().setMockMediaPlaybackTargetPickerEnabled(enabled);
+}
+
+void WebPageProxy::setMockMediaPlaybackTargetPickerState(const String& name, WebCore::MediaPlaybackTargetContext::State state)
+{
+    m_pageClient.mediaSessionManager().setMockMediaPlaybackTargetPickerState(name, state);
+}
+
 void WebPageProxy::setPlaybackTarget(uint64_t contextId, Ref<MediaPlaybackTarget>&& target)
 {
     if (!isValid())
index 314ae73..a42bbbb 100644 (file)
@@ -1065,6 +1065,8 @@ public:
     void removePlaybackTargetPickerClient(uint64_t);
     void showPlaybackTargetPicker(uint64_t, const WebCore::FloatRect&, bool hasVideo);
     void playbackTargetPickerClientStateDidChange(uint64_t, WebCore::MediaProducer::MediaStateFlags);
+    void setMockMediaPlaybackTargetPickerEnabled(bool);
+    void setMockMediaPlaybackTargetPickerState(const String&, WebCore::MediaPlaybackTargetContext::State);
 
     // WebMediaSessionManagerClient
     virtual void setPlaybackTarget(uint64_t, Ref<WebCore::MediaPlaybackTarget>&&) override;
index 114291e..64f0fe9 100644 (file)
@@ -433,6 +433,8 @@ messages -> WebPageProxy {
     RemovePlaybackTargetPickerClient(uint64_t contextId)
     ShowPlaybackTargetPicker(uint64_t clientId, WebCore::FloatRect pickerLocation, bool hasVideo)
     PlaybackTargetPickerClientStateDidChange(uint64_t contextId, unsigned mediaState)
+    SetMockMediaPlaybackTargetPickerEnabled(bool enabled)
+    SetMockMediaPlaybackTargetPickerState(String name, unsigned pickerState)
 #endif
 
     ImageOrMediaDocumentSizeChanged(WebCore::IntSize newSize)
index 636dccd..4200c3e 100644 (file)
@@ -1128,6 +1128,16 @@ void WebChromeClient::playbackTargetPickerClientStateDidChange(uint64_t contextI
 {
     m_page->send(Messages::WebPageProxy::PlaybackTargetPickerClientStateDidChange(contextId, state));
 }
+
+void WebChromeClient::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+    m_page->send(Messages::WebPageProxy::SetMockMediaPlaybackTargetPickerEnabled(enabled));
+}
+
+void WebChromeClient::setMockMediaPlaybackTargetPickerState(const String& name, WebCore::MediaPlaybackTargetContext::State state)
+{
+    m_page->send(Messages::WebPageProxy::SetMockMediaPlaybackTargetPickerState(name, state));
+}
 #endif
 
 void WebChromeClient::imageOrMediaDocumentSizeChanged(const WebCore::IntSize& newSize)
index 1821b46..6e5144e 100644 (file)
@@ -315,10 +315,12 @@ private:
     virtual void handleAutoFillButtonClick(WebCore::HTMLInputElement&) override;
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
-    virtual void addPlaybackTargetPickerClient(uint64_t /*contextId*/) override;
-    virtual void removePlaybackTargetPickerClient(uint64_t /*contextId*/) override;
-    virtual void showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint&, bool) override;
-    virtual void playbackTargetPickerClientStateDidChange(uint64_t, WebCore::MediaProducer::MediaStateFlags) override;
+    void addPlaybackTargetPickerClient(uint64_t /*contextId*/) override;
+    void removePlaybackTargetPickerClient(uint64_t /*contextId*/) override;
+    void showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint&, bool) override;
+    void playbackTargetPickerClientStateDidChange(uint64_t, WebCore::MediaProducer::MediaStateFlags) override;
+    void setMockMediaPlaybackTargetPickerEnabled(bool) override;
+    void setMockMediaPlaybackTargetPickerState(const String&, WebCore::MediaPlaybackTargetContext::State) override;
 #endif
 
     virtual void imageOrMediaDocumentSizeChanged(const WebCore::IntSize&) override;
index d985428..f114dc1 100644 (file)
@@ -131,6 +131,7 @@ class HTMLPlugInElement;
 class HTMLPlugInImageElement;
 class IntPoint;
 class KeyboardEvent;
+class MediaPlaybackTargetContext;
 class Page;
 class PrintContext;
 class Range;
@@ -143,7 +144,6 @@ class URL;
 class VisibleSelection;
 struct Highlight;
 struct KeypressCommand;
-struct MediaPlaybackTargetContext;
 struct TextCheckingResult;
 
 #if ENABLE(VIDEO) && USE(GSTREAMER)
index de8e132..30ef809 100644 (file)
@@ -420,7 +420,7 @@ messages -> WebPage LegacyReceiver {
     SetShouldDispatchFakeMouseMoveEvents(bool shouldDispatchFakeMouseMoveEvents)
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
-    PlaybackTargetSelected(uint64_t contextId, struct WebCore::MediaPlaybackTargetContext target)
+    PlaybackTargetSelected(uint64_t contextId, WebCore::MediaPlaybackTargetContext target)
     PlaybackTargetAvailabilityDidChange(uint64_t contextId, bool available)
     SetShouldPlayToPlaybackTarget(uint64_t contextId, bool shouldPlay)
 #endif
index 0542f91..fd01029 100644 (file)
@@ -90,6 +90,7 @@
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 #include <WebCore/MediaPlaybackTargetMac.h>
+#include <WebCore/MediaPlaybackTargetMock.h>
 #endif
 
 using namespace WebCore;
@@ -1261,9 +1262,17 @@ void WebPage::setFont(const String& fontFamily, double fontSize, uint64_t fontTr
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
 void WebPage::playbackTargetSelected(uint64_t contextId, const WebCore::MediaPlaybackTargetContext& targetContext) const
 {
-    ASSERT(targetContext.type == MediaPlaybackTargetContext::AVOutputContextType);
-
-    m_page->setPlaybackTarget(contextId, WebCore::MediaPlaybackTargetMac::create(targetContext.context.avOutputContext));
+    switch (targetContext.type()) {
+    case MediaPlaybackTargetContext::AVOutputContextType:
+        m_page->setPlaybackTarget(contextId, WebCore::MediaPlaybackTargetMac::create(targetContext.avOutputContext()));
+        break;
+    case MediaPlaybackTargetContext::MockType:
+        m_page->setPlaybackTarget(contextId, WebCore::MediaPlaybackTargetMock::create(targetContext.mockDeviceName(), targetContext.mockState()));
+        break;
+    case MediaPlaybackTargetContext::None:
+        ASSERT_NOT_REACHED();
+        break;
+    }
 }
 
 void WebPage::playbackTargetAvailabilityDidChange(uint64_t contextId, bool changed)