Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(424)

Unified Diff: chrome/browser/chromeos/arc/arc_navigation_throttle.cc

Issue 2441563002: arc: Create intermediate directories in c/b/c/arc (Closed)
Patch Set: Re-rebase to ToT Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/arc/arc_navigation_throttle.cc
diff --git a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
deleted file mode 100644
index 8857fbd853228a3623590fd0245ae75e816f648b..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/arc/arc_navigation_throttle.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram_macros.h"
-#include "components/arc/arc_bridge_service.h"
-#include "components/arc/arc_service_manager.h"
-#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/intent_helper/local_activity_resolver.h"
-#include "components/arc/intent_helper/page_transition_util.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/web_contents.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-
-namespace arc {
-
-namespace {
-
-constexpr uint32_t kMinVersionForHandleUrl = 2;
-constexpr uint32_t kMinVersionForRequestUrlHandlerList = 2;
-constexpr uint32_t kMinVersionForAddPreferredPackage = 7;
-
-scoped_refptr<ActivityIconLoader> GetIconLoader() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- ArcServiceManager* arc_service_manager = ArcServiceManager::Get();
- return arc_service_manager ? arc_service_manager->icon_loader() : nullptr;
-}
-
-// Compares the host name of the referrer and target URL to decide whether
-// the navigation needs to be overriden.
-bool ShouldOverrideUrlLoading(const GURL& previous_url,
- const GURL& current_url) {
- // When the navigation is initiated in a web page where sending a referrer
- // is disabled, |previous_url| can be empty. In this case, we should open
- // it in the desktop browser.
- if (!previous_url.is_valid() || previous_url.is_empty())
- return false;
-
- // Also check |current_url| just in case.
- if (!current_url.is_valid() || current_url.is_empty()) {
- DVLOG(1) << "Unexpected URL: " << current_url << ", opening it in Chrome.";
- return false;
- }
-
- return !net::registry_controlled_domains::SameDomainOrHost(
- current_url, previous_url,
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-}
-
-// Returns true if |handlers| contain one or more apps. When this function is
-// called from OnAppCandidatesReceived, |handlers| always contain Chrome (aka
-// intent_helper), but the function doesn't treat it as an app.
-bool IsAppAvailable(const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) {
- return handlers.size() > 1 || (handlers.size() == 1 &&
- !ArcIntentHelperBridge::IsIntentHelperPackage(
- handlers[0]->package_name));
-}
-
-// Searches for a preferred app in |handlers| and returns its index. If not
-// found, returns |handlers.size()|.
-size_t FindPreferredApp(
- const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers,
- const GURL& url_for_logging) {
- for (size_t i = 0; i < handlers.size(); ++i) {
- if (!handlers[i]->is_preferred)
- continue;
- if (ArcIntentHelperBridge::IsIntentHelperPackage(
- handlers[i]->package_name)) {
- // If Chrome browser was selected as the preferred app, we shouldn't
- // create a throttle.
- DVLOG(1)
- << "Chrome browser is selected as the preferred app for this URL: "
- << url_for_logging;
- }
- return i;
- }
- return handlers.size(); // not found
-}
-
-// Swaps Chrome app with any app in row |kMaxAppResults-1| iff its index is
-// bigger, thus ensuring the user can always see Chrome without scrolling.
-// When swap is needed, fills |out_indices| and returns true. If |handlers|
-// do not have Chrome, returns false.
-bool IsSwapElementsNeeded(
- const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers,
- std::pair<size_t, size_t>* out_indices) {
- size_t chrome_app_index = 0;
- for (size_t i = 0; i < handlers.size(); ++i) {
- if (ArcIntentHelperBridge::IsIntentHelperPackage(
- handlers[i]->package_name)) {
- chrome_app_index = i;
- break;
- }
- }
- if (chrome_app_index < ArcNavigationThrottle::kMaxAppResults)
- return false;
-
- *out_indices = std::make_pair(ArcNavigationThrottle::kMaxAppResults - 1,
- chrome_app_index);
- return true;
-}
-
-} // namespace
-
-ArcNavigationThrottle::ArcNavigationThrottle(
- content::NavigationHandle* navigation_handle,
- const ShowIntentPickerCallback& show_intent_picker_cb)
- : content::NavigationThrottle(navigation_handle),
- show_intent_picker_callback_(show_intent_picker_cb),
- previous_user_action_(CloseReason::INVALID),
- weak_ptr_factory_(this) {}
-
-ArcNavigationThrottle::~ArcNavigationThrottle() = default;
-
-content::NavigationThrottle::ThrottleCheckResult
-ArcNavigationThrottle::WillStartRequest() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- // We must not handle navigations started from the context menu.
- if (navigation_handle()->WasStartedFromContextMenu())
- return content::NavigationThrottle::PROCEED;
- return HandleRequest();
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-ArcNavigationThrottle::WillRedirectRequest() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- switch (previous_user_action_) {
- case CloseReason::ERROR:
- case CloseReason::DIALOG_DEACTIVATED:
- // User dismissed the dialog, or some error occurred before. Don't
- // repeatedly pop up the dialog.
- return content::NavigationThrottle::PROCEED;
-
- case CloseReason::ALWAYS_PRESSED:
- case CloseReason::JUST_ONCE_PRESSED:
- case CloseReason::PREFERRED_ACTIVITY_FOUND:
- // Should never get here - if the user selected one of these previously,
- // Chrome should not see a redirect.
- NOTREACHED();
-
- case CloseReason::INVALID:
- // No picker has previously been popped up for this - continue.
- break;
- }
- return HandleRequest();
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-ArcNavigationThrottle::HandleRequest() {
- const GURL& url = navigation_handle()->GetURL();
-
- // Always handle http(s) <form> submissions in Chrome for two reasons: 1) we
- // don't have a way to send POST data to ARC, and 2) intercepting http(s) form
- // submissions is not very important because such submissions are usually
- // done within the same domain. ShouldOverrideUrlLoading() below filters out
- // such submissions anyway.
- constexpr bool kAllowFormSubmit = false;
-
- if (ShouldIgnoreNavigation(navigation_handle()->GetPageTransition(),
- kAllowFormSubmit))
- return content::NavigationThrottle::PROCEED;
-
- const GURL referrer_url = navigation_handle()->GetReferrer().url;
- const GURL current_url = navigation_handle()->GetURL();
- const GURL last_committed_url =
- navigation_handle()->GetWebContents()->GetLastCommittedURL();
-
- // For navigations from http to https we clean up the Referrer as part of the
- // sanitization proccess, however we may still have access to the last
- // committed URL. On the other hand, navigations started within a new tab
- // (e.g. due to target="_blank") will keep no track of any previous entries
- // and so GetLastCommittedURL() can be seen empty sometimes, this is why we
- // use one or the other accordingly. Also we don't use GetVisibleURL() since
- // it may contain a still non-committed URL (i.e. it can be the same as
- // GetURL()).
- const GURL previous_url =
- referrer_url.is_empty() ? last_committed_url : referrer_url;
-
- if (!ShouldOverrideUrlLoading(previous_url, current_url))
- return content::NavigationThrottle::PROCEED;
-
- ArcServiceManager* arc_service_manager = ArcServiceManager::Get();
- DCHECK(arc_service_manager);
- scoped_refptr<LocalActivityResolver> local_resolver =
- arc_service_manager->activity_resolver();
- if (local_resolver->ShouldChromeHandleUrl(url)) {
- // Allow navigation to proceed if there isn't an android app that handles
- // the given URL.
- return content::NavigationThrottle::PROCEED;
- }
-
- auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance(
- "RequestUrlHandlerList", kMinVersionForRequestUrlHandlerList);
- if (!instance)
- return content::NavigationThrottle::PROCEED;
- instance->RequestUrlHandlerList(
- url.spec(), base::Bind(&ArcNavigationThrottle::OnAppCandidatesReceived,
- weak_ptr_factory_.GetWeakPtr()));
- return content::NavigationThrottle::DEFER;
-}
-
-// We received the array of app candidates to handle this URL (even the Chrome
-// app is included).
-void ArcNavigationThrottle::OnAppCandidatesReceived(
- mojo::Array<mojom::IntentHandlerInfoPtr> handlers) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!IsAppAvailable(handlers)) {
- // This scenario shouldn't be accesed as ArcNavigationThrottle is created
- // iff there are ARC apps which can actually handle the given URL.
- DVLOG(1) << "There are no app candidates for this URL: "
- << navigation_handle()->GetURL();
- navigation_handle()->Resume();
- return;
- }
-
- // If one of the apps is marked as preferred, use it right away without
- // showing the UI.
- const size_t index =
- FindPreferredApp(handlers, navigation_handle()->GetURL());
- if (index != handlers.size()) {
- const std::string package_name = handlers[index]->package_name;
- OnIntentPickerClosed(std::move(handlers), package_name,
- CloseReason::PREFERRED_ACTIVITY_FOUND);
- return;
- }
-
- std::pair<size_t, size_t> indices;
- if (IsSwapElementsNeeded(handlers, &indices))
- std::swap(handlers[indices.first], handlers[indices.second]);
-
- scoped_refptr<ActivityIconLoader> icon_loader = GetIconLoader();
- if (!icon_loader) {
- LOG(ERROR) << "Cannot get an instance of ActivityIconLoader";
- navigation_handle()->Resume();
- return;
- }
- std::vector<ActivityIconLoader::ActivityName> activities;
- for (const auto& handler : handlers)
- activities.emplace_back(handler->package_name, handler->activity_name);
- icon_loader->GetActivityIcons(
- activities,
- base::Bind(&ArcNavigationThrottle::OnAppIconsReceived,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&handlers)));
-}
-
-void ArcNavigationThrottle::OnAppIconsReceived(
- mojo::Array<mojom::IntentHandlerInfoPtr> handlers,
- std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> icons) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- std::vector<AppInfo> app_info;
-
- for (const auto& handler : handlers) {
- gfx::Image icon;
- const ActivityIconLoader::ActivityName activity(handler->package_name,
- handler->activity_name);
- const auto it = icons->find(activity);
-
- app_info.emplace_back(
- AppInfo(it != icons->end() ? it->second.icon20 : gfx::Image(),
- handler->package_name, handler->name));
- }
-
- show_intent_picker_callback_.Run(
- navigation_handle()->GetWebContents(), app_info,
- base::Bind(&ArcNavigationThrottle::OnIntentPickerClosed,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&handlers)));
-}
-
-void ArcNavigationThrottle::OnIntentPickerClosed(
- mojo::Array<mojom::IntentHandlerInfoPtr> handlers,
- const std::string& selected_app_package,
- CloseReason close_reason) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- const GURL& url = navigation_handle()->GetURL();
- content::NavigationHandle* handle = navigation_handle();
- previous_user_action_ = close_reason;
-
- // Make sure that the instance at least supports HandleUrl.
- auto* instance = ArcIntentHelperBridge::GetIntentHelperInstance(
- "HandleUrl", kMinVersionForHandleUrl);
- // Since we are selecting an app by its package name, we need to locate it
- // on the |handlers| structure before sending the IPC to ARC.
- const size_t selected_app_index = GetAppIndex(handlers, selected_app_package);
- if (!instance) {
- close_reason = CloseReason::ERROR;
- } else if (close_reason == CloseReason::JUST_ONCE_PRESSED ||
- close_reason == CloseReason::ALWAYS_PRESSED ||
- close_reason == CloseReason::PREFERRED_ACTIVITY_FOUND) {
- if (selected_app_index == handlers.size())
- close_reason = CloseReason::ERROR;
- }
-
- switch (close_reason) {
- case CloseReason::ERROR:
- case CloseReason::DIALOG_DEACTIVATED: {
- // If the user fails to select an option from the list, or the UI returned
- // an error or if |selected_app_index| is not a valid index, then resume
- // the navigation in Chrome.
- DVLOG(1) << "User didn't select a valid option, resuming navigation.";
- handle->Resume();
- break;
- }
- case CloseReason::ALWAYS_PRESSED: {
- // Call AddPreferredPackage if it is supported. Reusing the same
- // |instance| is okay.
- if (ArcIntentHelperBridge::GetIntentHelperInstance(
- "AddPreferredPackage", kMinVersionForAddPreferredPackage)) {
- instance->AddPreferredPackage(
- handlers[selected_app_index]->package_name);
- }
- // fall through.
- }
- case CloseReason::JUST_ONCE_PRESSED:
- case CloseReason::PREFERRED_ACTIVITY_FOUND: {
- if (ArcIntentHelperBridge::IsIntentHelperPackage(
- handlers[selected_app_index]->package_name)) {
- handle->Resume();
- } else {
- instance->HandleUrl(url.spec(), selected_app_package);
- handle->CancelDeferredNavigation(
- content::NavigationThrottle::CANCEL_AND_IGNORE);
- if (handle->GetWebContents()->GetController().IsInitialNavigation())
- handle->GetWebContents()->Close();
- }
- break;
- }
- case CloseReason::INVALID: {
- NOTREACHED();
- return;
- }
- }
-
- UMA_HISTOGRAM_ENUMERATION("Arc.IntentHandlerAction",
- static_cast<int>(close_reason),
- static_cast<int>(CloseReason::SIZE));
-}
-
-// static
-size_t ArcNavigationThrottle::GetAppIndex(
- const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers,
- const std::string& selected_app_package) {
- for (size_t i = 0; i < handlers.size(); ++i) {
- if (handlers[i]->package_name == selected_app_package)
- return i;
- }
- return handlers.size();
-}
-
-// static
-bool ArcNavigationThrottle::ShouldOverrideUrlLoadingForTesting(
- const GURL& previous_url,
- const GURL& current_url) {
- return ShouldOverrideUrlLoading(previous_url, current_url);
-}
-
-// static
-bool ArcNavigationThrottle::IsAppAvailableForTesting(
- const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) {
- return IsAppAvailable(handlers);
-}
-
-// static
-size_t ArcNavigationThrottle::FindPreferredAppForTesting(
- const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers) {
- return FindPreferredApp(handlers, GURL());
-}
-
-// static
-bool ArcNavigationThrottle::IsSwapElementsNeededForTesting(
- const mojo::Array<mojom::IntentHandlerInfoPtr>& handlers,
- std::pair<size_t, size_t>* out_indices) {
- return IsSwapElementsNeeded(handlers, out_indices);
-}
-
-} // namespace arc
« no previous file with comments | « chrome/browser/chromeos/arc/arc_navigation_throttle.h ('k') | chrome/browser/chromeos/arc/arc_navigation_throttle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698