Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 #include "chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog .h" | 5 #include "chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog .h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
|
Luis Héctor Chávez
2016/11/16 03:22:02
nit: remove utility, vector
Yusuke Sato
2016/11/16 06:10:21
Done.
| |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h" | 13 #include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h" |
| 14 #include "chrome/browser/chromeos/external_protocol_dialog.h" | 14 #include "chrome/browser/chromeos/external_protocol_dialog.h" |
| 15 #include "chrome/browser/tab_contents/tab_util.h" | 15 #include "chrome/browser/tab_contents/tab_util.h" |
| 16 #include "chrome/browser/ui/browser_dialogs.h" | 16 #include "chrome/browser/ui/browser_dialogs.h" |
| 17 #include "components/arc/arc_bridge_service.h" | 17 #include "components/arc/arc_bridge_service.h" |
| 18 #include "components/arc/arc_service_manager.h" | 18 #include "components/arc/arc_service_manager.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 | 93 |
| 94 instance->HandleUrl(url_and_package.first.spec(), url_and_package.second); | 94 instance->HandleUrl(url_and_package.first.spec(), url_and_package.second); |
| 95 CloseTabIfNeeded(render_process_host_id, routing_id); | 95 CloseTabIfNeeded(render_process_host_id, routing_id); |
| 96 } | 96 } |
| 97 | 97 |
| 98 // A helper function called by GetAction(). | 98 // A helper function called by GetAction(). |
| 99 GetActionResult GetActionInternal( | 99 GetActionResult GetActionInternal( |
| 100 const GURL& original_url, | 100 const GURL& original_url, |
| 101 const mojom::IntentHandlerInfoPtr& handler, | 101 const mojom::IntentHandlerInfoPtr& handler, |
| 102 std::pair<GURL, std::string>* out_url_and_package) { | 102 std::pair<GURL, std::string>* out_url_and_package) { |
| 103 if (!handler->fallback_url.is_null()) { | 103 if (handler->fallback_url.has_value()) { |
| 104 *out_url_and_package = std::make_pair(GURL(handler->fallback_url.get()), | 104 *out_url_and_package = |
| 105 handler->package_name.get()); | 105 std::make_pair(GURL(*handler->fallback_url), handler->package_name); |
| 106 if (ArcIntentHelperBridge::IsIntentHelperPackage(handler->package_name)) { | 106 if (ArcIntentHelperBridge::IsIntentHelperPackage(handler->package_name)) { |
| 107 // Since |package_name| is "Chrome", and |fallback_url| is not null, the | 107 // Since |package_name| is "Chrome", and |fallback_url| is not null, the |
| 108 // URL must be either http or https. Check it just in case, and if not, | 108 // URL must be either http or https. Check it just in case, and if not, |
| 109 // fallback to HANDLE_URL_IN_ARC; | 109 // fallback to HANDLE_URL_IN_ARC; |
| 110 if (out_url_and_package->first.SchemeIsHTTPOrHTTPS()) | 110 if (out_url_and_package->first.SchemeIsHTTPOrHTTPS()) |
| 111 return GetActionResult::OPEN_URL_IN_CHROME; | 111 return GetActionResult::OPEN_URL_IN_CHROME; |
| 112 | 112 |
| 113 LOG(WARNING) << "Failed to handle " << out_url_and_package->first | 113 LOG(WARNING) << "Failed to handle " << out_url_and_package->first |
| 114 << " in Chrome. Falling back to ARC..."; | 114 << " in Chrome. Falling back to ARC..."; |
| 115 } | 115 } |
| 116 // |fallback_url| which Chrome doesn't support is passed (e.g. market:). | 116 // |fallback_url| which Chrome doesn't support is passed (e.g. market:). |
| 117 return GetActionResult::HANDLE_URL_IN_ARC; | 117 return GetActionResult::HANDLE_URL_IN_ARC; |
| 118 } | 118 } |
| 119 | 119 |
| 120 // Unlike |handler->fallback_url|, the |original_url| should always be handled | 120 // Unlike |handler->fallback_url|, the |original_url| should always be handled |
| 121 // in ARC since it's external to Chrome. | 121 // in ARC since it's external to Chrome. |
| 122 *out_url_and_package = | 122 *out_url_and_package = std::make_pair(original_url, handler->package_name); |
| 123 std::make_pair(original_url, handler->package_name.get()); | |
| 124 return GetActionResult::HANDLE_URL_IN_ARC; | 123 return GetActionResult::HANDLE_URL_IN_ARC; |
| 125 } | 124 } |
| 126 | 125 |
| 127 // Gets an action that should be done when ARC has the |handlers| for the | 126 // Gets an action that should be done when ARC has the |handlers| for the |
| 128 // |original_url| and the user selects |selected_app_index|. When the user | 127 // |original_url| and the user selects |selected_app_index|. When the user |
| 129 // hasn't selected any app, |selected_app_index| must be set to | 128 // hasn't selected any app, |selected_app_index| must be set to |
| 130 // |handlers.size()|. | 129 // |handlers.size()|. |
| 131 // | 130 // |
| 132 // When the returned action is either OPEN_URL_IN_CHROME or HANDLE_URL_IN_ARC, | 131 // When the returned action is either OPEN_URL_IN_CHROME or HANDLE_URL_IN_ARC, |
| 133 // |out_url_and_package| is filled accordingly. | 132 // |out_url_and_package| is filled accordingly. |
| 134 GetActionResult GetAction( | 133 GetActionResult GetAction( |
| 135 const GURL& original_url, | 134 const GURL& original_url, |
| 136 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers, | 135 const std::vector<mojom::IntentHandlerInfoPtr>& handlers, |
| 137 size_t selected_app_index, | 136 size_t selected_app_index, |
| 138 std::pair<GURL, std::string>* out_url_and_package) { | 137 std::pair<GURL, std::string>* out_url_and_package) { |
| 139 DCHECK(out_url_and_package); | 138 DCHECK(out_url_and_package); |
| 140 if (!handlers.size()) | 139 if (!handlers.size()) |
| 141 return GetActionResult::SHOW_CHROME_OS_DIALOG; // no apps found. | 140 return GetActionResult::SHOW_CHROME_OS_DIALOG; // no apps found. |
| 142 | 141 |
| 143 if (selected_app_index == handlers.size()) { | 142 if (selected_app_index == handlers.size()) { |
| 144 // The user hasn't made the selection yet. | 143 // The user hasn't made the selection yet. |
| 145 | 144 |
| 146 // If |handlers| has only one element and its package is "Chrome", open | 145 // If |handlers| has only one element and its package is "Chrome", open |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 170 // The user has already made the selection. Decide how to open it, either in | 169 // The user has already made the selection. Decide how to open it, either in |
| 171 // Chrome or ARC. | 170 // Chrome or ARC. |
| 172 return GetActionInternal(original_url, handlers[selected_app_index], | 171 return GetActionInternal(original_url, handlers[selected_app_index], |
| 173 out_url_and_package); | 172 out_url_and_package); |
| 174 } | 173 } |
| 175 | 174 |
| 176 // Handles |url| if possible. Returns true if it is actually handled. | 175 // Handles |url| if possible. Returns true if it is actually handled. |
| 177 bool HandleUrl(int render_process_host_id, | 176 bool HandleUrl(int render_process_host_id, |
| 178 int routing_id, | 177 int routing_id, |
| 179 const GURL& url, | 178 const GURL& url, |
| 180 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers, | 179 const std::vector<mojom::IntentHandlerInfoPtr>& handlers, |
| 181 size_t selected_app_index, | 180 size_t selected_app_index, |
| 182 GetActionResult* out_result) { | 181 GetActionResult* out_result) { |
| 183 std::pair<GURL, std::string> url_and_package; | 182 std::pair<GURL, std::string> url_and_package; |
| 184 const GetActionResult result = | 183 const GetActionResult result = |
| 185 GetAction(url, handlers, selected_app_index, &url_and_package); | 184 GetAction(url, handlers, selected_app_index, &url_and_package); |
| 186 if (out_result) | 185 if (out_result) |
| 187 *out_result = result; | 186 *out_result = result; |
| 188 | 187 |
| 189 switch (result) { | 188 switch (result) { |
| 190 case GetActionResult::SHOW_CHROME_OS_DIALOG: | 189 case GetActionResult::SHOW_CHROME_OS_DIALOG: |
| 191 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, | 190 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, |
| 192 url); | 191 url); |
| 193 return true; | 192 return true; |
| 194 case GetActionResult::OPEN_URL_IN_CHROME: | 193 case GetActionResult::OPEN_URL_IN_CHROME: |
| 195 OpenUrlInChrome(render_process_host_id, routing_id, | 194 OpenUrlInChrome(render_process_host_id, routing_id, |
| 196 url_and_package.first); | 195 url_and_package.first); |
| 197 return true; | 196 return true; |
| 198 case GetActionResult::HANDLE_URL_IN_ARC: | 197 case GetActionResult::HANDLE_URL_IN_ARC: |
| 199 HandleUrlInArc(render_process_host_id, routing_id, url_and_package); | 198 HandleUrlInArc(render_process_host_id, routing_id, url_and_package); |
| 200 return true; | 199 return true; |
| 201 case GetActionResult::ASK_USER: | 200 case GetActionResult::ASK_USER: |
| 202 break; | 201 break; |
| 203 } | 202 } |
| 204 return false; | 203 return false; |
| 205 } | 204 } |
| 206 | 205 |
| 207 // Returns a fallback http(s) in |handlers| which Chrome can handle. Returns | 206 // Returns a fallback http(s) in |handlers| which Chrome can handle. Returns |
| 208 // an empty GURL if none found. | 207 // an empty GURL if none found. |
| 209 GURL GetUrlToNavigateOnDeactivate( | 208 GURL GetUrlToNavigateOnDeactivate( |
| 210 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) { | 209 const std::vector<mojom::IntentHandlerInfoPtr>& handlers) { |
| 211 const GURL empty_url; | 210 const GURL empty_url; |
| 212 for (size_t i = 0; i < handlers.size(); ++i) { | 211 for (size_t i = 0; i < handlers.size(); ++i) { |
| 213 std::pair<GURL, std::string> url_and_package; | 212 std::pair<GURL, std::string> url_and_package; |
| 214 if (GetActionInternal(empty_url, handlers[i], &url_and_package) == | 213 if (GetActionInternal(empty_url, handlers[i], &url_and_package) == |
| 215 GetActionResult::OPEN_URL_IN_CHROME) { | 214 GetActionResult::OPEN_URL_IN_CHROME) { |
| 216 DCHECK(url_and_package.first.SchemeIsHTTPOrHTTPS()); | 215 DCHECK(url_and_package.first.SchemeIsHTTPOrHTTPS()); |
| 217 return url_and_package.first; | 216 return url_and_package.first; |
| 218 } | 217 } |
| 219 } | 218 } |
| 220 return empty_url; // nothing found. | 219 return empty_url; // nothing found. |
| 221 } | 220 } |
| 222 | 221 |
| 223 // Called when the dialog is just deactivated without pressing one of the | 222 // Called when the dialog is just deactivated without pressing one of the |
| 224 // buttons. | 223 // buttons. |
| 225 void OnIntentPickerDialogDeactivated( | 224 void OnIntentPickerDialogDeactivated( |
| 226 int render_process_host_id, | 225 int render_process_host_id, |
| 227 int routing_id, | 226 int routing_id, |
| 228 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) { | 227 const std::vector<mojom::IntentHandlerInfoPtr>& handlers) { |
| 229 const GURL url_to_open_in_chrome = GetUrlToNavigateOnDeactivate(handlers); | 228 const GURL url_to_open_in_chrome = GetUrlToNavigateOnDeactivate(handlers); |
| 230 if (url_to_open_in_chrome.is_empty()) | 229 if (url_to_open_in_chrome.is_empty()) |
| 231 CloseTabIfNeeded(render_process_host_id, routing_id); | 230 CloseTabIfNeeded(render_process_host_id, routing_id); |
| 232 else | 231 else |
| 233 OpenUrlInChrome(render_process_host_id, routing_id, url_to_open_in_chrome); | 232 OpenUrlInChrome(render_process_host_id, routing_id, url_to_open_in_chrome); |
| 234 } | 233 } |
| 235 | 234 |
| 236 // Called when the dialog is closed. Note that once we show the UI, we should | 235 // Called when the dialog is closed. Note that once we show the UI, we should |
| 237 // never show the Chrome OS' fallback dialog. | 236 // never show the Chrome OS' fallback dialog. |
| 238 void OnIntentPickerClosed(int render_process_host_id, | 237 void OnIntentPickerClosed(int render_process_host_id, |
| 239 int routing_id, | 238 int routing_id, |
| 240 const GURL& url, | 239 const GURL& url, |
| 241 mojo::Array<mojom::IntentHandlerInfoPtr> handlers, | 240 std::vector<mojom::IntentHandlerInfoPtr> handlers, |
| 242 const std::string& selected_app_package, | 241 const std::string& selected_app_package, |
| 243 ArcNavigationThrottle::CloseReason close_reason) { | 242 ArcNavigationThrottle::CloseReason close_reason) { |
| 244 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 243 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 245 | 244 |
| 246 // If the user selected an app to continue the navigation, confirm that the | 245 // If the user selected an app to continue the navigation, confirm that the |
| 247 // |package_name| matches a valid option and return the index. | 246 // |package_name| matches a valid option and return the index. |
| 248 const size_t selected_app_index = | 247 const size_t selected_app_index = |
| 249 ArcNavigationThrottle::GetAppIndex(handlers, selected_app_package); | 248 ArcNavigationThrottle::GetAppIndex(handlers, selected_app_package); |
| 250 // Make sure that the instance at least supports HandleUrl. | 249 // Make sure that the instance at least supports HandleUrl. |
| 251 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( | 250 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 ArcNavigationThrottle::GetDestinationPlatform(selected_app_package, | 298 ArcNavigationThrottle::GetDestinationPlatform(selected_app_package, |
| 300 close_reason); | 299 close_reason); |
| 301 ArcNavigationThrottle::RecordUma(close_reason, platform); | 300 ArcNavigationThrottle::RecordUma(close_reason, platform); |
| 302 } | 301 } |
| 303 | 302 |
| 304 // Called when ARC returned activity icons for the |handlers|. | 303 // Called when ARC returned activity icons for the |handlers|. |
| 305 void OnAppIconsReceived( | 304 void OnAppIconsReceived( |
| 306 int render_process_host_id, | 305 int render_process_host_id, |
| 307 int routing_id, | 306 int routing_id, |
| 308 const GURL& url, | 307 const GURL& url, |
| 309 mojo::Array<mojom::IntentHandlerInfoPtr> handlers, | 308 std::vector<mojom::IntentHandlerInfoPtr> handlers, |
| 310 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons) { | 309 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons) { |
| 311 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 312 | 311 |
| 313 using AppInfo = arc::ArcNavigationThrottle::AppInfo; | 312 using AppInfo = arc::ArcNavigationThrottle::AppInfo; |
| 314 std::vector<AppInfo> app_info; | 313 std::vector<AppInfo> app_info; |
| 315 | 314 |
| 316 for (const auto& handler : handlers) { | 315 for (const auto& handler : handlers) { |
| 317 const ActivityIconLoader::ActivityName activity(handler->package_name, | 316 const ActivityIconLoader::ActivityName activity(handler->package_name, |
| 318 handler->activity_name); | 317 handler->activity_name); |
| 319 const auto it = icons->find(activity); | 318 const auto it = icons->find(activity); |
| 320 app_info.emplace_back( | 319 app_info.emplace_back( |
| 321 AppInfo(it != icons->end() ? it->second.icon20 : gfx::Image(), | 320 AppInfo(it != icons->end() ? it->second.icon20 : gfx::Image(), |
| 322 handler->package_name, handler->name)); | 321 handler->package_name, handler->name)); |
| 323 } | 322 } |
| 324 | 323 |
| 325 auto show_bubble_cb = base::Bind(ShowIntentPickerBubble()); | 324 auto show_bubble_cb = base::Bind(ShowIntentPickerBubble()); |
| 326 WebContents* web_contents = | 325 WebContents* web_contents = |
| 327 tab_util::GetWebContentsByID(render_process_host_id, routing_id); | 326 tab_util::GetWebContentsByID(render_process_host_id, routing_id); |
| 328 show_bubble_cb.Run(web_contents, app_info, | 327 show_bubble_cb.Run(web_contents, app_info, |
| 329 base::Bind(OnIntentPickerClosed, render_process_host_id, | 328 base::Bind(OnIntentPickerClosed, render_process_host_id, |
| 330 routing_id, url, base::Passed(&handlers))); | 329 routing_id, url, base::Passed(&handlers))); |
| 331 } | 330 } |
| 332 | 331 |
| 333 // Called when ARC returned a handler list for the |url|. | 332 // Called when ARC returned a handler list for the |url|. |
| 334 void OnUrlHandlerList(int render_process_host_id, | 333 void OnUrlHandlerList(int render_process_host_id, |
| 335 int routing_id, | 334 int routing_id, |
| 336 const GURL& url, | 335 const GURL& url, |
| 337 mojo::Array<mojom::IntentHandlerInfoPtr> handlers) { | 336 std::vector<mojom::IntentHandlerInfoPtr> handlers) { |
| 338 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 337 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 339 | 338 |
| 340 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( | 339 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( |
| 341 "HandleUrl", kMinVersionForHandleUrl); | 340 "HandleUrl", kMinVersionForHandleUrl); |
| 342 scoped_refptr<ActivityIconLoader> icon_loader = GetIconLoader(); | 341 scoped_refptr<ActivityIconLoader> icon_loader = GetIconLoader(); |
| 343 | 342 |
| 344 if (!instance || !icon_loader) { | 343 if (!instance || !icon_loader) { |
| 345 // ARC is not running anymore. Show the Chrome OS dialog. | 344 // ARC is not running anymore. Show the Chrome OS dialog. |
| 346 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, url); | 345 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, url); |
| 347 return; | 346 return; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 base::Bind(OnUrlHandlerList, render_process_host_id, routing_id, url)); | 425 base::Bind(OnUrlHandlerList, render_process_host_id, routing_id, url)); |
| 427 return true; | 426 return true; |
| 428 } | 427 } |
| 429 | 428 |
| 430 bool ShouldIgnoreNavigationForTesting(ui::PageTransition page_transition) { | 429 bool ShouldIgnoreNavigationForTesting(ui::PageTransition page_transition) { |
| 431 return ShouldIgnoreNavigation(page_transition); | 430 return ShouldIgnoreNavigation(page_transition); |
| 432 } | 431 } |
| 433 | 432 |
| 434 GetActionResult GetActionForTesting( | 433 GetActionResult GetActionForTesting( |
| 435 const GURL& original_url, | 434 const GURL& original_url, |
| 436 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers, | 435 const std::vector<mojom::IntentHandlerInfoPtr>& handlers, |
| 437 size_t selected_app_index, | 436 size_t selected_app_index, |
| 438 std::pair<GURL, std::string>* out_url_and_package) { | 437 std::pair<GURL, std::string>* out_url_and_package) { |
| 439 return GetAction(original_url, handlers, selected_app_index, | 438 return GetAction(original_url, handlers, selected_app_index, |
| 440 out_url_and_package); | 439 out_url_and_package); |
| 441 } | 440 } |
| 442 | 441 |
| 443 GURL GetUrlToNavigateOnDeactivateForTesting( | 442 GURL GetUrlToNavigateOnDeactivateForTesting( |
| 444 const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) { | 443 const std::vector<mojom::IntentHandlerInfoPtr>& handlers) { |
| 445 return GetUrlToNavigateOnDeactivate(handlers); | 444 return GetUrlToNavigateOnDeactivate(handlers); |
| 446 } | 445 } |
| 447 | 446 |
| 448 } // namespace arc | 447 } // namespace arc |
| OLD | NEW |