Commit 584c663e authored by Avi Drissman's avatar Avi Drissman Committed by Commit Bot

Implement support for macOS 10.15 Universal Links.

Reuse the PWA intent picker for the UI.

BUG=981337

Change-Id: Ib4956fb0218d9d6055c315a4fcb579094ea0daec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1703487
Commit-Queue: Avi Drissman <avi@chromium.org>
Reviewed-by: default avatarMaggie Cai <mxcai@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680138}
parent 34c55a35
...@@ -363,7 +363,19 @@ typedef NSString* NSAppearanceName; ...@@ -363,7 +363,19 @@ typedef NSString* NSAppearanceName;
BASE_EXPORT extern NSAppearanceName const NSAppearanceNameDarkAqua; BASE_EXPORT extern NSAppearanceName const NSAppearanceNameDarkAqua;
#endif #endif // MAC_OS_X_VERSION_10_14
#if !defined(MAC_OS_X_VERSION_10_15) || \
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_15
@interface SFUniversalLink : NSObject
- (instancetype)initWithWebpageURL:(NSURL*)url;
@property(readonly) NSURL* webpageURL;
@property(readonly) NSURL* applicationURL;
@property(getter=isEnabled) BOOL enabled;
@end
#endif // MAC_OS_X_VERSION_10_15
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// The symbol for kCWSSIDDidChangeNotification is available in the // The symbol for kCWSSIDDidChangeNotification is available in the
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
<array> <array>
<string>${CHROMIUM_TEAM_ID}.${CHROMIUM_BUNDLE_ID}.webauthn</string> <string>${CHROMIUM_TEAM_ID}.${CHROMIUM_BUNDLE_ID}.webauthn</string>
</array> </array>
<key>com.apple.developer.associated-domains.applinks.read-write</key>
<true/>
<key>com.apple.security.device.audio-input</key> <key>com.apple.security.device.audio-input</key>
<true/> <true/>
<key>com.apple.security.device.bluetooth</key> <key>com.apple.security.device.bluetooth</key>
......
...@@ -3785,6 +3785,8 @@ jumbo_split_static_library("browser") { ...@@ -3785,6 +3785,8 @@ jumbo_split_static_library("browser") {
if (is_mac) { if (is_mac) {
allow_circular_includes_from += [ "//chrome/browser/apps/app_shim" ] allow_circular_includes_from += [ "//chrome/browser/apps/app_shim" ]
sources += [ sources += [
"apps/intent_helper/mac_apps_navigation_throttle.h",
"apps/intent_helper/mac_apps_navigation_throttle.mm",
"badging/badge_manager_delegate_mac.cc", "badging/badge_manager_delegate_mac.cc",
"badging/badge_manager_delegate_mac.h", "badging/badge_manager_delegate_mac.h",
"download/drag_download_item_mac.mm", "download/drag_download_item_mac.mm",
...@@ -3807,6 +3809,9 @@ jumbo_split_static_library("browser") { ...@@ -3807,6 +3809,9 @@ jumbo_split_static_library("browser") {
"ImageCaptureCore.framework", "ImageCaptureCore.framework",
"OpenGL.framework", "OpenGL.framework",
"QuartzCore.framework", "QuartzCore.framework",
# TODO(avi): When we move to the 10.15 SDK, -weak_framework SafariServices
# here and remove the manual framework opening code.
"SecurityInterface.framework", "SecurityInterface.framework",
] ]
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h" #include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h"
#include "chrome/browser/apps/intent_helper/page_transition_util.h" #include "chrome/browser/apps/intent_helper/page_transition_util.h"
#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/extension_util.h"
...@@ -160,6 +161,7 @@ void AppsNavigationThrottle::OnIntentPickerClosed( ...@@ -160,6 +161,7 @@ void AppsNavigationThrottle::OnIntentPickerClosed(
case apps::mojom::AppType::kBuiltIn: case apps::mojom::AppType::kBuiltIn:
case apps::mojom::AppType::kCrostini: case apps::mojom::AppType::kCrostini:
case apps::mojom::AppType::kExtension: case apps::mojom::AppType::kExtension:
case apps::mojom::AppType::kMacNative:
NOTREACHED(); NOTREACHED();
} }
RecordUma(launch_name, app_type, close_reason, Source::kHttpOrHttps, RecordUma(launch_name, app_type, close_reason, Source::kHttpOrHttps,
...@@ -293,6 +295,8 @@ AppsNavigationThrottle::Platform AppsNavigationThrottle::GetDestinationPlatform( ...@@ -293,6 +295,8 @@ AppsNavigationThrottle::Platform AppsNavigationThrottle::GetDestinationPlatform(
return Platform::ARC; return Platform::ARC;
case PickerAction::PWA_APP_PRESSED: case PickerAction::PWA_APP_PRESSED:
return Platform::PWA; return Platform::PWA;
case PickerAction::MAC_NATIVE_APP_PRESSED:
return Platform::MAC_NATIVE;
case PickerAction::ERROR_BEFORE_PICKER: case PickerAction::ERROR_BEFORE_PICKER:
case PickerAction::ERROR_AFTER_PICKER: case PickerAction::ERROR_AFTER_PICKER:
case PickerAction::DIALOG_DEACTIVATED: case PickerAction::DIALOG_DEACTIVATED:
...@@ -344,11 +348,12 @@ void AppsNavigationThrottle::CloseOrGoBack(content::WebContents* web_contents) { ...@@ -344,11 +348,12 @@ void AppsNavigationThrottle::CloseOrGoBack(content::WebContents* web_contents) {
} }
// static // static
bool AppsNavigationThrottle::ContainsOnlyPwas( bool AppsNavigationThrottle::ContainsOnlyPwasAndMacApps(
const std::vector<apps::IntentPickerAppInfo>& apps) { const std::vector<apps::IntentPickerAppInfo>& apps) {
return std::all_of(apps.begin(), apps.end(), return std::all_of(apps.begin(), apps.end(),
[](const apps::IntentPickerAppInfo& app_info) { [](const apps::IntentPickerAppInfo& app_info) {
return app_info.type == apps::mojom::AppType::kWeb; return app_info.type == apps::mojom::AppType::kWeb ||
app_info.type == apps::mojom::AppType::kMacNative;
}); });
} }
...@@ -359,7 +364,9 @@ bool AppsNavigationThrottle::ShouldShowPersistenceOptions( ...@@ -359,7 +364,9 @@ bool AppsNavigationThrottle::ShouldShowPersistenceOptions(
// if only PWAs are present. // if only PWAs are present.
// TODO(crbug.com/826982): Provide the "Remember my choice" option when the // TODO(crbug.com/826982): Provide the "Remember my choice" option when the
// app registry can support persistence for PWAs. // app registry can support persistence for PWAs.
return !ContainsOnlyPwas(apps); // TODO(avi): When Chrome gains a UI for managing the persistence of PWAs,
// reuse that UI for managing the persistent behavior of Universal Links.
return !ContainsOnlyPwasAndMacApps(apps);
} }
bool AppsNavigationThrottle::ShouldDeferNavigationForArc( bool AppsNavigationThrottle::ShouldDeferNavigationForArc(
...@@ -367,6 +374,11 @@ bool AppsNavigationThrottle::ShouldDeferNavigationForArc( ...@@ -367,6 +374,11 @@ bool AppsNavigationThrottle::ShouldDeferNavigationForArc(
return false; return false;
} }
std::vector<IntentPickerAppInfo> AppsNavigationThrottle::AppInfoForUrl(
const GURL& url) {
return std::vector<IntentPickerAppInfo>{};
}
void AppsNavigationThrottle::ShowIntentPickerForApps( void AppsNavigationThrottle::ShowIntentPickerForApps(
content::WebContents* web_contents, content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service, IntentPickerAutoDisplayService* ui_auto_display_service,
...@@ -446,6 +458,8 @@ AppsNavigationThrottle::PickerAction AppsNavigationThrottle::GetPickerAction( ...@@ -446,6 +458,8 @@ AppsNavigationThrottle::PickerAction AppsNavigationThrottle::GetPickerAction(
: PickerAction::ARC_APP_PRESSED; : PickerAction::ARC_APP_PRESSED;
case apps::mojom::AppType::kWeb: case apps::mojom::AppType::kWeb:
return PickerAction::PWA_APP_PRESSED; return PickerAction::PWA_APP_PRESSED;
case apps::mojom::AppType::kMacNative:
return PickerAction::MAC_NATIVE_APP_PRESSED;
case apps::mojom::AppType::kBuiltIn: case apps::mojom::AppType::kBuiltIn:
case apps::mojom::AppType::kCrostini: case apps::mojom::AppType::kCrostini:
case apps::mojom::AppType::kExtension: case apps::mojom::AppType::kExtension:
...@@ -506,8 +520,11 @@ AppsNavigationThrottle::HandleRequest() { ...@@ -506,8 +520,11 @@ AppsNavigationThrottle::HandleRequest() {
} }
// We didn't query ARC, so proceed with the navigation and query if we have an // We didn't query ARC, so proceed with the navigation and query if we have an
// installed desktop PWA to handle the URL. // installed desktop app to handle the URL.
std::vector<IntentPickerAppInfo> apps = FindPwaForUrl(web_contents, url, {}); std::vector<IntentPickerAppInfo> apps = AppInfoForUrl(url);
// Perhaps an installed desktop PWA?
apps = FindPwaForUrl(web_contents, url, std::move(apps));
if (!apps.empty()) if (!apps.empty())
ui_displayed_ = true; ui_displayed_ = true;
......
...@@ -129,17 +129,19 @@ class AppsNavigationThrottle : public content::NavigationThrottle { ...@@ -129,17 +129,19 @@ class AppsNavigationThrottle : public content::NavigationThrottle {
// Picker errors occurring before the picker is shown. // Picker errors occurring before the picker is shown.
ERROR_BEFORE_PICKER = 10, ERROR_BEFORE_PICKER = 10,
INVALID = 11, INVALID = 11,
kMaxValue = INVALID, MAC_NATIVE_APP_PRESSED = 12,
kMaxValue = MAC_NATIVE_APP_PRESSED,
}; };
// As for PickerAction, these define the buckets for an UMA histogram, so this // As for PickerAction, these define the buckets for an UMA histogram, so this
// must be treated in an append-only fashion. This helps especify where a // must be treated in an append-only fashion. This helps specify where a
// navigation will continue. // navigation will continue.
enum class Platform : int { enum class Platform : int {
ARC = 0, ARC = 0,
CHROME = 1, CHROME = 1,
PWA = 2, PWA = 2,
kMaxValue = PWA, MAC_NATIVE = 3,
kMaxValue = MAC_NATIVE,
}; };
// These enums are used to define the intent picker show state, whether the // These enums are used to define the intent picker show state, whether the
...@@ -170,19 +172,22 @@ class AppsNavigationThrottle : public content::NavigationThrottle { ...@@ -170,19 +172,22 @@ class AppsNavigationThrottle : public content::NavigationThrottle {
static void CloseOrGoBack(content::WebContents* web_contents); static void CloseOrGoBack(content::WebContents* web_contents);
static bool ContainsOnlyPwas( static bool ContainsOnlyPwasAndMacApps(
const std::vector<apps::IntentPickerAppInfo>& apps); const std::vector<apps::IntentPickerAppInfo>& apps);
static bool ShouldShowPersistenceOptions( static bool ShouldShowPersistenceOptions(
std::vector<apps::IntentPickerAppInfo>& apps); std::vector<apps::IntentPickerAppInfo>& apps);
// Overridden for Chrome OS to allow arc handling. // Overrides for Chrome OS to allow ARC handling.
virtual void MaybeRemoveComingFromArcFlag(content::WebContents* web_contents, virtual void MaybeRemoveComingFromArcFlag(content::WebContents* web_contents,
const GURL& previous_url, const GURL& previous_url,
const GURL& current_url) {} const GURL& current_url) {}
virtual bool ShouldDeferNavigationForArc(content::NavigationHandle* handle); virtual bool ShouldDeferNavigationForArc(content::NavigationHandle* handle);
// Allows a subclass to synchronously provide app info.
virtual std::vector<IntentPickerAppInfo> AppInfoForUrl(const GURL& url);
void ShowIntentPickerForApps( void ShowIntentPickerForApps(
content::WebContents* web_contents, content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service, IntentPickerAutoDisplayService* ui_auto_display_service,
......
...@@ -84,8 +84,9 @@ struct IntentPickerAppInfo { ...@@ -84,8 +84,9 @@ struct IntentPickerAppInfo {
// The icon to be displayed for this app in the picker. // The icon to be displayed for this app in the picker.
gfx::Image icon; gfx::Image icon;
// The string used to launch this app. Represents an Android package name // The string used to launch this app. Represents an Android package name when
// when type is ARC. // |type| is kArc, and when |type| is kMacNative, it is the file path of the
// native app to use.
std::string launch_name; std::string launch_name;
// The string shown to the user to identify this app in the intent picker. // The string shown to the user to identify this app in the intent picker.
......
// Copyright 2019 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.
#ifndef CHROME_BROWSER_APPS_INTENT_HELPER_MAC_APPS_NAVIGATION_THROTTLE_H_
#define CHROME_BROWSER_APPS_INTENT_HELPER_MAC_APPS_NAVIGATION_THROTTLE_H_
#include "chrome/browser/apps/intent_helper/apps_navigation_throttle.h"
// This file implements support for the macOS feature of Universal Links,
// introduced in macOS 10.15. See:
// - https://developer.apple.com/ios/universal-links/
// - https://developer.apple.com/documentation/safariservices/sfuniversallink
// - https://crbug.com/981337
namespace apps {
class MacAppsNavigationThrottle : public apps::AppsNavigationThrottle {
public:
// Possibly creates a navigation throttle that checks if any installed apps
// can handle the URL being navigated to. The user is prompted if they wish to
// open the app or remain in the browser.
static std::unique_ptr<apps::AppsNavigationThrottle> MaybeCreate(
content::NavigationHandle* handle);
// Queries for installed apps which can handle |url|, and displays the intent
// picker bubble for |web_contents|.
static void ShowIntentPickerBubble(
content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service,
const GURL& url);
explicit MacAppsNavigationThrottle(
content::NavigationHandle* navigation_handle);
~MacAppsNavigationThrottle() override;
private:
// Called when the intent picker is closed for |url|, in |web_contents|, with
// |launch_name| as the (possibly empty) action to be triggered based on
// |app_type|. |close_reason| gives the reason for the picker being closed,
// and |should_persist| is true if the user indicated they wish to remember
// the choice made. |ui_auto_display_service| keeps track of whether or not
// the user dismissed the ui without engaging with it.
static void OnIntentPickerClosed(
content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service,
const GURL& url,
const std::string& launch_name,
apps::mojom::AppType app_type,
apps::IntentPickerCloseReason close_reason,
bool should_persist);
PickerShowState GetPickerShowState(
const std::vector<apps::IntentPickerAppInfo>& apps_for_picker,
content::WebContents* web_contents,
const GURL& url) override;
IntentPickerResponse GetOnPickerClosedCallback(
content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service,
const GURL& url) override;
std::vector<IntentPickerAppInfo> AppInfoForUrl(const GURL& url) override;
DISALLOW_COPY_AND_ASSIGN(MacAppsNavigationThrottle);
};
} // namespace apps
#endif // CHROME_BROWSER_APPS_INTENT_HELPER_MAC_APPS_NAVIGATION_THROTTLE_H_
// Copyright 2019 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/apps/intent_helper/mac_apps_navigation_throttle.h"
#import <Cocoa/Cocoa.h>
#include <dlfcn.h>
#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/sys_string_conversions.h"
#include "content/public/browser/navigation_handle.h"
#include "net/base/mac/url_conversions.h"
namespace apps {
namespace {
const char kSafariServicesFrameworkPath[] =
"/System/Library/Frameworks/SafariServices.framework/"
"Versions/Current/SafariServices";
IntentPickerAppInfo AppInfoForAppUrl(NSURL* app_url) {
NSString* app_name = nil;
if (![app_url getResourceValue:&app_name
forKey:NSURLLocalizedNameKey
error:nil]) {
// This shouldn't happen but just in case.
app_name = [app_url lastPathComponent];
}
NSImage* app_icon = nil;
if (![app_url getResourceValue:&app_icon
forKey:NSURLEffectiveIconKey
error:nil]) {
// This shouldn't happen but just in case.
app_icon = [NSImage imageNamed:NSImageNameApplicationIcon];
}
app_icon.size = NSMakeSize(16, 16);
return IntentPickerAppInfo(apps::mojom::AppType::kMacNative,
gfx::Image(app_icon),
base::SysNSStringToUTF8([app_url path]),
base::SysNSStringToUTF8(app_name));
}
SFUniversalLink* GetUniversalLink(const GURL& url) {
static void* safari_services = []() -> void* {
if (@available(macOS 10.15, *))
return dlopen(kSafariServicesFrameworkPath, RTLD_LAZY);
return nullptr;
}();
static const Class SFUniversalLink_class =
NSClassFromString(@"SFUniversalLink");
if (!safari_services || !SFUniversalLink_class)
return nil;
return [[[SFUniversalLink_class alloc]
initWithWebpageURL:net::NSURLWithGURL(url)] autorelease];
}
std::vector<IntentPickerAppInfo> AppInfoForUrlImpl(const GURL& url) {
std::vector<IntentPickerAppInfo> apps;
SFUniversalLink* link = GetUniversalLink(url);
if (link)
apps.push_back(AppInfoForAppUrl(link.applicationURL));
return apps;
}
} // namespace
// static
std::unique_ptr<apps::AppsNavigationThrottle>
MacAppsNavigationThrottle::MaybeCreate(content::NavigationHandle* handle) {
if (!handle->IsInMainFrame())
return nullptr;
if (!apps::AppsNavigationThrottle::CanCreate(handle->GetWebContents()))
return nullptr;
return std::make_unique<MacAppsNavigationThrottle>(handle);
}
// static
void MacAppsNavigationThrottle::ShowIntentPickerBubble(
content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service,
const GURL& url) {
// First, the Universal Link, if there is one.
std::vector<IntentPickerAppInfo> apps = AppInfoForUrlImpl(url);
// Then, any PWAs.
apps = apps::AppsNavigationThrottle::FindPwaForUrl(web_contents, url,
std::move(apps));
bool show_persistence_options = ShouldShowPersistenceOptions(apps);
apps::AppsNavigationThrottle::ShowIntentPickerBubbleForApps(
web_contents, std::move(apps), show_persistence_options,
base::BindOnce(&OnIntentPickerClosed, web_contents,
ui_auto_display_service, url));
}
MacAppsNavigationThrottle::MacAppsNavigationThrottle(
content::NavigationHandle* navigation_handle)
: apps::AppsNavigationThrottle(navigation_handle) {}
MacAppsNavigationThrottle::~MacAppsNavigationThrottle() = default;
// static
void MacAppsNavigationThrottle::OnIntentPickerClosed(
content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service,
const GURL& url,
const std::string& launch_name,
apps::mojom::AppType app_type,
apps::IntentPickerCloseReason close_reason,
bool should_persist) {
if (app_type == apps::mojom::AppType::kMacNative) {
if (close_reason == apps::IntentPickerCloseReason::OPEN_APP) {
[[NSWorkspace sharedWorkspace]
openURLs:@[ net::NSURLWithGURL(url) ]
withApplicationAtURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString(
launch_name)]
options:0
configuration:@{}
error:nil];
}
apps::AppsNavigationThrottle::RecordUma(launch_name, app_type, close_reason,
Source::kHttpOrHttps,
should_persist);
return;
}
apps::AppsNavigationThrottle::OnIntentPickerClosed(
web_contents, ui_auto_display_service, url, launch_name, app_type,
close_reason, should_persist);
}
apps::AppsNavigationThrottle::PickerShowState
MacAppsNavigationThrottle::GetPickerShowState(
const std::vector<apps::IntentPickerAppInfo>& apps_for_picker,
content::WebContents* web_contents,
const GURL& url) {
return PickerShowState::kOmnibox;
}
IntentPickerResponse MacAppsNavigationThrottle::GetOnPickerClosedCallback(
content::WebContents* web_contents,
IntentPickerAutoDisplayService* ui_auto_display_service,
const GURL& url) {
return base::BindOnce(&OnIntentPickerClosed, web_contents,
ui_auto_display_service, url);
}
std::vector<IntentPickerAppInfo> MacAppsNavigationThrottle::AppInfoForUrl(
const GURL& url) {
return AppInfoForUrlImpl(url);
}
} // namespace apps
...@@ -386,6 +386,7 @@ ...@@ -386,6 +386,7 @@
#include "components/services/quarantine/public/cpp/quarantine_features_win.h" #include "components/services/quarantine/public/cpp/quarantine_features_win.h"
#include "sandbox/win/src/sandbox_policy.h" #include "sandbox/win/src/sandbox_policy.h"
#elif defined(OS_MACOSX) #elif defined(OS_MACOSX)
#include "chrome/browser/apps/intent_helper/mac_apps_navigation_throttle.h"
#include "chrome/browser/chrome_browser_main_mac.h" #include "chrome/browser/chrome_browser_main_mac.h"
#include "services/audio/public/mojom/constants.mojom.h" #include "services/audio/public/mojom/constants.mojom.h"
#include "services/video_capture/public/mojom/constants.mojom.h" #include "services/video_capture/public/mojom/constants.mojom.h"
...@@ -4289,6 +4290,8 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation( ...@@ -4289,6 +4290,8 @@ ChromeContentBrowserClient::CreateThrottlesForNavigation(
auto url_to_apps_throttle = auto url_to_apps_throttle =
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
chromeos::ChromeOsAppsNavigationThrottle::MaybeCreate(handle); chromeos::ChromeOsAppsNavigationThrottle::MaybeCreate(handle);
#elif defined(OS_MACOSX)
apps::MacAppsNavigationThrottle::MaybeCreate(handle);
#else #else
apps::AppsNavigationThrottle::MaybeCreate(handle); apps::AppsNavigationThrottle::MaybeCreate(handle);
#endif #endif
......
...@@ -93,6 +93,7 @@ void ChromeOsAppsNavigationThrottle::OnIntentPickerClosed( ...@@ -93,6 +93,7 @@ void ChromeOsAppsNavigationThrottle::OnIntentPickerClosed(
case apps::mojom::AppType::kBuiltIn: case apps::mojom::AppType::kBuiltIn:
case apps::mojom::AppType::kCrostini: case apps::mojom::AppType::kCrostini:
case apps::mojom::AppType::kExtension: case apps::mojom::AppType::kExtension:
case apps::mojom::AppType::kMacNative:
break; break;
} }
apps::AppsNavigationThrottle::OnIntentPickerClosed( apps::AppsNavigationThrottle::OnIntentPickerClosed(
...@@ -162,6 +163,7 @@ ChromeOsAppsNavigationThrottle::GetDestinationPlatform( ...@@ -162,6 +163,7 @@ ChromeOsAppsNavigationThrottle::GetDestinationPlatform(
case PickerAction::CHROME_PREFERRED_PRESSED: case PickerAction::CHROME_PREFERRED_PRESSED:
case PickerAction::OBSOLETE_ALWAYS_PRESSED: case PickerAction::OBSOLETE_ALWAYS_PRESSED:
case PickerAction::OBSOLETE_JUST_ONCE_PRESSED: case PickerAction::OBSOLETE_JUST_ONCE_PRESSED:
case PickerAction::MAC_NATIVE_APP_PRESSED:
case PickerAction::INVALID: case PickerAction::INVALID:
break; break;
} }
...@@ -286,7 +288,7 @@ bool ChromeOsAppsNavigationThrottle::ShouldAutoDisplayUi( ...@@ -286,7 +288,7 @@ bool ChromeOsAppsNavigationThrottle::ShouldAutoDisplayUi(
// until "Remember my choice" is available for desktop PWAs. // until "Remember my choice" is available for desktop PWAs.
// TODO(crbug.com/826982): show the intent picker when the app registry is // TODO(crbug.com/826982): show the intent picker when the app registry is
// available to persist "Remember my choice" for PWAs. // available to persist "Remember my choice" for PWAs.
if (ContainsOnlyPwas(apps_for_picker)) if (ContainsOnlyPwasAndMacApps(apps_for_picker))
return false; return false;
DCHECK(ui_auto_display_service_); DCHECK(ui_auto_display_service_);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_config.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/logging.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
...@@ -43,6 +44,10 @@ std::unique_ptr<app_list::AppContextMenu> AppServiceAppItem::MakeAppContextMenu( ...@@ -43,6 +44,10 @@ std::unique_ptr<app_list::AppContextMenu> AppServiceAppItem::MakeAppContextMenu(
case apps::mojom::AppType::kWeb: case apps::mojom::AppType::kWeb:
return std::make_unique<app_list::ExtensionAppContextMenu>( return std::make_unique<app_list::ExtensionAppContextMenu>(
delegate, profile, app_id, controller, is_platform_app); delegate, profile, app_id, controller, is_platform_app);
case apps::mojom::AppType::kMacNative:
NOTREACHED() << "Should not be trying to make a menu for a native app";
return nullptr;
} }
return nullptr; return nullptr;
......
...@@ -76,11 +76,9 @@ class IntentPickerLabelButton : public views::LabelButton { ...@@ -76,11 +76,9 @@ class IntentPickerLabelButton : public views::LabelButton {
public: public:
IntentPickerLabelButton(views::ButtonListener* listener, IntentPickerLabelButton(views::ButtonListener* listener,
const gfx::Image* icon, const gfx::Image* icon,
const std::string& launch_name,
const std::string& display_name) const std::string& display_name)
: LabelButton(listener, : LabelButton(listener,
base::UTF8ToUTF16(base::StringPiece(display_name))), base::UTF8ToUTF16(base::StringPiece(display_name))) {
launch_name_(launch_name) {
SetHorizontalAlignment(gfx::ALIGN_LEFT); SetHorizontalAlignment(gfx::ALIGN_LEFT);
SetMinSize(gfx::Size(kMaxIntentPickerLabelButtonWidth, kRowHeight)); SetMinSize(gfx::Size(kMaxIntentPickerLabelButtonWidth, kRowHeight));
SetInkDropMode(InkDropMode::ON); SetInkDropMode(InkDropMode::ON);
...@@ -106,9 +104,6 @@ class IntentPickerLabelButton : public views::LabelButton { ...@@ -106,9 +104,6 @@ class IntentPickerLabelButton : public views::LabelButton {
return GetInkDrop()->GetTargetInkDropState(); return GetInkDrop()->GetTargetInkDropState();
} }
private:
std::string launch_name_;
DISALLOW_COPY_AND_ASSIGN(IntentPickerLabelButton); DISALLOW_COPY_AND_ASSIGN(IntentPickerLabelButton);
}; };
...@@ -353,7 +348,7 @@ void IntentPickerBubbleView::Initialize() { ...@@ -353,7 +348,7 @@ void IntentPickerBubbleView::Initialize() {
} }
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
auto app_button = std::make_unique<IntentPickerLabelButton>( auto app_button = std::make_unique<IntentPickerLabelButton>(
this, &app_info.icon, app_info.launch_name, app_info.display_name); this, &app_info.icon, app_info.display_name);
app_button->set_tag(i); app_button->set_tag(i);
scrollable_view->AddChildViewAt(std::move(app_button), i++); scrollable_view->AddChildViewAt(std::move(app_button), i++);
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/intent_picker_view.h"
#include "build/build_config.h"
#include "chrome/browser/apps/intent_helper/apps_navigation_throttle.h" #include "chrome/browser/apps/intent_helper/apps_navigation_throttle.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
...@@ -19,6 +20,10 @@ ...@@ -19,6 +20,10 @@
#include "chrome/browser/chromeos/apps/intent_helper/chromeos_apps_navigation_throttle.h" #include "chrome/browser/chromeos/apps/intent_helper/chromeos_apps_navigation_throttle.h"
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
#if defined(OS_MACOSX)
#include "chrome/browser/apps/intent_helper/mac_apps_navigation_throttle.h"
#endif // defined(OS_MACOSX)
namespace content { namespace content {
class WebContents; class WebContents;
} }
...@@ -48,6 +53,9 @@ void IntentPickerView::OnExecuting( ...@@ -48,6 +53,9 @@ void IntentPickerView::OnExecuting(
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
chromeos::ChromeOsAppsNavigationThrottle::ShowIntentPickerBubble( chromeos::ChromeOsAppsNavigationThrottle::ShowIntentPickerBubble(
web_contents, /*ui_auto_display_service=*/nullptr, url); web_contents, /*ui_auto_display_service=*/nullptr, url);
#elif defined(OS_MACOSX)
apps::MacAppsNavigationThrottle::ShowIntentPickerBubble(
web_contents, /*ui_auto_display_service=*/nullptr, url);
#else #else
apps::AppsNavigationThrottle::ShowIntentPickerBubble( apps::AppsNavigationThrottle::ShowIntentPickerBubble(
web_contents, /*ui_auto_display_service=*/nullptr, url); web_contents, /*ui_auto_display_service=*/nullptr, url);
......
...@@ -67,9 +67,10 @@ enum AppType { ...@@ -67,9 +67,10 @@ enum AppType {
kUnknown = 0, kUnknown = 0,
kArc, // Android app. kArc, // Android app.
kBuiltIn, // Built-in app. kBuiltIn, // Built-in app.
kCrostini, // Linux app. kCrostini, // Linux (via Crostini) app.
kExtension, // Extension-backed app. kExtension, // Extension-backed app.
kWeb, // Web app. kWeb, // Web app.
kMacNative, // Native Mac app.
}; };
// Whether an app is ready to launch, i.e. installed. // Whether an app is ready to launch, i.e. installed.
......
...@@ -2412,18 +2412,18 @@ Unknown properties are collapsed to zero. --> ...@@ -2412,18 +2412,18 @@ Unknown properties are collapsed to zero. -->
<int value="8" label="ARC app preferred and pressed"/> <int value="8" label="ARC app preferred and pressed"/>
<int value="9" label="Progressive web app pressed"/> <int value="9" label="Progressive web app pressed"/>
<int value="10" label="Error before showing picker"/> <int value="10" label="Error before showing picker"/>
<int value="11" label="Invalid"/>
<int value="12" label="Mac native app pressed"/>
</enum> </enum>
<enum name="ArcIntentHandlerDestinationPlatform"> <enum name="ArcIntentHandlerDestinationPlatform">
<obsolete>
Deprecated as of 9/2018 (M71).
</obsolete>
<summary> <summary>
Defines ARC intent handler platforms to continue the navigation. Defines ARC intent handler platforms to continue the navigation.
</summary> </summary>
<int value="0" label="ARC"/> <int value="0" label="ARC"/>
<int value="1" label="Chrome"/> <int value="1" label="Chrome"/>
<int value="2" label="Progressive web app"/> <int value="2" label="Progressive web app"/>
<int value="3" label="Mac native app"/>
</enum> </enum>
<enum name="ArcIntentHelperOpenType"> <enum name="ArcIntentHelperOpenType">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment