OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 package org.chromium.chrome.browser.externalnav; | 5 package org.chromium.chrome.browser.externalnav; |
6 | 6 |
7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.app.Activity; | 8 import android.app.Activity; |
9 import android.content.ActivityNotFoundException; | 9 import android.content.ActivityNotFoundException; |
10 import android.content.ComponentName; | 10 import android.content.ComponentName; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 // - http://crbug.com/159153 : Don't override http or https URLs from th e NTP or bookmarks. | 101 // - http://crbug.com/159153 : Don't override http or https URLs from th e NTP or bookmarks. |
102 // - http://crbug.com/162106: Intent picker should not be presented on r eturning to a page. | 102 // - http://crbug.com/162106: Intent picker should not be presented on r eturning to a page. |
103 // This should be covered by not showing the picker if the core type i s reload. | 103 // This should be covered by not showing the picker if the core type i s reload. |
104 | 104 |
105 // http://crbug.com/164194 . A navigation forwards or backwards should n ever trigger | 105 // http://crbug.com/164194 . A navigation forwards or backwards should n ever trigger |
106 // the intent picker. | 106 // the intent picker. |
107 if (isForwardBackNavigation) { | 107 if (isForwardBackNavigation) { |
108 return OverrideUrlLoadingResult.NO_OVERRIDE; | 108 return OverrideUrlLoadingResult.NO_OVERRIDE; |
109 } | 109 } |
110 | 110 |
111 // http://crbug/331571 : Do not override a navigation started from user typing. | 111 Intent intent; |
112 // http://crbug/424029 : Need to stay in Chrome for an intent heading ex plicitly to Chrome. | 112 // perform generic parsing of the URI to turn it into an Intent. |
113 if (params.getRedirectHandler() != null | 113 try { |
114 && params.getRedirectHandler().shouldStayInChrome()) { | 114 intent = Intent.parseUri(params.getUrl(), Intent.URI_INTENT_SCHEME); |
115 } catch (URISyntaxException ex) { | |
116 Log.w(TAG, "Bad URI " + params.getUrl() + ": " + ex.getMessage()); | |
115 return OverrideUrlLoadingResult.NO_OVERRIDE; | 117 return OverrideUrlLoadingResult.NO_OVERRIDE; |
116 } | 118 } |
117 | 119 |
120 boolean hasBrowserFallbackUrl = false; | |
121 String browserFallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK _URL); | |
122 if (browserFallbackUrl != null | |
123 && UrlUtilities.isValidForIntentFallbackNavigation(browserFallba ckUrl)) { | |
124 hasBrowserFallbackUrl = true; | |
125 } | |
126 | |
127 if (params.getRedirectHandler() != null) { | |
128 // http://crbug/331571 : Do not override a navigation started from u ser typing. | |
129 // http://crbug/424029 : Need to stay in Chrome for an intent headin g explicitly to | |
130 // Chrome. | |
131 if (params.getRedirectHandler().shouldStayInChrome()) { | |
132 if (hasBrowserFallbackUrl) { | |
133 return clobberCurrentTabWithFallbackUrl(browserFallbackUrl, params); | |
134 } else { | |
135 return OverrideUrlLoadingResult.NO_OVERRIDE; | |
136 } | |
137 } else if (params.getRedirectHandler().shouldNotOverrideUrlLoading() ) { | |
138 // For instance, if this is a chained fallback URL, we ignore it . | |
139 return OverrideUrlLoadingResult.NO_OVERRIDE; | |
140 } | |
141 } | |
142 | |
118 // http://crbug.com/149218: We want to show the intent picker for ordina ry links, providing | 143 // http://crbug.com/149218: We want to show the intent picker for ordina ry links, providing |
119 // the link is not an incoming intent from another application, unless i t's a redirect (see | 144 // the link is not an incoming intent from another application, unless i t's a redirect (see |
120 // below). | 145 // below). |
121 boolean linkNotFromIntent = isLink && !isFromIntent; | 146 boolean linkNotFromIntent = isLink && !isFromIntent; |
122 | 147 |
123 boolean isOnEffectiveIntentRedirect = params.getRedirectHandler() == nul l ? false | 148 boolean isOnEffectiveIntentRedirect = params.getRedirectHandler() == nul l ? false |
124 : params.getRedirectHandler().isOnEffectiveIntentRedirectChain() ; | 149 : params.getRedirectHandler().isOnEffectiveIntentRedirectChain() ; |
125 | 150 |
126 // http://crbug.com/170925: We need to show the intent picker when we re ceive an intent from | 151 // http://crbug.com/170925: We need to show the intent picker when we re ceive an intent from |
127 // another app that 30x redirects to a YouTube/Google Maps/Play Store/Go ogle+ URL etc. | 152 // another app that 30x redirects to a YouTube/Google Maps/Play Store/Go ogle+ URL etc. |
(...skipping 13 matching lines...) Expand all Loading... | |
141 // page, there is clear intent to complete the navigation in Chrome. | 166 // page, there is clear intent to complete the navigation in Chrome. |
142 if (params.getReferrerUrl() != null && params.getReferrerUrl().startsWit h( | 167 if (params.getReferrerUrl() != null && params.getReferrerUrl().startsWit h( |
143 UrlConstants.CHROME_SCHEME) && (params.getUrl().startsWith(UrlCo nstants.HTTP_SCHEME) | 168 UrlConstants.CHROME_SCHEME) && (params.getUrl().startsWith(UrlCo nstants.HTTP_SCHEME) |
144 || params.getUrl().startsWith(UrlConstants.HTTPS_SCHEME) )) { | 169 || params.getUrl().startsWith(UrlConstants.HTTPS_SCHEME) )) { |
145 return OverrideUrlLoadingResult.NO_OVERRIDE; | 170 return OverrideUrlLoadingResult.NO_OVERRIDE; |
146 } | 171 } |
147 | 172 |
148 if (params.getUrl().startsWith(SCHEME_WTAI_MC)) { | 173 if (params.getUrl().startsWith(SCHEME_WTAI_MC)) { |
149 // wtai://wp/mc;number | 174 // wtai://wp/mc;number |
150 // number=string(phone-number) | 175 // number=string(phone-number) |
151 Intent intent = new Intent(Intent.ACTION_VIEW, | 176 mDelegate.startActivity(new Intent(Intent.ACTION_VIEW, |
152 Uri.parse(WebView.SCHEME_TEL | 177 Uri.parse(WebView.SCHEME_TEL |
153 + params.getUrl().substring(SCHEME_WTAI_MC.length()) )); | 178 + params.getUrl().substring(SCHEME_WTAI_MC.length()) ))); |
154 mDelegate.startActivity(intent); | |
155 return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT; | 179 return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT; |
156 } else if (params.getUrl().startsWith(SCHEME_WTAI)) { | 180 } else if (params.getUrl().startsWith(SCHEME_WTAI)) { |
157 // TODO: handle other WTAI schemes. | 181 // TODO: handle other WTAI schemes. |
158 return OverrideUrlLoadingResult.NO_OVERRIDE; | 182 return OverrideUrlLoadingResult.NO_OVERRIDE; |
159 } | 183 } |
160 | 184 |
161 // The "about:" schemes are internal to the browser; don't want these to | 185 // The "about:" schemes are internal to the browser; don't want these to |
162 // be dispatched to other apps. | 186 // be dispatched to other apps. |
163 if (params.getUrl().startsWith("about:")) { | 187 if (params.getUrl().startsWith("about:")) { |
164 return OverrideUrlLoadingResult.NO_OVERRIDE; | 188 return OverrideUrlLoadingResult.NO_OVERRIDE; |
(...skipping 11 matching lines...) Expand all Loading... | |
176 if (params.getUrl().matches(".*youtube\\.com.*[?&]pairingCode=.*")) { | 200 if (params.getUrl().matches(".*youtube\\.com.*[?&]pairingCode=.*")) { |
177 return OverrideUrlLoadingResult.NO_OVERRIDE; | 201 return OverrideUrlLoadingResult.NO_OVERRIDE; |
178 } | 202 } |
179 | 203 |
180 // TODO(changwan): check if we need to handle URL even when external int ent is off. | 204 // TODO(changwan): check if we need to handle URL even when external int ent is off. |
181 if (CommandLine.getInstance().hasSwitch( | 205 if (CommandLine.getInstance().hasSwitch( |
182 ChromeSwitches.DISABLE_EXTERNAL_INTENT_REQUESTS)) { | 206 ChromeSwitches.DISABLE_EXTERNAL_INTENT_REQUESTS)) { |
183 return OverrideUrlLoadingResult.NO_OVERRIDE; | 207 return OverrideUrlLoadingResult.NO_OVERRIDE; |
184 } | 208 } |
185 | 209 |
186 Intent intent; | |
187 // perform generic parsing of the URI to turn it into an Intent. | |
188 try { | |
189 intent = Intent.parseUri(params.getUrl(), Intent.URI_INTENT_SCHEME); | |
190 } catch (URISyntaxException ex) { | |
191 Log.w(TAG, "Bad URI " + params.getUrl() + ": " + ex.getMessage()); | |
192 return OverrideUrlLoadingResult.NO_OVERRIDE; | |
193 } | |
194 | |
195 boolean hasBrowserFallbackUrl = false; | |
196 String browserFallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK _URL); | |
197 if (browserFallbackUrl != null | |
198 && UrlUtilities.isValidForIntentFallbackNavigation(browserFallba ckUrl)) { | |
199 hasBrowserFallbackUrl = true; | |
200 } | |
201 | |
202 // check whether the intent can be resolved. If not, we will see | 210 // check whether the intent can be resolved. If not, we will see |
203 // whether we can download it from the Market. | 211 // whether we can download it from the Market. |
204 if (!mDelegate.canResolveActivity(intent)) { | 212 if (!mDelegate.canResolveActivity(intent)) { |
205 if (hasBrowserFallbackUrl) { | 213 if (hasBrowserFallbackUrl) { |
206 // NOTE: any further redirection from fall-back URL should not o verride URL loading. | 214 return clobberCurrentTabWithFallbackUrl(browserFallbackUrl, para ms); |
207 // Otherwise, it can be used in chain for fingerprinting multipl e app installation | |
208 // status in one shot. In order to prevent this scenario, we not ify redirection | |
209 // handler that redirection from the current navigation should s tay in Chrome. | |
210 if (params.getRedirectHandler() != null) { | |
211 params.getRedirectHandler() | |
212 .setShouldStayInChromeUntilNewUrlLoading(); | |
213 } | |
214 return mDelegate.clobberCurrentTab(browserFallbackUrl, params.ge tReferrerUrl(), | |
215 params.getTab()); | |
216 } | 215 } |
217 String packagename = intent.getPackage(); | 216 String packagename = intent.getPackage(); |
218 if (packagename != null) { | 217 if (packagename != null) { |
219 try { | 218 try { |
220 intent = new Intent(Intent.ACTION_VIEW, Uri.parse( | 219 intent = new Intent(Intent.ACTION_VIEW, Uri.parse( |
221 "market://details?id=" + packagename | 220 "market://details?id=" + packagename |
222 + "&referrer=" + mDelegate.getPackageName())); | 221 + "&referrer=" + mDelegate.getPackageName())); |
223 intent.addCategory(Intent.CATEGORY_BROWSABLE); | 222 intent.addCategory(Intent.CATEGORY_BROWSABLE); |
224 intent.setPackage("com.android.vending"); | 223 intent.setPackage("com.android.vending"); |
225 mDelegate.startActivity(intent); | 224 mDelegate.startActivity(intent); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 } | 331 } |
333 } catch (ActivityNotFoundException ex) { | 332 } catch (ActivityNotFoundException ex) { |
334 // Ignore the error. If no application can handle the URL, | 333 // Ignore the error. If no application can handle the URL, |
335 // assume the browser can handle it. | 334 // assume the browser can handle it. |
336 } | 335 } |
337 | 336 |
338 return OverrideUrlLoadingResult.NO_OVERRIDE; | 337 return OverrideUrlLoadingResult.NO_OVERRIDE; |
339 } | 338 } |
340 | 339 |
341 /** | 340 /** |
341 * Clobber the current tab with fallback URL. | |
342 * | |
343 * @param browserFallbackUrl The fallback URL. | |
344 * @param params The external navigation params. | |
345 * @return {@link OverrideUrlLoadingResult} (if the tab was clobbered, or we launched an | |
346 *intent.) | |
Maria
2015/03/27 00:12:59
indent 8 on second line and don't need parenthesis
Changwan Ryu
2015/03/27 02:09:50
Done.
| |
347 */ | |
348 private OverrideUrlLoadingResult clobberCurrentTabWithFallbackUrl( | |
349 String browserFallbackUrl, ExternalNavigationParams params) { | |
350 // NOTE: any further redirection from fall-back URL should not override URL loading. | |
351 // Otherwise, it can be used in chain for fingerprinting multiple app in stallation | |
352 // status in one shot. In order to prevent this scenario, we notify redi rection | |
353 // handler that redirection from the current navigation should stay in C hrome. | |
354 if (params.getRedirectHandler() != null) { | |
355 params.getRedirectHandler().setShouldNotOverrideUrlLoadingUntilNewUr lLoading(); | |
356 } | |
357 return mDelegate.clobberCurrentTab( | |
358 browserFallbackUrl, params.getReferrerUrl(), params.getTab()); | |
359 } | |
360 | |
361 /** | |
342 * @return Whether the |url| could be handled by an external application on the system. | 362 * @return Whether the |url| could be handled by an external application on the system. |
343 */ | 363 */ |
344 public boolean canExternalAppHandleUrl(String url) { | 364 public boolean canExternalAppHandleUrl(String url) { |
345 if (url.startsWith(SCHEME_WTAI_MC)) return true; | 365 if (url.startsWith(SCHEME_WTAI_MC)) return true; |
346 try { | 366 try { |
347 Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); | 367 Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); |
348 return intent.getPackage() != null || mDelegate.canResolveActivity(i ntent); | 368 return intent.getPackage() != null || mDelegate.canResolveActivity(i ntent); |
349 } catch (URISyntaxException ex) { | 369 } catch (URISyntaxException ex) { |
350 // Ignore the error. | 370 // Ignore the error. |
351 } | 371 } |
352 return false; | 372 return false; |
353 } | 373 } |
354 } | 374 } |
OLD | NEW |