| 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 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 #include "ui/base/window_open_disposition.h" | 27 #include "ui/base/window_open_disposition.h" |
| 28 #include "ui/gfx/image/image.h" | 28 #include "ui/gfx/image/image.h" |
| 29 #include "url/gurl.h" | 29 #include "url/gurl.h" |
| 30 | 30 |
| 31 using content::WebContents; | 31 using content::WebContents; |
| 32 | 32 |
| 33 namespace arc { | 33 namespace arc { |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 constexpr uint32_t kMinVersionForHandleUrl = 2; | |
| 38 constexpr uint32_t kMinVersionForRequestUrlHandlerList = 2; | |
| 39 constexpr uint32_t kMinVersionForAddPreferredPackage = 7; | |
| 40 | |
| 41 // TODO(yusukes|djacobo): Find a better way to detect a request loop and remove | 37 // TODO(yusukes|djacobo): Find a better way to detect a request loop and remove |
| 42 // the global variables. | 38 // the global variables. |
| 43 base::LazyInstance<GURL> g_last_url = LAZY_INSTANCE_INITIALIZER; | 39 base::LazyInstance<GURL> g_last_url = LAZY_INSTANCE_INITIALIZER; |
| 44 ui::PageTransition g_last_page_transition; | 40 ui::PageTransition g_last_page_transition; |
| 45 | 41 |
| 46 // Shows the Chrome OS' original external protocol dialog as a fallback. | 42 // Shows the Chrome OS' original external protocol dialog as a fallback. |
| 47 void ShowFallbackExternalProtocolDialog(int render_process_host_id, | 43 void ShowFallbackExternalProtocolDialog(int render_process_host_id, |
| 48 int routing_id, | 44 int routing_id, |
| 49 const GURL& url) { | 45 const GURL& url) { |
| 50 WebContents* web_contents = | 46 WebContents* web_contents = |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 // TODO(yusukes): Send a non-empty referrer. | 79 // TODO(yusukes): Send a non-empty referrer. |
| 84 url, content::Referrer(), WindowOpenDisposition::CURRENT_TAB, | 80 url, content::Referrer(), WindowOpenDisposition::CURRENT_TAB, |
| 85 page_transition_type, kIsRendererInitiated); | 81 page_transition_type, kIsRendererInitiated); |
| 86 web_contents->OpenURL(params); | 82 web_contents->OpenURL(params); |
| 87 } | 83 } |
| 88 | 84 |
| 89 // Sends |url| to ARC. | 85 // Sends |url| to ARC. |
| 90 void HandleUrlInArc(int render_process_host_id, | 86 void HandleUrlInArc(int render_process_host_id, |
| 91 int routing_id, | 87 int routing_id, |
| 92 const std::pair<GURL, std::string>& url_and_package) { | 88 const std::pair<GURL, std::string>& url_and_package) { |
| 93 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( | 89 auto* arc_service_manager = ArcServiceManager::Get(); |
| 94 "HandleUrl", kMinVersionForHandleUrl); | 90 if (!arc_service_manager) |
| 91 return; |
| 92 auto* instance = ARC_GET_INSTANCE_FOR_METHOD( |
| 93 arc_service_manager->arc_bridge_service()->intent_helper(), HandleUrl); |
| 95 if (!instance) | 94 if (!instance) |
| 96 return; | 95 return; |
| 97 | 96 |
| 98 instance->HandleUrl(url_and_package.first.spec(), url_and_package.second); | 97 instance->HandleUrl(url_and_package.first.spec(), url_and_package.second); |
| 99 CloseTabIfNeeded(render_process_host_id, routing_id); | 98 CloseTabIfNeeded(render_process_host_id, routing_id); |
| 100 } | 99 } |
| 101 | 100 |
| 102 // A helper function called by GetAction(). | 101 // A helper function called by GetAction(). |
| 103 GetActionResult GetActionInternal( | 102 GetActionResult GetActionInternal( |
| 104 const GURL& original_url, | 103 const GURL& original_url, |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 const GURL& url, | 252 const GURL& url, |
| 254 std::vector<mojom::IntentHandlerInfoPtr> handlers, | 253 std::vector<mojom::IntentHandlerInfoPtr> handlers, |
| 255 const std::string& selected_app_package, | 254 const std::string& selected_app_package, |
| 256 ArcNavigationThrottle::CloseReason close_reason) { | 255 ArcNavigationThrottle::CloseReason close_reason) { |
| 257 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 256 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 258 | 257 |
| 259 // If the user selected an app to continue the navigation, confirm that the | 258 // If the user selected an app to continue the navigation, confirm that the |
| 260 // |package_name| matches a valid option and return the index. | 259 // |package_name| matches a valid option and return the index. |
| 261 const size_t selected_app_index = | 260 const size_t selected_app_index = |
| 262 ArcNavigationThrottle::GetAppIndex(handlers, selected_app_package); | 261 ArcNavigationThrottle::GetAppIndex(handlers, selected_app_package); |
| 262 |
| 263 // Make sure that the instance at least supports HandleUrl. | 263 // Make sure that the instance at least supports HandleUrl. |
| 264 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( | 264 auto* arc_service_manager = ArcServiceManager::Get(); |
| 265 "HandleUrl", kMinVersionForHandleUrl); | 265 mojom::IntentHelperInstance* instance = nullptr; |
| 266 if (arc_service_manager) { |
| 267 instance = ARC_GET_INSTANCE_FOR_METHOD( |
| 268 arc_service_manager->arc_bridge_service()->intent_helper(), HandleUrl); |
| 269 } |
| 270 |
| 266 if (!instance) { | 271 if (!instance) { |
| 267 close_reason = ArcNavigationThrottle::CloseReason::ERROR; | 272 close_reason = ArcNavigationThrottle::CloseReason::ERROR; |
| 268 } else if (close_reason == | 273 } else if (close_reason == |
| 269 ArcNavigationThrottle::CloseReason::JUST_ONCE_PRESSED || | 274 ArcNavigationThrottle::CloseReason::JUST_ONCE_PRESSED || |
| 270 close_reason == | 275 close_reason == |
| 271 ArcNavigationThrottle::CloseReason::ALWAYS_PRESSED) { | 276 ArcNavigationThrottle::CloseReason::ALWAYS_PRESSED) { |
| 272 if (selected_app_index == handlers.size()) { | 277 if (selected_app_index == handlers.size()) { |
| 273 close_reason = ArcNavigationThrottle::CloseReason::ERROR; | 278 close_reason = ArcNavigationThrottle::CloseReason::ERROR; |
| 274 } else { | 279 } else { |
| 275 // The user has made a selection. Clear g_last_* variables. | 280 // The user has made a selection. Clear g_last_* variables. |
| 276 g_last_url.Get() = GURL(); | 281 g_last_url.Get() = GURL(); |
| 277 g_last_page_transition = ui::PageTransition(); | 282 g_last_page_transition = ui::PageTransition(); |
| 278 } | 283 } |
| 279 } | 284 } |
| 280 | 285 |
| 281 switch (close_reason) { | 286 switch (close_reason) { |
| 282 case ArcNavigationThrottle::CloseReason::ALWAYS_PRESSED: { | 287 case ArcNavigationThrottle::CloseReason::ALWAYS_PRESSED: { |
| 283 if (ArcIntentHelperBridge::GetIntentHelperInstance( | 288 DCHECK(arc_service_manager); |
| 284 "AddPreferredPackage", kMinVersionForAddPreferredPackage)) { | 289 if (ARC_GET_INSTANCE_FOR_METHOD( |
| 290 arc_service_manager->arc_bridge_service()->intent_helper(), |
| 291 AddPreferredPackage)) { |
| 285 instance->AddPreferredPackage( | 292 instance->AddPreferredPackage( |
| 286 handlers[selected_app_index]->package_name); | 293 handlers[selected_app_index]->package_name); |
| 287 } | 294 } |
| 288 // fall through. | 295 // fall through. |
| 289 } | 296 } |
| 290 case ArcNavigationThrottle::CloseReason::JUST_ONCE_PRESSED: { | 297 case ArcNavigationThrottle::CloseReason::JUST_ONCE_PRESSED: { |
| 291 // Launch the selected app. | 298 // Launch the selected app. |
| 292 HandleUrl(render_process_host_id, routing_id, url, false, handlers, | 299 HandleUrl(render_process_host_id, routing_id, url, false, handlers, |
| 293 selected_app_index, nullptr); | 300 selected_app_index, nullptr); |
| 294 break; | 301 break; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 321 | 328 |
| 322 // Called when ARC returned activity icons for the |handlers|. | 329 // Called when ARC returned activity icons for the |handlers|. |
| 323 void OnAppIconsReceived( | 330 void OnAppIconsReceived( |
| 324 int render_process_host_id, | 331 int render_process_host_id, |
| 325 int routing_id, | 332 int routing_id, |
| 326 const GURL& url, | 333 const GURL& url, |
| 327 std::vector<mojom::IntentHandlerInfoPtr> handlers, | 334 std::vector<mojom::IntentHandlerInfoPtr> handlers, |
| 328 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons) { | 335 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons) { |
| 329 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 336 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 330 | 337 |
| 331 using AppInfo = arc::ArcNavigationThrottle::AppInfo; | 338 using AppInfo = ArcNavigationThrottle::AppInfo; |
| 332 std::vector<AppInfo> app_info; | 339 std::vector<AppInfo> app_info; |
| 333 | 340 |
| 334 for (const auto& handler : handlers) { | 341 for (const auto& handler : handlers) { |
| 335 const ActivityIconLoader::ActivityName activity(handler->package_name, | 342 const ActivityIconLoader::ActivityName activity(handler->package_name, |
| 336 handler->activity_name); | 343 handler->activity_name); |
| 337 const auto it = icons->find(activity); | 344 const auto it = icons->find(activity); |
| 338 app_info.emplace_back( | 345 app_info.emplace_back( |
| 339 AppInfo(it != icons->end() ? it->second.icon20 : gfx::Image(), | 346 AppInfo(it != icons->end() ? it->second.icon20 : gfx::Image(), |
| 340 handler->package_name, handler->name)); | 347 handler->package_name, handler->name)); |
| 341 } | 348 } |
| 342 | 349 |
| 343 auto show_bubble_cb = base::Bind(ShowIntentPickerBubble()); | 350 auto show_bubble_cb = base::Bind(ShowIntentPickerBubble()); |
| 344 WebContents* web_contents = | 351 WebContents* web_contents = |
| 345 tab_util::GetWebContentsByID(render_process_host_id, routing_id); | 352 tab_util::GetWebContentsByID(render_process_host_id, routing_id); |
| 346 show_bubble_cb.Run(web_contents, app_info, | 353 show_bubble_cb.Run(web_contents, app_info, |
| 347 base::Bind(OnIntentPickerClosed, render_process_host_id, | 354 base::Bind(OnIntentPickerClosed, render_process_host_id, |
| 348 routing_id, url, base::Passed(&handlers))); | 355 routing_id, url, base::Passed(&handlers))); |
| 349 } | 356 } |
| 350 | 357 |
| 351 // Called when ARC returned a handler list for the |url|. | 358 // Called when ARC returned a handler list for the |url|. |
| 352 void OnUrlHandlerList(int render_process_host_id, | 359 void OnUrlHandlerList(int render_process_host_id, |
| 353 int routing_id, | 360 int routing_id, |
| 354 const GURL& url, | 361 const GURL& url, |
| 355 bool always_ask_user, | 362 bool always_ask_user, |
| 356 std::vector<mojom::IntentHandlerInfoPtr> handlers) { | 363 std::vector<mojom::IntentHandlerInfoPtr> handlers) { |
| 357 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 364 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 358 | 365 |
| 359 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( | 366 auto* arc_service_manager = ArcServiceManager::Get(); |
| 360 "HandleUrl", kMinVersionForHandleUrl); | 367 if (!arc_service_manager) { |
| 368 // ARC is not running anymore. Show the Chrome OS dialog. |
| 369 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, url); |
| 370 return; |
| 371 } |
| 372 |
| 373 auto* instance = ARC_GET_INSTANCE_FOR_METHOD( |
| 374 arc_service_manager->arc_bridge_service()->intent_helper(), HandleUrl); |
| 361 scoped_refptr<ActivityIconLoader> icon_loader = GetIconLoader(); | 375 scoped_refptr<ActivityIconLoader> icon_loader = GetIconLoader(); |
| 362 | 376 |
| 363 if (!instance || !icon_loader) { | 377 if (!instance || !icon_loader) { |
| 364 // ARC is not running anymore. Show the Chrome OS dialog. | 378 // ARC is not running anymore. Show the Chrome OS dialog. |
| 365 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, url); | 379 ShowFallbackExternalProtocolDialog(render_process_host_id, routing_id, url); |
| 366 return; | 380 return; |
| 367 } | 381 } |
| 368 | 382 |
| 369 // Check if the |url| should be handled right away without showing the UI. | 383 // Check if the |url| should be handled right away without showing the UI. |
| 370 GetActionResult result; | 384 GetActionResult result; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 MaskOutPageTransition(page_transition, ui::PAGE_TRANSITION_FROM_API); | 464 MaskOutPageTransition(page_transition, ui::PAGE_TRANSITION_FROM_API); |
| 451 | 465 |
| 452 if (ShouldIgnoreNavigation(masked_page_transition, | 466 if (ShouldIgnoreNavigation(masked_page_transition, |
| 453 true /* allow_form_submit */, | 467 true /* allow_form_submit */, |
| 454 true /* allow_client_redirect */)) { | 468 true /* allow_client_redirect */)) { |
| 455 LOG(WARNING) << "RunArcExternalProtocolDialog: ignoring " << url | 469 LOG(WARNING) << "RunArcExternalProtocolDialog: ignoring " << url |
| 456 << " with PageTransition=" << masked_page_transition; | 470 << " with PageTransition=" << masked_page_transition; |
| 457 return false; | 471 return false; |
| 458 } | 472 } |
| 459 | 473 |
| 460 auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance( | 474 auto* arc_service_manager = ArcServiceManager::Get(); |
| 461 "RequestUrlHandlerList", kMinVersionForRequestUrlHandlerList); | 475 if (!arc_service_manager) |
| 476 return false; // ARC is either not supported or not yet ready. |
| 477 |
| 478 auto* instance = ARC_GET_INSTANCE_FOR_METHOD( |
| 479 arc_service_manager->arc_bridge_service()->intent_helper(), |
| 480 RequestUrlHandlerList); |
| 462 if (!instance) | 481 if (!instance) |
| 463 return false; // ARC is either not supported or not yet ready. | 482 return false; // the same. |
| 464 | 483 |
| 465 WebContents* web_contents = | 484 WebContents* web_contents = |
| 466 tab_util::GetWebContentsByID(render_process_host_id, routing_id); | 485 tab_util::GetWebContentsByID(render_process_host_id, routing_id); |
| 467 if (!web_contents || !web_contents->GetBrowserContext() || | 486 if (!web_contents || !web_contents->GetBrowserContext() || |
| 468 web_contents->GetBrowserContext()->IsOffTheRecord()) { | 487 web_contents->GetBrowserContext()->IsOffTheRecord()) { |
| 469 return false; | 488 return false; |
| 470 } | 489 } |
| 471 | 490 |
| 472 // Show ARC version of the dialog, which is IntentPickerBubbleView. To show | 491 // Show ARC version of the dialog, which is IntentPickerBubbleView. To show |
| 473 // the bubble view, we need to ask ARC for a handler list first. | 492 // the bubble view, we need to ask ARC for a handler list first. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 495 bool IsSafeToRedirectToArcWithoutUserConfirmationForTesting( | 514 bool IsSafeToRedirectToArcWithoutUserConfirmationForTesting( |
| 496 const GURL& url, | 515 const GURL& url, |
| 497 ui::PageTransition page_transition, | 516 ui::PageTransition page_transition, |
| 498 const GURL& last_url, | 517 const GURL& last_url, |
| 499 ui::PageTransition last_page_transition) { | 518 ui::PageTransition last_page_transition) { |
| 500 return IsSafeToRedirectToArcWithoutUserConfirmation( | 519 return IsSafeToRedirectToArcWithoutUserConfirmation( |
| 501 url, page_transition, last_url, last_page_transition); | 520 url, page_transition, last_url, last_page_transition); |
| 502 } | 521 } |
| 503 | 522 |
| 504 } // namespace arc | 523 } // namespace arc |
| OLD | NEW |