Unreviewed, rolling out r220288.
[WebKit-https.git] / Source / WebKit / UIProcess / ios / forms / WKAirPlayRoutePicker.mm
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKAirPlayRoutePicker.h"
28
29 #if PLATFORM(IOS)
30
31 #import "UIKitSPI.h"
32 #import "WKContentView.h"
33 #import "WKContentViewInteraction.h"
34 #import "WebPageProxy.h"
35 #import <WebCore/MediaPlayerSPI.h>
36 #import <wtf/RetainPtr.h>
37 #import <wtf/SoftLinking.h>
38
39 #pragma clang diagnostic push
40 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
41
42 SOFT_LINK_FRAMEWORK(MediaPlayer)
43 SOFT_LINK_CLASS(MediaPlayer, MPAVRoutingController)
44 SOFT_LINK_CLASS(MediaPlayer, MPAudioVideoRoutingPopoverController)
45 SOFT_LINK_CLASS(MediaPlayer, MPAVRoutingSheet)
46
47 using namespace WebKit;
48
49 @implementation WKAirPlayRoutePicker {
50     RetainPtr<MPAVRoutingController> _routingController;
51     RetainPtr<MPAudioVideoRoutingPopoverController> _popoverController;  // iPad
52     RetainPtr<MPAVRoutingSheet> _actionSheet; // iPhone
53     WKContentView* _view; // Weak reference.
54 }
55
56 - (instancetype)initWithView:(WKContentView *)view
57 {
58     if (!(self = [super init]))
59         return nil;
60
61     _view = view;
62     return self;
63 }
64
65 - (void)dealloc
66 {
67     // The ActionSheet's completion handler will release and clear the ActionSheet.
68     [_actionSheet dismiss];
69     [self _dismissAirPlayRoutePickerIPad];
70
71     [super dealloc];
72 }
73
74 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
75 {
76     if (popoverController != _popoverController)
77         return;
78
79     [self _dismissAirPlayRoutePickerIPad];
80 }
81
82 - (void)_presentAirPlayPopoverAnimated:(BOOL)animated fromRect:(CGRect)elementRect
83 {
84     [_popoverController presentPopoverFromRect:elementRect inView:_view permittedArrowDirections:UIPopoverArrowDirectionAny animated:animated];
85 }
86
87 - (void)_windowWillRotate:(NSNotification *)notification
88 {
89     [_popoverController dismissPopoverAnimated:NO];
90 }
91
92 - (void)_windowDidRotate:(NSNotification *)notification
93 {
94     [self _dismissAirPlayRoutePickerIPad];
95 }
96
97 - (void)_dismissAirPlayRoutePickerIPad
98 {
99     if (!_routingController)
100         return;
101
102     [_routingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
103     _routingController = nil;
104
105     if (!_popoverController)
106         return;
107
108     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
109     [center removeObserver:self name:UIWindowWillRotateNotification object:nil];
110     [center removeObserver:self name:UIWindowDidRotateNotification object:nil];
111
112     [_popoverController dismissPopoverAnimated:NO];
113     [_popoverController setDelegate:nil];
114     _popoverController = nil;
115 }
116
117 - (void)showAirPlayPickerIPad:(MPAVItemType)itemType fromRect:(CGRect)elementRect
118 {
119     if (_popoverController)
120         return;
121
122     _popoverController = adoptNS([allocMPAudioVideoRoutingPopoverControllerInstance() initWithType:itemType]);
123     [_popoverController setDelegate:self];
124
125     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
126     [center addObserver:self selector:@selector(_windowWillRotate:) name:UIWindowWillRotateNotification object:nil];
127     [center addObserver:self selector:@selector(_windowDidRotate:) name:UIWindowDidRotateNotification object:nil];
128
129     [self _presentAirPlayPopoverAnimated:YES fromRect:elementRect];
130 }
131
132 - (void)showAirPlayPickerIPhone:(MPAVItemType)itemType
133 {
134     if (_actionSheet)
135         return;
136
137     _actionSheet = adoptNS([allocMPAVRoutingSheetInstance() initWithAVItemType:itemType]);
138
139     [_actionSheet showInView:_view withCompletionHandler:^{
140         [_routingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
141         _routingController = nil;
142         _actionSheet = nil;
143     }];
144 }
145
146 - (void)show:(BOOL)hasVideo fromRect:(CGRect)elementRect
147 {
148     _routingController = adoptNS([allocMPAVRoutingControllerInstance() initWithName:@"WebKit2 - HTML media element showing AirPlay route picker"]);
149     [_routingController setDiscoveryMode:MPRouteDiscoveryModeDetailed];
150
151     MPAVItemType itemType = hasVideo ? MPAVItemTypeVideo : MPAVItemTypeAudio;
152     if (UICurrentUserInterfaceIdiomIsPad())
153         [self showAirPlayPickerIPad:itemType fromRect:elementRect];
154     else
155         [self showAirPlayPickerIPhone:itemType];
156 }
157
158 @end
159
160 #pragma clang diagnostic pop
161
162 #endif // PLATFORM(IOS)