blob: d1805f0a48878d8e55fcd363603b18a1f30e831a [file] [log] [blame]
// Copyright 2017 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/fileapi/recent_drive_source.h"
#include <utility>
#include <vector>
#include "base/files/file_path.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/post_task.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/fileapi/recent_file.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/fileapi/file_system_operation.h"
#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/common/fileapi/file_system_types.h"
using content::BrowserThread;
namespace chromeos {
namespace {
void OnGetMetadataOnIOThread(
storage::FileSystemOperation::GetMetadataCallback callback,
base::File::Error result,
const base::File::Info& info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), result, info));
}
void GetMetadataOnIOThread(
scoped_refptr<storage::FileSystemContext> file_system_context,
const storage::FileSystemURL& url,
int fields,
storage::FileSystemOperation::GetMetadataCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
file_system_context->operation_runner()->GetMetadata(
url, fields,
base::BindOnce(&OnGetMetadataOnIOThread, std::move(callback)));
}
} // namespace
const char RecentDriveSource::kLoadHistogramName[] =
"FileBrowser.Recent.LoadDrive";
RecentDriveSource::RecentDriveSource(Profile* profile)
: profile_(profile), weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
RecentDriveSource::~RecentDriveSource() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
void RecentDriveSource::GetRecentFiles(Params params) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!params_.has_value());
DCHECK(files_.empty());
DCHECK_EQ(0, num_inflight_stats_);
DCHECK(build_start_time_.is_null());
params_.emplace(std::move(params));
build_start_time_ = base::TimeTicks::Now();
auto* integration_service =
drive::util::GetIntegrationServiceByProfile(profile_);
if (!integration_service) {
// |integration_service| is nullptr if Drive is disabled.
OnSearchMetadata(drive::FILE_ERROR_FAILED, nullptr);
return;
}
if (integration_service->file_system()) {
integration_service->file_system()->SearchMetadata(
"" /* query */, drive::SEARCH_METADATA_EXCLUDE_DIRECTORIES,
params_.value().max_files(), drive::MetadataSearchOrder::LAST_MODIFIED,
base::BindOnce(&RecentDriveSource::OnSearchMetadata,
weak_ptr_factory_.GetWeakPtr()));
return;
}
auto query_params = drivefs::mojom::QueryParameters::New();
query_params->page_size = params_->max_files();
query_params->query_source =
drivefs::mojom::QueryParameters::QuerySource::kLocalOnly;
query_params->sort_field =
drivefs::mojom::QueryParameters::SortField::kLastModified;
query_params->sort_direction =
drivefs::mojom::QueryParameters::SortDirection::kDescending;
integration_service->GetDriveFsInterface()->StartSearchQuery(
mojo::MakeRequest(&search_query_), std::move(query_params));
search_query_->GetNextPage(base::BindOnce(
&RecentDriveSource::GotSearchResults, weak_ptr_factory_.GetWeakPtr()));
}
void RecentDriveSource::OnSearchMetadata(
drive::FileError error,
std::unique_ptr<drive::MetadataSearchResultVector> results) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(params_.has_value());
DCHECK(files_.empty());
DCHECK_EQ(0, num_inflight_stats_);
DCHECK(!build_start_time_.is_null());
if (error != drive::FILE_ERROR_OK) {
OnComplete();
return;
}
DCHECK(results.get());
std::string extension_id = params_.value().origin().host();
for (const auto& result : *results) {
if (result.is_directory)
continue;
base::FilePath virtual_path =
file_manager::util::ConvertDrivePathToRelativeFileSystemPath(
profile_, extension_id, result.path);
storage::FileSystemURL url =
params_.value().file_system_context()->CreateCrackedFileSystemURL(
params_.value().origin(), storage::kFileSystemTypeExternal,
virtual_path);
++num_inflight_stats_;
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&GetMetadataOnIOThread,
base::WrapRefCounted(params_.value().file_system_context()), url,
storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
base::BindOnce(&RecentDriveSource::OnGetMetadata,
weak_ptr_factory_.GetWeakPtr(), url)));
}
if (num_inflight_stats_ == 0)
OnComplete();
}
void RecentDriveSource::OnGetMetadata(const storage::FileSystemURL& url,
base::File::Error result,
const base::File::Info& info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (result == base::File::FILE_OK)
files_.emplace_back(url, info.last_modified);
--num_inflight_stats_;
if (num_inflight_stats_ == 0)
OnComplete();
}
void RecentDriveSource::OnComplete() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(params_.has_value());
DCHECK_EQ(0, num_inflight_stats_);
DCHECK(!build_start_time_.is_null());
UMA_HISTOGRAM_TIMES(kLoadHistogramName,
base::TimeTicks::Now() - build_start_time_);
build_start_time_ = base::TimeTicks();
Params params = std::move(params_.value());
params_.reset();
std::vector<RecentFile> files = std::move(files_);
files_.clear();
DCHECK(!params_.has_value());
DCHECK(files_.empty());
DCHECK_EQ(0, num_inflight_stats_);
DCHECK(build_start_time_.is_null());
std::move(params.callback()).Run(std::move(files));
}
void RecentDriveSource::GotSearchResults(
drive::FileError error,
base::Optional<std::vector<drivefs::mojom::QueryItemPtr>> results) {
search_query_.reset();
auto* integration_service =
drive::util::GetIntegrationServiceByProfile(profile_);
if (!results || !integration_service) {
OnComplete();
return;
}
files_.reserve(results->size());
for (auto& result : *results) {
if (result->metadata->type ==
drivefs::mojom::FileMetadata::Type::kDirectory) {
continue;
}
base::FilePath path = integration_service->GetMountPointPath().BaseName();
if (!base::FilePath("/").AppendRelativePath(result->path, &path)) {
path = path.Append(result->path);
}
files_.emplace_back(
params_.value().file_system_context()->CreateCrackedFileSystemURL(
params_->origin(), storage::kFileSystemTypeExternal, path),
result->metadata->last_viewed_by_me_time);
}
OnComplete();
}
} // namespace chromeos