Commit aa4f22e9 authored by Satoshi Niwa's avatar Satoshi Niwa Committed by Commit Bot

Update path_util::ConvertToContentUrl to handling multiple URLs at a time.

Background:
* We are migrating callers of ConvertPathToArcUrl (sync) to using ConvertToContentUrl (async) instead.
* exo_parts.cc (a caller of ConvertToContentUrl) needs to handle multiple URLs at a time,
  so it converts single-URL callbacks to multiple-URLs callback using BarrierClosure.
* It turns out arc_file_tasks.cc (a caller of ConvertPathToArcUrl) also needs to handle multiple URLs at a time.
* Moving the BarrierClosure logic from exo_parts to path_util, so we don't need to duplicate the same BarrierClosure logic in arc_file_tasks after migration.

Bug: chromium:811679
Test: unit_test
Change-Id: I461651bac3e5110afdd7b97d39576436cb3a92fd
Reviewed-on: https://chromium-review.googlesource.com/983335Reviewed-by: default avatarDavid Reveman <reveman@chromium.org>
Reviewed-by: default avatarDaichi Hirono <hirono@chromium.org>
Reviewed-by: default avatarShuhei Takahashi <nya@chromium.org>
Commit-Queue: Satoshi Niwa <niwa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547406}
parent d73a1b6b
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/file_manager/path_util.h"
#include "base/barrier_closure.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/sys_info.h" #include "base/sys_info.h"
#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h" #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h"
...@@ -47,9 +48,19 @@ Profile* GetPrimaryProfile() { ...@@ -47,9 +48,19 @@ Profile* GetPrimaryProfile() {
return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user); return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user);
} }
void OnContentUrlResolved(ConvertToContentUrlCallback callback, // Helper function for |ConvertToContentUrls|.
const GURL& url) { void OnSingleContentUrlResolved(const base::RepeatingClosure& barrier_closure,
std::move(callback).Run(url); std::vector<GURL>* out_urls,
size_t index,
const GURL& url) {
(*out_urls)[index] = url;
barrier_closure.Run();
}
// Helper function for |ConvertToContentUrls|.
void OnAllContentUrlsResolved(ConvertToContentUrlsCallback callback,
std::unique_ptr<std::vector<GURL>> urls) {
std::move(callback).Run(*urls);
} }
} // namespace } // namespace
...@@ -143,42 +154,57 @@ bool ConvertPathToArcUrl(const base::FilePath& path, GURL* arc_url_out) { ...@@ -143,42 +154,57 @@ bool ConvertPathToArcUrl(const base::FilePath& path, GURL* arc_url_out) {
return false; return false;
} }
void ConvertToContentUrl(const storage::FileSystemURL& file_system_url, void ConvertToContentUrls(
ConvertToContentUrlCallback callback) { const std::vector<storage::FileSystemURL>& file_system_urls,
ConvertToContentUrlsCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
GURL arc_url; if (file_system_urls.empty()) {
if (file_system_url.mount_type() == storage::kFileSystemTypeExternal && std::move(callback).Run(std::vector<GURL>());
ConvertPathToArcUrl(file_system_url.path(), &arc_url)) {
std::move(callback).Run(arc_url);
return;
}
Profile* primary_profile = GetPrimaryProfile();
if (!primary_profile) {
std::move(callback).Run(GURL());
return; return;
} }
Profile* profile = GetPrimaryProfile();
auto* documents_provider_root_map = auto* documents_provider_root_map =
arc::ArcDocumentsProviderRootMap::GetForBrowserContext(primary_profile); profile ? arc::ArcDocumentsProviderRootMap::GetForBrowserContext(profile)
if (!documents_provider_root_map) { : nullptr;
std::move(callback).Run(GURL());
return; // To keep the original order, prefill |out_urls| with empty URLs and
// specify index when updating it like (*out_urls)[index] = url.
auto out_urls = std::make_unique<std::vector<GURL>>(file_system_urls.size());
auto* out_urls_ptr = out_urls.get();
auto barrier = base::BarrierClosure(
file_system_urls.size(),
base::BindOnce(&OnAllContentUrlsResolved, std::move(callback),
std::move(out_urls)));
auto single_content_url_callback =
base::BindRepeating(&OnSingleContentUrlResolved, barrier, out_urls_ptr);
for (size_t index = 0; index < file_system_urls.size(); ++index) {
const auto& file_system_url = file_system_urls[index];
GURL arc_url;
if (file_system_url.mount_type() == storage::kFileSystemTypeExternal &&
ConvertPathToArcUrl(file_system_url.path(), &arc_url)) {
single_content_url_callback.Run(index, arc_url);
continue;
}
if (!documents_provider_root_map) {
single_content_url_callback.Run(index, GURL());
continue;
}
base::FilePath filepath;
auto* documents_provider_root =
documents_provider_root_map->ParseAndLookup(file_system_url, &filepath);
if (!documents_provider_root) {
single_content_url_callback.Run(index, GURL());
continue;
}
documents_provider_root->ResolveToContentUrl(
filepath, base::BindRepeating(single_content_url_callback, index));
} }
base::FilePath file_path;
auto* documents_provider_root =
documents_provider_root_map->ParseAndLookup(file_system_url, &file_path);
if (!documents_provider_root) {
std::move(callback).Run(GURL());
return;
}
// TODO(niwa): Remove OnContentUrlResolved once ResolveToContentUrl is
// migrated from base::Callback to base::OnceCallback.
documents_provider_root->ResolveToContentUrl(
file_path, base::Bind(&OnContentUrlResolved, base::Passed(&callback)));
} }
} // namespace util } // namespace util
......
...@@ -43,20 +43,22 @@ bool MigratePathFromOldFormat(Profile* profile, ...@@ -43,20 +43,22 @@ bool MigratePathFromOldFormat(Profile* profile,
// The canonical mount point name for "Downloads" folder. // The canonical mount point name for "Downloads" folder.
std::string GetDownloadsMountPointName(Profile* profile); std::string GetDownloadsMountPointName(Profile* profile);
// DEPRECATED. Use |ConvertToContentUrl| instead. // DEPRECATED. Use |ConvertToContentUrls| instead.
// While this function can convert paths under Downloads, /media/removable // While this function can convert paths under Downloads, /media/removable
// and /special/drive, this CANNOT convert paths under ARC media directories // and /special/drive, this CANNOT convert paths under ARC media directories
// (/special/arc-documents-provider). // (/special/arc-documents-provider).
// TODO(crbug.com/811679): Migrate all callers and remove this. // TODO(crbug.com/811679): Migrate all callers and remove this.
bool ConvertPathToArcUrl(const base::FilePath& path, GURL* arc_url_out); bool ConvertPathToArcUrl(const base::FilePath& path, GURL* arc_url_out);
using ConvertToContentUrlCallback = using ConvertToContentUrlsCallback =
base::OnceCallback<void(const GURL& content_url)>; base::OnceCallback<void(const std::vector<GURL>& content_urls)>;
// Asynchronously converts a Chrome OS file system URL to a content:// URL. // Asynchronously converts Chrome OS file system URLs to content:// URLs.
// Returns an empty GURL if |file_system_url| is not convertible. // Always returns a vector of the same size as |file_system_urls|.
void ConvertToContentUrl(const storage::FileSystemURL& file_system_url, // Empty GURLs are filled in the vector if conversion fails.
ConvertToContentUrlCallback callback); void ConvertToContentUrls(
const std::vector<storage::FileSystemURL>& file_system_urls,
ConvertToContentUrlsCallback callback);
} // namespace util } // namespace util
} // namespace file_manager } // namespace file_manager
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/external_mount_points.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using storage::FileSystemURL;
namespace file_manager { namespace file_manager {
namespace util { namespace util {
namespace { namespace {
...@@ -149,9 +151,9 @@ class FileManagerPathUtilConvertUrlTest : public testing::Test { ...@@ -149,9 +151,9 @@ class FileManagerPathUtilConvertUrlTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(FileManagerPathUtilConvertUrlTest); DISALLOW_COPY_AND_ASSIGN(FileManagerPathUtilConvertUrlTest);
}; };
storage::FileSystemURL CreateExternalURL(const base::FilePath& path) { FileSystemURL CreateExternalURL(const base::FilePath& path) {
return storage::FileSystemURL::CreateForTest( return FileSystemURL::CreateForTest(GURL(), storage::kFileSystemTypeExternal,
GURL(), storage::kFileSystemTypeExternal, path); path);
} }
TEST_F(FileManagerPathUtilConvertUrlTest, ConvertPathToArcUrl_Removable) { TEST_F(FileManagerPathUtilConvertUrlTest, ConvertPathToArcUrl_Removable) {
...@@ -201,105 +203,116 @@ TEST_F(FileManagerPathUtilConvertUrlTest, ConvertPathToArcUrl_Special) { ...@@ -201,105 +203,116 @@ TEST_F(FileManagerPathUtilConvertUrlTest, ConvertPathToArcUrl_Special) {
} }
TEST_F(FileManagerPathUtilConvertUrlTest, TEST_F(FileManagerPathUtilConvertUrlTest,
ConvertToContentUrl_InvalidMountType) { ConvertToContentUrls_InvalidMountType) {
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl( ConvertToContentUrls(
storage::FileSystemURL::CreateForTest( std::vector<FileSystemURL>{FileSystemURL::CreateForTest(
GURL(), storage::kFileSystemTypeTest, GURL(), storage::kFileSystemTypeTest,
base::FilePath::FromUTF8Unsafe("/media/removable/a/b/c")), base::FilePath::FromUTF8Unsafe("/media/removable/a/b/c"))},
base::BindOnce( base::BindOnce(
[](base::RunLoop* run_loop, const GURL& url) { [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
run_loop->Quit(); run_loop->Quit();
EXPECT_EQ(GURL(), url); ASSERT_EQ(1U, urls.size());
EXPECT_EQ(GURL(), urls[0]);
}, },
&run_loop)); &run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrl_Removable) { TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrls_Removable) {
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl( ConvertToContentUrls(
CreateExternalURL( std::vector<FileSystemURL>{CreateExternalURL(
base::FilePath::FromUTF8Unsafe("/media/removable/a/b/c")), base::FilePath::FromUTF8Unsafe("/media/removable/a/b/c"))},
base::BindOnce( base::BindOnce(
[](base::RunLoop* run_loop, const GURL& url) { [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
run_loop->Quit(); run_loop->Quit();
ASSERT_EQ(1U, urls.size());
EXPECT_EQ( EXPECT_EQ(
GURL("content://org.chromium.arc.removablemediaprovider/a/b/c"), GURL("content://org.chromium.arc.removablemediaprovider/a/b/c"),
url); urls[0]);
}, },
&run_loop)); &run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, TEST_F(FileManagerPathUtilConvertUrlTest,
ConvertToContentUrl_InvalidRemovable) { ConvertToContentUrls_InvalidRemovable) {
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl(CreateExternalURL(base::FilePath::FromUTF8Unsafe( ConvertToContentUrls(
"/media/removable_foobar")), std::vector<FileSystemURL>{CreateExternalURL(
base::BindOnce( base::FilePath::FromUTF8Unsafe("/media/removable_foobar"))},
[](base::RunLoop* run_loop, const GURL& url) { base::BindOnce(
run_loop->Quit(); [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
EXPECT_EQ(GURL(), url); run_loop->Quit();
}, ASSERT_EQ(1U, urls.size());
&run_loop)); EXPECT_EQ(GURL(), urls[0]);
},
&run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrl_Downloads) { TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrls_Downloads) {
const base::FilePath downloads = GetDownloadsFolderForProfile( const base::FilePath downloads = GetDownloadsFolderForProfile(
chromeos::ProfileHelper::Get()->GetProfileByUserIdHashForTest( chromeos::ProfileHelper::Get()->GetProfileByUserIdHashForTest(
"user@gmail.com-hash")); "user@gmail.com-hash"));
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl( ConvertToContentUrls(
CreateExternalURL(downloads.AppendASCII("a/b/c")), std::vector<FileSystemURL>{
CreateExternalURL(downloads.AppendASCII("a/b/c"))},
base::BindOnce( base::BindOnce(
[](base::RunLoop* run_loop, const GURL& url) { [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
run_loop->Quit(); run_loop->Quit();
ASSERT_EQ(1U, urls.size());
EXPECT_EQ( EXPECT_EQ(
GURL("content://org.chromium.arc.intent_helper.fileprovider/" GURL("content://org.chromium.arc.intent_helper.fileprovider/"
"download/a/b/c"), "download/a/b/c"),
url); urls[0]);
}, },
&run_loop)); &run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, TEST_F(FileManagerPathUtilConvertUrlTest,
ConvertToContentUrl_InvalidDownloads) { ConvertToContentUrls_InvalidDownloads) {
const base::FilePath downloads = GetDownloadsFolderForProfile( const base::FilePath downloads = GetDownloadsFolderForProfile(
chromeos::ProfileHelper::Get()->GetProfileByUserIdHashForTest( chromeos::ProfileHelper::Get()->GetProfileByUserIdHashForTest(
"user2@gmail.com-hash")); "user2@gmail.com-hash"));
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl(CreateExternalURL(downloads.AppendASCII("a/b/c")), ConvertToContentUrls(
base::BindOnce( std::vector<FileSystemURL>{
[](base::RunLoop* run_loop, const GURL& url) { CreateExternalURL(downloads.AppendASCII("a/b/c"))},
run_loop->Quit(); base::BindOnce(
EXPECT_EQ(GURL(), url); [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
}, run_loop->Quit();
&run_loop)); ASSERT_EQ(1U, urls.size());
EXPECT_EQ(GURL(), urls[0]);
},
&run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrl_Special) { TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrls_Special) {
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl( ConvertToContentUrls(
CreateExternalURL(drive_mount_point_.AppendASCII("a/b/c")), std::vector<FileSystemURL>{
CreateExternalURL(drive_mount_point_.AppendASCII("a/b/c"))},
base::BindOnce( base::BindOnce(
[](base::RunLoop* run_loop, const GURL& url) { [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
run_loop->Quit(); run_loop->Quit();
ASSERT_EQ(1U, urls.size());
EXPECT_EQ( EXPECT_EQ(
GURL( GURL(
"content://org.chromium.arc.chromecontentprovider/" "content://org.chromium.arc.chromecontentprovider/"
"externalfile%3Adrive-user%2540gmail.com-hash%2Fa%2Fb%2Fc"), "externalfile%3Adrive-user%2540gmail.com-hash%2Fa%2Fb%2Fc"),
url); urls[0]);
}, },
&run_loop)); &run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, TEST_F(FileManagerPathUtilConvertUrlTest,
ConvertToContentUrl_ArcDocumentsProvider) { ConvertToContentUrls_ArcDocumentsProvider) {
// Add images_root/Download/photo.jpg to the fake file system. // Add images_root/Download/photo.jpg to the fake file system.
const char kAuthority[] = "com.android.providers.media.documents"; const char kAuthority[] = "com.android.providers.media.documents";
fake_file_system_.AddDocument(arc::FakeFileSystemInstance::Document( fake_file_system_.AddDocument(arc::FakeFileSystemInstance::Document(
...@@ -312,39 +325,69 @@ TEST_F(FileManagerPathUtilConvertUrlTest, ...@@ -312,39 +325,69 @@ TEST_F(FileManagerPathUtilConvertUrlTest,
kAuthority, "photo-id", "dir-id", "photo.jpg", "image/jpeg", 3, 33)); kAuthority, "photo-id", "dir-id", "photo.jpg", "image/jpeg", 3, 33));
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl( ConvertToContentUrls(
storage::FileSystemURL::CreateForTest( std::vector<FileSystemURL>{FileSystemURL::CreateForTest(
GURL(), storage::kFileSystemTypeArcDocumentsProvider, GURL(), storage::kFileSystemTypeArcDocumentsProvider,
base::FilePath::FromUTF8Unsafe( base::FilePath::FromUTF8Unsafe(
"/special/arc-documents-provider/" "/special/arc-documents-provider/"
"com.android.providers.media.documents/" "com.android.providers.media.documents/"
"images_root/Download/photo.jpg")), "images_root/Download/photo.jpg"))},
base::BindOnce( base::BindOnce(
[](base::RunLoop* run_loop, const GURL& url) { [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
run_loop->Quit(); run_loop->Quit();
ASSERT_EQ(1U, urls.size());
EXPECT_EQ(GURL("content://com.android.providers.media.documents/" EXPECT_EQ(GURL("content://com.android.providers.media.documents/"
"document/photo-id"), "document/photo-id"),
url); urls[0]);
}, },
&run_loop)); &run_loop));
run_loop.Run(); run_loop.Run();
} }
TEST_F(FileManagerPathUtilConvertUrlTest, TEST_F(FileManagerPathUtilConvertUrlTest,
ConvertToContentUrl_ArcDocumentsProviderFileNotFound) { ConvertToContentUrls_ArcDocumentsProviderFileNotFound) {
base::RunLoop run_loop; base::RunLoop run_loop;
ConvertToContentUrl(storage::FileSystemURL::CreateForTest( ConvertToContentUrls(
GURL(), storage::kFileSystemTypeArcDocumentsProvider, std::vector<FileSystemURL>{FileSystemURL::CreateForTest(
base::FilePath::FromUTF8Unsafe( GURL(), storage::kFileSystemTypeArcDocumentsProvider,
"/special/arc-documents-provider/" base::FilePath::FromUTF8Unsafe(
"com.android.providers.media.documents/" "/special/arc-documents-provider/"
"images_root/Download/photo.jpg")), "com.android.providers.media.documents/"
base::BindOnce( "images_root/Download/photo.jpg"))},
[](base::RunLoop* run_loop, const GURL& url) { base::BindOnce(
run_loop->Quit(); [](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
EXPECT_EQ(GURL(""), url); run_loop->Quit();
}, ASSERT_EQ(1U, urls.size());
&run_loop)); EXPECT_EQ(GURL(""), urls[0]);
},
&run_loop));
run_loop.Run();
}
TEST_F(FileManagerPathUtilConvertUrlTest, ConvertToContentUrls_MultipeUrls) {
base::RunLoop run_loop;
ConvertToContentUrls(
std::vector<FileSystemURL>{
CreateExternalURL(base::FilePath::FromUTF8Unsafe("/invalid")),
CreateExternalURL(
base::FilePath::FromUTF8Unsafe("/media/removable/a/b/c")),
CreateExternalURL(drive_mount_point_.AppendASCII("a/b/c")),
},
base::BindOnce(
[](base::RunLoop* run_loop, const std::vector<GURL>& urls) {
run_loop->Quit();
ASSERT_EQ(3U, urls.size());
EXPECT_EQ(GURL(), urls[0]); // Invalid URL.
EXPECT_EQ(
GURL("content://org.chromium.arc.removablemediaprovider/a/b/c"),
urls[1]);
EXPECT_EQ(
GURL(
"content://org.chromium.arc.chromecontentprovider/"
"externalfile%3Adrive-user%2540gmail.com-hash%2Fa%2Fb%2Fc"),
urls[2]);
},
&run_loop));
run_loop.Run(); run_loop.Run();
} }
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <glib.h> #include <glib.h>
#endif #endif
#include "base/barrier_closure.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
...@@ -73,20 +72,6 @@ void GetFileSystemUrlsFromPickle( ...@@ -73,20 +72,6 @@ void GetFileSystemUrlsFromPickle(
} }
} }
// Helper function for |GetUrlsFromPickle|.
void OnSingleUrlResolved(const base::RepeatingClosure& barrier_closure,
std::vector<GURL>* out_urls,
const GURL& url) {
out_urls->push_back(url);
barrier_closure.Run();
}
// Helper function for |GetUrlsFromPickle|.
void OnAllUrlsResolved(exo::FileHelper::UrlsFromPickleCallback callback,
std::unique_ptr<std::vector<GURL>> urls) {
std::move(callback).Run(*urls);
}
class ChromeFileHelper : public exo::FileHelper { class ChromeFileHelper : public exo::FileHelper {
public: public:
ChromeFileHelper() = default; ChromeFileHelper() = default;
...@@ -118,19 +103,8 @@ class ChromeFileHelper : public exo::FileHelper { ...@@ -118,19 +103,8 @@ class ChromeFileHelper : public exo::FileHelper {
std::move(callback).Run(std::vector<GURL>()); std::move(callback).Run(std::vector<GURL>());
return; return;
} }
file_manager::util::ConvertToContentUrls(file_system_urls,
auto out_urls = std::make_unique<std::vector<GURL>>(); std::move(callback));
auto* out_urls_ptr = out_urls.get();
auto barrier = base::BarrierClosure(
file_system_urls.size(),
base::BindOnce(&OnAllUrlsResolved, std::move(callback),
std::move(out_urls)));
auto convert_url_callback =
base::BindRepeating(&OnSingleUrlResolved, barrier, out_urls_ptr);
for (const auto& file_system_url : file_system_urls) {
file_manager::util::ConvertToContentUrl(file_system_url,
convert_url_callback);
}
} }
}; };
......
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