OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/web/external_app_launcher.h" | 5 #import "ios/chrome/browser/web/external_app_launcher.h" |
6 | 6 |
| 7 #include "base/ios/ios_util.h" |
7 #include "base/ios/weak_nsobject.h" | 8 #include "base/ios/weak_nsobject.h" |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
10 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
11 #include "components/strings/grit/components_strings.h" | 12 #include "components/strings/grit/components_strings.h" |
12 #include "ios/chrome/browser/experimental_flags.h" | 13 #include "ios/chrome/browser/experimental_flags.h" |
13 #import "ios/chrome/browser/open_url_util.h" | 14 #import "ios/chrome/browser/open_url_util.h" |
14 #include "ios/chrome/grit/ios_strings.h" | 15 #include "ios/chrome/grit/ios_strings.h" |
15 #import "net/base/mac/url_conversions.h" | 16 #import "net/base/mac/url_conversions.h" |
16 #include "ui/base/l10n/l10n_util.h" | 17 #include "ui/base/l10n/l10n_util.h" |
(...skipping 23 matching lines...) Expand all Loading... |
40 return [ITMSSchemes() containsObject:base::SysUTF8ToNSString(scheme)]; | 41 return [ITMSSchemes() containsObject:base::SysUTF8ToNSString(scheme)]; |
41 } | 42 } |
42 | 43 |
43 // Logs an entry for |Tab.ExternalApplicationOpened|. If the user decided to | 44 // Logs an entry for |Tab.ExternalApplicationOpened|. If the user decided to |
44 // open in an external app, pass true. Otherwise, if the user cancelled the | 45 // open in an external app, pass true. Otherwise, if the user cancelled the |
45 // opening, pass false. | 46 // opening, pass false. |
46 void RecordExternalApplicationOpened(bool opened) { | 47 void RecordExternalApplicationOpened(bool opened) { |
47 UMA_HISTOGRAM_BOOLEAN("Tab.ExternalApplicationOpened", opened); | 48 UMA_HISTOGRAM_BOOLEAN("Tab.ExternalApplicationOpened", opened); |
48 } | 49 } |
49 | 50 |
| 51 // Returns whether gURL has the scheme of a URL that initiates a call. |
| 52 BOOL UrlHasPhoneCallScheme(const GURL& gURL) { |
| 53 return gURL.SchemeIs("tel") || gURL.SchemeIs("facetime") || |
| 54 gURL.SchemeIs("facetime-audio"); |
| 55 } |
| 56 |
| 57 // Returns a string to be used as the label for the prompt's action button. |
| 58 NSString* PromptActionString(NSString* scheme) { |
| 59 if ([scheme isEqualToString:@"facetime"]) |
| 60 return l10n_util::GetNSString(IDS_IOS_FACETIME_BUTTON); |
| 61 else if ([scheme isEqualToString:@"tel"] || |
| 62 [scheme isEqualToString:@"facetime-audio"]) |
| 63 return l10n_util::GetNSString(IDS_IOS_PHONE_CALL_BUTTON); |
| 64 NOTREACHED(); |
| 65 return @""; |
| 66 } |
| 67 |
50 } // namespace | 68 } // namespace |
51 | 69 |
52 @interface ExternalAppLauncher () | 70 @interface ExternalAppLauncher () |
53 // Returns the Phone/FaceTime call argument from |URL|. | 71 // Returns the Phone/FaceTime call argument from |URL|. |
54 + (NSString*)formatCallArgument:(NSURL*)URL; | 72 + (NSString*)formatCallArgument:(NSURL*)URL; |
55 // Ask user for confirmation before dialing FaceTime destination. | 73 // Ask user for confirmation before dialing Phone or FaceTime destinations. |
56 - (void)openFaceTimePromptForURL:(NSURL*)telURL; | 74 - (void)openPromptForURL:(NSURL*)URL; |
57 // Ask user for confirmation before moving to external app. | 75 // Ask user for confirmation before moving to external app. |
58 - (void)openExternalAppWithPromptForURL:(NSURL*)URL; | 76 - (void)openExternalAppWithPromptForURL:(NSURL*)URL; |
59 // Presents a configured alert controller on the root view controller. | 77 // Presents a configured alert controller on the root view controller. |
60 - (void)presentAlertControllerWithMessage:(NSString*)message | 78 - (void)presentAlertControllerWithMessage:(NSString*)message |
61 openTitle:(NSString*)openTitle | 79 openTitle:(NSString*)openTitle |
62 openHandler:(AlertHandler)openHandler | 80 openHandler:(AlertHandler)openHandler |
63 cancelHandler:(AlertHandler)cancelHandler; | 81 cancelHandler:(AlertHandler)cancelHandler; |
64 @end | 82 @end |
65 | 83 |
66 @implementation ExternalAppLauncher | 84 @implementation ExternalAppLauncher |
(...skipping 22 matching lines...) Expand all Loading... |
89 openTitle:openTitle | 107 openTitle:openTitle |
90 openHandler:^(UIAlertAction* action) { | 108 openHandler:^(UIAlertAction* action) { |
91 RecordExternalApplicationOpened(true); | 109 RecordExternalApplicationOpened(true); |
92 OpenUrlWithCompletionHandler(URL, nil); | 110 OpenUrlWithCompletionHandler(URL, nil); |
93 } | 111 } |
94 cancelHandler:^(UIAlertAction* action) { | 112 cancelHandler:^(UIAlertAction* action) { |
95 RecordExternalApplicationOpened(false); | 113 RecordExternalApplicationOpened(false); |
96 }]; | 114 }]; |
97 } | 115 } |
98 | 116 |
99 - (void)openFaceTimePromptForURL:(NSURL*)URL { | 117 - (void)openPromptForURL:(NSURL*)URL { |
100 NSString* openTitle = l10n_util::GetNSString(IDS_IOS_FACETIME_BUTTON); | |
101 [self presentAlertControllerWithMessage:[[self class] formatCallArgument:URL] | 118 [self presentAlertControllerWithMessage:[[self class] formatCallArgument:URL] |
102 openTitle:openTitle | 119 openTitle:PromptActionString(URL.scheme) |
103 openHandler:^(UIAlertAction* action) { | 120 openHandler:^(UIAlertAction* action) { |
104 OpenUrlWithCompletionHandler(URL, nil); | 121 OpenUrlWithCompletionHandler(URL, nil); |
105 } | 122 } |
106 cancelHandler:nil]; | 123 cancelHandler:nil]; |
107 } | 124 } |
108 | 125 |
109 - (void)presentAlertControllerWithMessage:(NSString*)message | 126 - (void)presentAlertControllerWithMessage:(NSString*)message |
110 openTitle:(NSString*)openTitle | 127 openTitle:(NSString*)openTitle |
111 openHandler:(AlertHandler)openHandler | 128 openHandler:(AlertHandler)openHandler |
112 cancelHandler:(AlertHandler)cancelHandler { | 129 cancelHandler:(AlertHandler)cancelHandler { |
(...skipping 16 matching lines...) Expand all Loading... |
129 presentViewController:alertController | 146 presentViewController:alertController |
130 animated:YES | 147 animated:YES |
131 completion:nil]; | 148 completion:nil]; |
132 } | 149 } |
133 | 150 |
134 - (BOOL)openURL:(const GURL&)gURL linkClicked:(BOOL)linkClicked { | 151 - (BOOL)openURL:(const GURL&)gURL linkClicked:(BOOL)linkClicked { |
135 if (!gURL.is_valid() || !gURL.has_scheme()) | 152 if (!gURL.is_valid() || !gURL.has_scheme()) |
136 return NO; | 153 return NO; |
137 NSURL* URL = net::NSURLWithGURL(gURL); | 154 NSURL* URL = net::NSURLWithGURL(gURL); |
138 | 155 |
139 if (gURL.SchemeIs("facetime") || gURL.SchemeIs("facetime-audio")) { | 156 // iOS 10.3.2 introduced new prompts when facetime: and facetime-audio: |
| 157 // URL schemes are opened. It is no longer necessary for Chrome to present |
| 158 // another prompt before the system-provided prompt. |
| 159 if (!base::ios::IsRunningOnOrLater(10, 3, 2) && UrlHasPhoneCallScheme(gURL)) { |
140 // Showing an alert view immediately has a side-effect where focus is | 160 // Showing an alert view immediately has a side-effect where focus is |
141 // taken from the UIWebView so quickly that mouseup events are lost and | 161 // taken from the UIWebView so quickly that mouseup events are lost and |
142 // buttons get 'stuck' in the on position. The solution is to defer | 162 // buttons get 'stuck' in the on position. The solution is to defer |
143 // showing the view. | 163 // showing the view. |
144 [self performSelector:@selector(openFaceTimePromptForURL:) | 164 [self performSelector:@selector(openPromptForURL:) |
145 withObject:URL | 165 withObject:URL |
146 afterDelay:0.0]; | 166 afterDelay:0.0]; |
147 return YES; | 167 return YES; |
148 } | 168 } |
149 | 169 |
150 // Use telprompt instead of tel because telprompt returns user back to | |
151 // Chrome after phone call is completed/aborted. | |
152 if (gURL.SchemeIs("tel")) { | |
153 GURL::Replacements replacements; | |
154 replacements.SetSchemeStr("telprompt"); | |
155 URL = net::NSURLWithGURL(gURL.ReplaceComponents(replacements)); | |
156 DCHECK([[URL scheme] isEqualToString:@"telprompt"]); | |
157 } | |
158 | |
159 // Don't open external application if chrome is not active. | 170 // Don't open external application if chrome is not active. |
160 if ([[UIApplication sharedApplication] applicationState] != | 171 if ([[UIApplication sharedApplication] applicationState] != |
161 UIApplicationStateActive) | 172 UIApplicationStateActive) |
162 return NO; | 173 return NO; |
163 | 174 |
164 if (experimental_flags::IsExternalApplicationPromptEnabled()) { | 175 if (experimental_flags::IsExternalApplicationPromptEnabled()) { |
165 // Prompt user to open itunes when opening it is not a result of a link | 176 // Prompt user to open itunes when opening it is not a result of a link |
166 // click. | 177 // click. |
167 if (!linkClicked && UrlHasAppStoreScheme(gURL)) { | 178 if (!linkClicked && UrlHasAppStoreScheme(gURL)) { |
168 [self performSelector:@selector(openExternalAppWithPromptForURL:) | 179 [self performSelector:@selector(openExternalAppWithPromptForURL:) |
169 withObject:URL | 180 withObject:URL |
170 afterDelay:0.0]; | 181 afterDelay:0.0]; |
171 return YES; | 182 return YES; |
172 } | 183 } |
173 } | 184 } |
174 | 185 |
175 // If the following call returns YES, an external application is about to be | 186 // If the following call returns YES, an external application is about to be |
176 // launched and Chrome will go into the background now. | 187 // launched and Chrome will go into the background now. |
177 // TODO(crbug.com/622735): This call still needs to be updated. | 188 // TODO(crbug.com/622735): This call still needs to be updated. |
178 // It's heavily nested so some refactoring is needed. | 189 // It's heavily nested so some refactoring is needed. |
179 return [[UIApplication sharedApplication] openURL:URL]; | 190 return [[UIApplication sharedApplication] openURL:URL]; |
180 } | 191 } |
181 | 192 |
182 @end | 193 @end |
OLD | NEW |