blob: 5b13523e557561e761bcfae7197e2821f5725990 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/apps/intent_helper/apps_navigation_throttle.h"
#include <utility>
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/browser_app_launcher.h"
#include "chrome/browser/apps/intent_helper/intent_picker_internal.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_tab_helper.h"
#include "chrome/common/chrome_features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/features.h"
#include "ui/gfx/image/image.h"
#include "url/origin.h"
namespace {
using ThrottleCheckResult = content::NavigationThrottle::ThrottleCheckResult;
} // namespace
namespace apps {
// static
std::unique_ptr<content::NavigationThrottle>
AppsNavigationThrottle::MaybeCreate(content::NavigationHandle* handle) {
// Don't handle navigations in subframes or main frames that are in a nested
// frame tree (e.g. portals, fenced-frame). We specifically allow
// prerendering navigations so that we can destroy the prerender. Opening an
// app must only happen when the user intentionally navigates; however, for a
// prerender, the prerender-activating navigation doesn't run throttles so we
// must cancel it during initial loading to get a standard (non-prerendering)
// navigation at link-click-time.
if (!handle->IsInPrimaryMainFrame() && !handle->IsInPrerenderedMainFrame())
return nullptr;
content::WebContents* web_contents = handle->GetWebContents();
if (!ShouldCheckAppsForUrl(web_contents))
return nullptr;
return std::make_unique<AppsNavigationThrottle>(handle);
}
AppsNavigationThrottle::AppsNavigationThrottle(
content::NavigationHandle* navigation_handle)
: content::NavigationThrottle(navigation_handle) {}
AppsNavigationThrottle::~AppsNavigationThrottle() = default;
const char* AppsNavigationThrottle::GetNameForLogging() {
return "AppsNavigationThrottle";
}
ThrottleCheckResult AppsNavigationThrottle::WillStartRequest() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
starting_url_ = GetStartingGURL(navigation_handle());
return HandleRequest();
}
ThrottleCheckResult AppsNavigationThrottle::WillRedirectRequest() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return HandleRequest();
}
bool AppsNavigationThrottle::ShouldCancelNavigation(
content::NavigationHandle* handle) {
return false;
}
bool AppsNavigationThrottle::ShouldShowDisablePage(
content::NavigationHandle* handle) {
return false;
}
ThrottleCheckResult AppsNavigationThrottle::MaybeShowCustomResult() {
return content::NavigationThrottle::CANCEL_AND_IGNORE;
}
bool AppsNavigationThrottle::navigate_from_link() const {
return navigate_from_link_;
}
ThrottleCheckResult AppsNavigationThrottle::HandleRequest() {
content::NavigationHandle* handle = navigation_handle();
// If the navigation won't update the current document, don't check intent for
// the navigation.
if (handle->IsSameDocument())
return content::NavigationThrottle::PROCEED;
content::WebContents* web_contents = handle->GetWebContents();
const GURL& url = handle->GetURL();
navigate_from_link_ = IsNavigateFromLink(handle);
// Do not automatically launch the app if we shouldn't override url loading,
// or if we don't have a browser, or we are already in an app browser.
if (ShouldOverrideUrlLoading(starting_url_, url) &&
!InAppBrowser(web_contents)) {
// Handles apps that are automatically launched and the navigation needs to
// be cancelled. This only applies on the new intent picker system, because
// we don't need to defer the navigation to find out preferred app anymore.
if (ShouldCancelNavigation(handle)) {
return content::NavigationThrottle::CANCEL_AND_IGNORE;
}
if (ShouldShowDisablePage(handle))
return MaybeShowCustomResult();
}
return content::NavigationThrottle::PROCEED;
}
} // namespace apps