Commit 93ce65c8 authored by Ewann's avatar Ewann Committed by Commit Bot

Open Downloads in Files.app

The purpose of this patch is to directly open Files.app to present downloaded files from Chrome.
To open Files.app from Chrome, I use a URL which unfortunately is not documented but still used by Apple to create folder shortcuts.
This functionality is developed under a flag "kOpenDownloadsInFilesApp".

Bug: 1052851
Change-Id: I30d9ba7cdafbddd5bc852faf3ce8bc83807bafb5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2060370Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Commit-Queue: Ewann Pellé <ewannpv@chromium.org>
Cr-Commit-Position: refs/heads/master@{#747300}
parent 2d444bf7
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DIRECTORY_UTIL_H_ #ifndef IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DIRECTORY_UTIL_H_
#define IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DIRECTORY_UTIL_H_ #define IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DIRECTORY_UTIL_H_
#import <Foundation/Foundation.h>
namespace base { namespace base {
class FilePath; class FilePath;
} }
...@@ -17,4 +19,8 @@ bool GetDownloadsDirectory(base::FilePath* directory_path); ...@@ -17,4 +19,8 @@ bool GetDownloadsDirectory(base::FilePath* directory_path);
// Asynchronously deletes downloads directory. // Asynchronously deletes downloads directory.
void DeleteDownloadsDirectory(); void DeleteDownloadsDirectory();
// Returns URL which can be used to open Chrome's directory in files.app.
// Returns nil if it cannot get the directory.
NSURL* GetFilesAppDownloadsDirectoryUrl();
#endif // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DIRECTORY_UTIL_H_ #endif // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DIRECTORY_UTIL_H_
...@@ -52,3 +52,14 @@ void DeleteDownloadsDirectory() { ...@@ -52,3 +52,14 @@ void DeleteDownloadsDirectory() {
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&DeleteDownloadsDirectorySync)); base::BindOnce(&DeleteDownloadsDirectorySync));
} }
NSURL* GetFilesAppDownloadsDirectoryUrl() {
base::FilePath download_dir;
if (!GetDownloadsDirectory(&download_dir)) {
return nil;
}
return [NSURL
URLWithString:[NSString stringWithFormat:@"shareddocuments://%s",
download_dir.value().c_str()]];
}
...@@ -47,6 +47,7 @@ source_set("flags") { ...@@ -47,6 +47,7 @@ source_set("flags") {
"//ios/chrome/browser/passwords:feature_flags", "//ios/chrome/browser/passwords:feature_flags",
"//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/dialogs:feature_flags", "//ios/chrome/browser/ui/dialogs:feature_flags",
"//ios/chrome/browser/ui/download:features",
"//ios/chrome/browser/ui/fullscreen:feature_flags", "//ios/chrome/browser/ui/fullscreen:feature_flags",
"//ios/chrome/browser/ui/infobars:feature_flags", "//ios/chrome/browser/ui/infobars:feature_flags",
"//ios/chrome/browser/ui/page_info:features", "//ios/chrome/browser/ui/page_info:features",
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include "ios/chrome/browser/passwords/password_manager_features.h" #include "ios/chrome/browser/passwords/password_manager_features.h"
#include "ios/chrome/browser/system_flags.h" #include "ios/chrome/browser/system_flags.h"
#import "ios/chrome/browser/ui/dialogs/dialog_features.h" #import "ios/chrome/browser/ui/dialogs/dialog_features.h"
#import "ios/chrome/browser/ui/download/features.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
#import "ios/chrome/browser/ui/infobars/infobar_feature.h" #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
#import "ios/chrome/browser/ui/page_info/features.h" #import "ios/chrome/browser/ui/page_info/features.h"
...@@ -603,6 +604,10 @@ const flags_ui::FeatureEntry kFeatureEntries[] = { ...@@ -603,6 +604,10 @@ const flags_ui::FeatureEntry kFeatureEntries[] = {
flags_ui::kOsIos, flags_ui::kOsIos,
FEATURE_VALUE_TYPE( FEATURE_VALUE_TYPE(
fullscreen::features::kFullscreenControllerBrowserScoped)}, fullscreen::features::kFullscreenControllerBrowserScoped)},
{"open-downloads-in-files.app",
flag_descriptions::kOpenDownloadsInFilesAppName,
flag_descriptions::kOpenDownloadsInFilesAppDescription, flags_ui::kOsIos,
FEATURE_VALUE_TYPE(kOpenDownloadsInFilesApp)},
}; };
// Add all switches from experimental flags to |command_line|. // Add all switches from experimental flags to |command_line|.
......
...@@ -316,6 +316,12 @@ const char kOmniboxOnFocusSuggestionsDescription[] = ...@@ -316,6 +316,12 @@ const char kOmniboxOnFocusSuggestionsDescription[] =
"before the user has typed any input. This provides overrides for the " "before the user has typed any input. This provides overrides for the "
"default suggestion locations."; "default suggestion locations.";
const char kOpenDownloadsInFilesAppName[] = "Open Downloads in Files.app";
const char kOpenDownloadsInFilesAppDescription[] =
"Allows user to open Files.app after pressing the 'Downloads' button from "
"the tools menu or after pressing the 'Open in downloads' button invoked "
"by pressing 'Open In...' after download completes.";
const char kPageInfoRefactoringName[] = "New design of the page info"; const char kPageInfoRefactoringName[] = "New design of the page info";
const char kPageInfoRefactoringDescription[] = const char kPageInfoRefactoringDescription[] =
"Uses the new design for the page security info."; "Uses the new design for the page security info.";
......
...@@ -269,6 +269,10 @@ extern const char kOmniboxOnDeviceHeadSuggestionsDescription[]; ...@@ -269,6 +269,10 @@ extern const char kOmniboxOnDeviceHeadSuggestionsDescription[];
extern const char kOmniboxOnFocusSuggestionsName[]; extern const char kOmniboxOnFocusSuggestionsName[];
extern const char kOmniboxOnFocusSuggestionsDescription[]; extern const char kOmniboxOnFocusSuggestionsDescription[];
// Title and description for the flag to open Downloaded files in Files.app.
extern const char kOpenDownloadsInFilesAppName[];
extern const char kOpenDownloadsInFilesAppDescription[];
// Title and description for the flag to enable the new design of the page info. // Title and description for the flag to enable the new design of the page info.
extern const char kPageInfoRefactoringName[]; extern const char kPageInfoRefactoringName[];
extern const char kPageInfoRefactoringDescription[]; extern const char kPageInfoRefactoringDescription[];
......
...@@ -95,6 +95,7 @@ source_set("browser_view") { ...@@ -95,6 +95,7 @@ source_set("browser_view") {
"//ios/chrome/browser/ui/dialogs:dialogs_internal", "//ios/chrome/browser/ui/dialogs:dialogs_internal",
"//ios/chrome/browser/ui/dialogs:feature_flags", "//ios/chrome/browser/ui/dialogs:feature_flags",
"//ios/chrome/browser/ui/download", "//ios/chrome/browser/ui/download",
"//ios/chrome/browser/ui/download:features",
"//ios/chrome/browser/ui/elements:elements_internal", "//ios/chrome/browser/ui/elements:elements_internal",
"//ios/chrome/browser/ui/find_bar", "//ios/chrome/browser/ui/find_bar",
"//ios/chrome/browser/ui/first_run", "//ios/chrome/browser/ui/first_run",
...@@ -195,6 +196,7 @@ source_set("unit_tests") { ...@@ -195,6 +196,7 @@ source_set("unit_tests") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
testonly = true testonly = true
sources = [ sources = [
"browser_coordinator_unittest.mm",
"browser_view_controller_helper_unittest.mm", "browser_view_controller_helper_unittest.mm",
"browser_view_controller_unittest.mm", "browser_view_controller_unittest.mm",
"key_commands_provider_unittest.mm", "key_commands_provider_unittest.mm",
...@@ -211,6 +213,7 @@ source_set("unit_tests") { ...@@ -211,6 +213,7 @@ source_set("unit_tests") {
"//ios/chrome/browser", "//ios/chrome/browser",
"//ios/chrome/browser/bookmarks", "//ios/chrome/browser/bookmarks",
"//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/download",
"//ios/chrome/browser/favicon", "//ios/chrome/browser/favicon",
"//ios/chrome/browser/main:test_support", "//ios/chrome/browser/main:test_support",
"//ios/chrome/browser/search_engines", "//ios/chrome/browser/search_engines",
...@@ -224,6 +227,7 @@ source_set("unit_tests") { ...@@ -224,6 +227,7 @@ source_set("unit_tests") {
"//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/alert_coordinator",
"//ios/chrome/browser/ui/browser_container:ui", "//ios/chrome/browser/ui/browser_container:ui",
"//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/download:features",
"//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/ui/toolbar/public",
"//ios/chrome/browser/ui/toolbar/test", "//ios/chrome/browser/ui/toolbar/test",
"//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util",
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#import "ios/chrome/browser/ui/commands/password_breach_commands.h" #import "ios/chrome/browser/ui/commands/password_breach_commands.h"
#import "ios/chrome/browser/ui/commands/text_zoom_commands.h" #import "ios/chrome/browser/ui/commands/text_zoom_commands.h"
#import "ios/chrome/browser/ui/download/ar_quick_look_coordinator.h" #import "ios/chrome/browser/ui/download/ar_quick_look_coordinator.h"
#import "ios/chrome/browser/ui/download/features.h"
#import "ios/chrome/browser/ui/download/pass_kit_coordinator.h" #import "ios/chrome/browser/ui/download/pass_kit_coordinator.h"
#import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h" #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h"
#import "ios/chrome/browser/ui/find_bar/find_bar_coordinator.h" #import "ios/chrome/browser/ui/find_bar/find_bar_coordinator.h"
...@@ -512,11 +513,22 @@ ...@@ -512,11 +513,22 @@
} }
- (void)showDownloadsFolder { - (void)showDownloadsFolder {
// TODO(crbug.com/1046329): Directly open Chrome's folder. if (base::FeatureList::IsEnabled(kOpenDownloadsInFilesApp)) {
NSURL* URL = GetFilesAppDownloadsDirectoryUrl();
if (!URL)
return;
[[UIApplication sharedApplication] openURL:URL
options:@{}
completionHandler:nil];
return;
}
base::FilePath download_dir; base::FilePath download_dir;
if (!GetDownloadsDirectory(&download_dir)) { if (!GetDownloadsDirectory(&download_dir)) {
return; return;
} }
UIDocumentPickerViewController* documentPicker = UIDocumentPickerViewController* documentPicker =
[[UIDocumentPickerViewController alloc] [[UIDocumentPickerViewController alloc]
initWithDocumentTypes:@[ @"public.data" ] initWithDocumentTypes:@[ @"public.data" ]
......
// Copyright 2020 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.
#import "ios/chrome/browser/ui/browser_view/browser_coordinator.h"
#include "base/files/file_util.h"
#include "base/test/scoped_feature_list.h"
#include "ios/chrome/browser/download/download_directory_util.h"
#include "ios/chrome/browser/main/test_browser.h"
#import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/download/features.h"
#include "ios/web/public/test/web_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#include "third_party/ocmock/gtest_support.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// Test fixture for BrowserCoordinator testing.
class BrowserCoordinatorTest : public PlatformTest {
protected:
BrowserCoordinatorTest()
: base_view_controller_([[UIViewController alloc] init]) {}
BrowserCoordinator* GetBrowserCoordinator() {
return [[BrowserCoordinator alloc]
initWithBaseViewController:base_view_controller_
browser:&browser_];
}
web::WebTaskEnvironment task_environment_;
UIViewController* base_view_controller_;
TestBrowser browser_;
};
// Tests if the URL to open the downlads directory from files.app is valid.
TEST_F(BrowserCoordinatorTest, ShowDownloadsFolder) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(kOpenDownloadsInFilesApp);
base::FilePath download_dir;
ASSERT_TRUE(GetDownloadsDirectory(&download_dir));
NSURL* url = GetFilesAppDownloadsDirectoryUrl();
ASSERT_TRUE(url);
UIApplication* shared_application = [UIApplication sharedApplication];
ASSERT_TRUE([shared_application canOpenURL:url]);
id shared_application_mock = OCMPartialMock(shared_application);
OCMExpect([shared_application_mock openURL:url
options:[OCMArg any]
completionHandler:nil]);
BrowserCoordinator* browser_coordinator = GetBrowserCoordinator();
[browser_coordinator start];
CommandDispatcher* dispatcher = browser_.GetCommandDispatcher();
id<BrowserCoordinatorCommands> handler =
HandlerForProtocol(dispatcher, BrowserCoordinatorCommands);
[handler showDownloadsFolder];
[browser_coordinator stop];
EXPECT_OCMOCK_VERIFY(shared_application_mock);
}
...@@ -177,3 +177,12 @@ source_set("eg2_tests") { ...@@ -177,3 +177,12 @@ source_set("eg2_tests") {
libs = [ "UIKit.framework" ] libs = [ "UIKit.framework" ]
} }
source_set("features") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"features.h",
"features.mm",
]
deps = [ "//base" ]
}
// Copyright 2020 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 IOS_CHROME_BROWSER_UI_DOWNLOAD_FEATURES_H_
#define IOS_CHROME_BROWSER_UI_DOWNLOAD_FEATURES_H_
#include "base/feature_list.h"
// Feature to open Downloaded files in Files.app.
extern const base::Feature kOpenDownloadsInFilesApp;
#endif // IOS_CHROME_BROWSER_UI_DOWNLOAD_FEATURES_H_
// Copyright 2020 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.
#import "ios/chrome/browser/ui/download/features.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
const base::Feature kOpenDownloadsInFilesApp{"OpenDownloadsInFilesApp",
base::FEATURE_DISABLED_BY_DEFAULT};
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