Commit 14d132c6 authored by Austin Tankiang's avatar Austin Tankiang Committed by Commit Bot

Remove legacy drive sync client loaders

Bug: 1003238
Change-Id: I88ec141acd23900f7be259a34d27a8bc118e43ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1896492
Commit-Queue: Austin Tankiang <austinct@chromium.org>
Reviewed-by: default avatarSergei Datsenko <dats@chromium.org>
Reviewed-by: default avatarStuart Langley <slangley@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713759}
parent 415dc078
......@@ -2935,11 +2935,8 @@ source_set("unit_tests") {
"../ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc",
"../ui/webui/settings/chromeos/internet_handler_unittest.cc",
"../ui/webui/settings/chromeos/multidevice_handler_unittest.cc",
"//components/drive/about_resource_loader_unittest.cc",
"//components/drive/change_list_loader_unittest.cc",
"//components/drive/change_list_processor_unittest.cc",
"//components/drive/chromeos/file_cache_unittest.cc",
"//components/drive/directory_loader_unittest.cc",
"//components/drive/drive_file_util_unittest.cc",
"//components/drive/drive_notification_manager_unittest.cc",
"//components/drive/drive_operation_queue_unittest.cc",
......@@ -2954,9 +2951,6 @@ source_set("unit_tests") {
"//components/drive/resource_metadata_storage_unittest.cc",
"//components/drive/resource_metadata_unittest.cc",
"//components/drive/search_metadata_unittest.cc",
"//components/drive/start_page_token_loader_unittest.cc",
"//components/drive/team_drive_change_list_loader_unittest.cc",
"//components/drive/team_drive_list_loader_unittest.cc",
]
public_deps = [
......
......@@ -97,20 +97,8 @@ static_library("test_support") {
if (is_chromeos) {
source_set("drive_chromeos") {
sources = [
"chromeos/about_resource_loader.cc",
"chromeos/about_resource_loader.h",
"chromeos/about_resource_root_folder_id_loader.cc",
"chromeos/about_resource_root_folder_id_loader.h",
"chromeos/change_list_loader.cc",
"chromeos/change_list_loader.h",
"chromeos/change_list_loader_observer.h",
"chromeos/change_list_processor.cc",
"chromeos/change_list_processor.h",
"chromeos/default_corpus_change_list_loader.cc",
"chromeos/default_corpus_change_list_loader.h",
"chromeos/directory_loader.cc",
"chromeos/directory_loader.h",
"chromeos/drive_change_list_loader.h",
"chromeos/drive_file_util.cc",
"chromeos/drive_file_util.h",
"chromeos/drive_operation_queue.h",
......@@ -119,23 +107,14 @@ if (is_chromeos) {
"chromeos/file_system_interface.cc",
"chromeos/file_system_interface.h",
"chromeos/file_system_observer.h",
"chromeos/loader_controller.cc",
"chromeos/loader_controller.h",
"chromeos/remove_stale_cache_files.cc",
"chromeos/remove_stale_cache_files.h",
"chromeos/resource_metadata.cc",
"chromeos/resource_metadata.h",
"chromeos/root_folder_id_loader.h",
"chromeos/search_metadata.cc",
"chromeos/search_metadata.h",
"chromeos/start_page_token_loader.cc",
"chromeos/start_page_token_loader.h",
"chromeos/team_drive.cc",
"chromeos/team_drive.h",
"chromeos/team_drive_change_list_loader.cc",
"chromeos/team_drive_change_list_loader.h",
"chromeos/team_drive_list_loader.cc",
"chromeos/team_drive_list_loader.h",
"chromeos/team_drive_list_observer.h",
]
deps = [
......
......@@ -22,10 +22,7 @@ specific_include_rules = {
# The following test dependencies should be removed to fully componentize this
# directory. crbug.com/498951
r"(about_resource_loader_unittest\.cc"
r"|change_list_loader_unittest\.cc"
r"|change_list_processor_unittest\.cc"
r"|directory_loader_unittest\.cc"
r"(change_list_processor_unittest\.cc"
r"|drive_file_util_unittest\.cc"
r"|file_cache_unittest\.cc"
r"|file_system_core_util_unittest\.cc"
......@@ -35,9 +32,6 @@ specific_include_rules = {
r"|resource_metadata_storage_unittest\.cc"
r"|resource_metadata_unittest\.cc"
r"|search_metadata_unittest\.cc"
r"|start_page_token_loader_unittest\.cc"
r"|team_drive_change_list_loader_unittest\.cc"
r"|team_drive_list_loader_unittest\.cc"
r")": [
"+content/public/test/browser_task_environment.h",
],
......
// Copyright 2018 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 "components/drive/chromeos/about_resource_loader.h"
#include <memory>
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/drive/chromeos/drive_test_util.h"
#include "components/drive/chromeos/file_cache.h"
#include "components/drive/chromeos/resource_metadata.h"
#include "components/drive/event_logger.h"
#include "components/drive/job_scheduler.h"
#include "components/drive/resource_metadata_storage.h"
#include "components/drive/service/fake_drive_service.h"
#include "components/drive/service/test_util.h"
#include "components/prefs/testing_pref_service.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace drive {
namespace internal {
namespace {
struct DestroyHelper {
template <typename T>
void operator()(T* object) const {
if (object) {
object->Destroy();
}
}
};
} // namespace
class AboutResourceLoaderTest : public testing::Test {
protected:
void SetUp() override {
task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::TestMockTimeTaskRunner::Type::kBoundToThread);
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
test_util::RegisterDrivePrefs(pref_service_->registry());
logger_ = std::make_unique<EventLogger>();
drive_service_ = std::make_unique<FakeDriveService>();
ASSERT_TRUE(test_util::SetUpTestEntries(drive_service_.get()));
network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
network::mojom::ConnectionType::CONNECTION_WIFI);
scheduler_ = std::make_unique<JobScheduler>(
pref_service_.get(), logger_.get(), drive_service_.get(),
network::TestNetworkConnectionTracker::GetInstance(),
task_runner_.get(), mojo::NullRemote());
metadata_storage_.reset(
new ResourceMetadataStorage(temp_dir_.GetPath(), task_runner_.get()));
ASSERT_TRUE(metadata_storage_->Initialize());
cache_.reset(new FileCache(metadata_storage_.get(), temp_dir_.GetPath(),
task_runner_.get(),
nullptr /* free_disk_space_getter */));
ASSERT_TRUE(cache_->Initialize());
metadata_.reset(new ResourceMetadata(metadata_storage_.get(), cache_.get(),
task_runner_.get()));
ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
about_resource_loader_ = std::make_unique<AboutResourceLoader>(
scheduler_.get(), task_runner_->GetMockTickClock());
}
void TearDown() override {
// We need to manually reset the objects that implement the Destroy idiom,
// that deletes the object on the |task_runner_|. This is simpler than
// introducing custom deleters that capture the |task_runner_| and
// invoke RunUntilIdle().
metadata_.reset();
cache_.reset();
metadata_storage_.reset();
task_runner_->RunUntilIdle();
}
// Adds a new file to the root directory of the service.
std::unique_ptr<google_apis::FileResource> AddNewFile(
const std::string& title) {
google_apis::DriveApiErrorCode error = google_apis::DRIVE_FILE_ERROR;
std::unique_ptr<google_apis::FileResource> entry;
drive_service_->AddNewFile(
"text/plain", "content text", drive_service_->GetRootResourceId(),
title,
false, // shared_with_me
google_apis::test_util::CreateCopyResultCallback(&error, &entry));
task_runner_->RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_CREATED, error);
return entry;
}
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<EventLogger> logger_;
std::unique_ptr<FakeDriveService> drive_service_;
std::unique_ptr<JobScheduler> scheduler_;
std::unique_ptr<ResourceMetadataStorage, DestroyHelper> metadata_storage_;
std::unique_ptr<FileCache, DestroyHelper> cache_;
std::unique_ptr<ResourceMetadata, DestroyHelper> metadata_;
std::unique_ptr<AboutResourceLoader> about_resource_loader_;
};
TEST_F(AboutResourceLoaderTest, AboutResourceLoader) {
google_apis::DriveApiErrorCode error[6] = {};
std::unique_ptr<google_apis::AboutResource> about[6];
// No resource is cached at the beginning.
ASSERT_FALSE(about_resource_loader_->cached_about_resource());
// Since no resource is cached, this "Get" should trigger the update.
about_resource_loader_->GetAboutResource(
google_apis::test_util::CreateCopyResultCallback(error + 0, about + 0));
// Since there is one in-flight update, the next "Get" just wait for it.
about_resource_loader_->GetAboutResource(
google_apis::test_util::CreateCopyResultCallback(error + 1, about + 1));
task_runner_->RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[0]);
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[1]);
const int64_t first_changestamp = about[0]->largest_change_id();
EXPECT_EQ(first_changestamp, about[1]->largest_change_id());
ASSERT_TRUE(about_resource_loader_->cached_about_resource());
EXPECT_EQ(
first_changestamp,
about_resource_loader_->cached_about_resource()->largest_change_id());
// Increment changestamp by 1.
AddNewFile("temp");
// Explicitly calling UpdateAboutResource will start another API call.
about_resource_loader_->UpdateAboutResource(
google_apis::test_util::CreateCopyResultCallback(error + 2, about + 2));
// It again waits for the in-flight UpdateAboutResoure call, even though this
// time there is a cached result.
about_resource_loader_->GetAboutResource(
google_apis::test_util::CreateCopyResultCallback(error + 3, about + 3));
task_runner_->RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[2]);
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[3]);
EXPECT_EQ(first_changestamp + 1, about[2]->largest_change_id());
EXPECT_EQ(first_changestamp + 1, about[3]->largest_change_id());
EXPECT_EQ(
first_changestamp + 1,
about_resource_loader_->cached_about_resource()->largest_change_id());
// Increment changestamp by 1.
AddNewFile("temp2");
// Now no UpdateAboutResource task is running. Returns the cached result.
about_resource_loader_->GetAboutResource(
google_apis::test_util::CreateCopyResultCallback(error + 4, about + 4));
// Explicitly calling UpdateAboutResource will start another API call.
about_resource_loader_->UpdateAboutResource(
google_apis::test_util::CreateCopyResultCallback(error + 5, about + 5));
task_runner_->RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error[4]);
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[5]);
EXPECT_EQ(first_changestamp + 1, about[4]->largest_change_id());
EXPECT_EQ(first_changestamp + 2, about[5]->largest_change_id());
EXPECT_EQ(
first_changestamp + 2,
about_resource_loader_->cached_about_resource()->largest_change_id());
EXPECT_EQ(3, drive_service_->about_resource_load_count());
}
TEST_F(AboutResourceLoaderTest, EvictCache) {
google_apis::DriveApiErrorCode error;
std::unique_ptr<google_apis::AboutResource> about;
// No resource is cached at the beginning.
ASSERT_FALSE(about_resource_loader_->cached_about_resource());
// Since no resource is cached, this "Get" should trigger the update.
about_resource_loader_->GetAboutResource(
google_apis::test_util::CreateCopyResultCallback(&error, &about));
task_runner_->RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
// Should have a cached resource.
ASSERT_TRUE(about_resource_loader_->cached_about_resource());
// Advance the timer should evict the cache.
task_runner_->FastForwardUntilNoTasksRemain();
// Cache should be evicted.
ASSERT_FALSE(about_resource_loader_->cached_about_resource());
}
} // namespace internal
} // namespace drive
This diff is collapsed.
// Copyright 2018 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 "components/drive/chromeos/about_resource_loader.h"
#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/drive/job_scheduler.h"
namespace drive {
namespace internal {
namespace {
// The time period that we will cache the result of UpdateAboutResource.
constexpr base::TimeDelta kCacheEvictionTimeout =
base::TimeDelta::FromMinutes(1);
} // namespace
AboutResourceLoader::AboutResourceLoader(JobScheduler* scheduler,
const base::TickClock* clock)
: scheduler_(scheduler), current_update_task_id_(-1) {
cache_eviction_timer_ = std::make_unique<base::RetainingOneShotTimer>(
FROM_HERE, kCacheEvictionTimeout,
base::BindRepeating(&AboutResourceLoader::EvictCachedAboutResource,
base::Unretained(this)),
clock);
}
AboutResourceLoader::~AboutResourceLoader() = default;
void AboutResourceLoader::GetAboutResource(
const google_apis::AboutResourceCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(callback);
// If the latest UpdateAboutResource task is still running. Wait for it,
if (pending_callbacks_.count(current_update_task_id_)) {
pending_callbacks_[current_update_task_id_].emplace_back(callback);
return;
}
if (cached_about_resource_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(callback, google_apis::HTTP_NO_CONTENT,
std::make_unique<google_apis::AboutResource>(
*cached_about_resource_)));
} else {
UpdateAboutResource(callback);
}
}
void AboutResourceLoader::UpdateAboutResource(
const google_apis::AboutResourceCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(callback);
++current_update_task_id_;
pending_callbacks_[current_update_task_id_].emplace_back(callback);
scheduler_->GetAboutResource(base::BindRepeating(
&AboutResourceLoader::UpdateAboutResourceAfterGetAbout,
weak_ptr_factory_.GetWeakPtr(), current_update_task_id_));
}
void AboutResourceLoader::UpdateAboutResourceAfterGetAbout(
int task_id,
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::AboutResource> about_resource) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
FileError error = GDataToFileError(status);
const std::vector<google_apis::AboutResourceCallback> callbacks =
pending_callbacks_[task_id];
pending_callbacks_.erase(task_id);
if (error != FILE_ERROR_OK) {
for (auto& callback : callbacks)
callback.Run(status, nullptr);
return;
}
// Updates the cache when the resource is successfully obtained.
if (cached_about_resource_ && cached_about_resource_->largest_change_id() >
about_resource->largest_change_id()) {
LOG(WARNING) << "Local cached about resource is fresher than server, "
<< "local = " << cached_about_resource_->largest_change_id()
<< ", server = " << about_resource->largest_change_id();
}
cached_about_resource_ =
std::make_unique<google_apis::AboutResource>(*about_resource);
cache_eviction_timer_->Reset();
for (auto& callback : callbacks) {
callback.Run(status,
std::make_unique<google_apis::AboutResource>(*about_resource));
}
}
void AboutResourceLoader::EvictCachedAboutResource() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
cached_about_resource_.reset();
}
} // namespace internal
} // namespace drive
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_ABOUT_RESOURCE_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_ABOUT_RESOURCE_LOADER_H_
#include <map>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/default_tick_clock.h"
#include "base/timer/timer.h"
#include "google_apis/drive/drive_common_callbacks.h"
namespace drive {
class JobScheduler;
namespace internal {
// This class is responsible to load AboutResource from the server and cache it.
class AboutResourceLoader {
public:
// |clock| can be injected for testing.
explicit AboutResourceLoader(
JobScheduler* scheduler,
const base::TickClock* clock = base::DefaultTickClock::GetInstance());
~AboutResourceLoader();
// Returns the cached about resource.
// NULL is returned if the cache is not available.
const google_apis::AboutResource* cached_about_resource() const {
return cached_about_resource_.get();
}
// Gets the 'latest' about resource and asynchronously runs |callback|. I.e.,
// 1) If the last call to UpdateAboutResource call is in-flight, wait for it.
// 2) Otherwise, if the resource is cached, just returns the cached value.
// 3) If neither of the above hold, queries the API server by calling
// |UpdateAboutResource|.
void GetAboutResource(const google_apis::AboutResourceCallback& callback);
// Gets the about resource from the server, and caches it if successful. This
// function calls JobScheduler::GetAboutResource internally. The cache will be
// used in |GetAboutResource|.
void UpdateAboutResource(const google_apis::AboutResourceCallback& callback);
private:
// Part of UpdateAboutResource().
// This function should be called when the latest about resource is being
// fetched from the server. The retrieved about resource is cloned, and one is
// cached and the other is passed to callbacks associated with |task_id|.
void UpdateAboutResourceAfterGetAbout(
int task_id,
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::AboutResource> about_resource);
void EvictCachedAboutResource();
JobScheduler* scheduler_;
std::unique_ptr<google_apis::AboutResource> cached_about_resource_;
// Identifier to denote the latest UpdateAboutResource call.
int current_update_task_id_;
// Mapping from each UpdateAboutResource task ID to the corresponding
// callbacks. Note that there will be multiple callbacks for a single task
// when GetAboutResource is called before the task completes.
std::map<int, std::vector<google_apis::AboutResourceCallback>>
pending_callbacks_;
std::unique_ptr<base::RetainingOneShotTimer> cache_eviction_timer_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<AboutResourceLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AboutResourceLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_ABOUT_RESOURCE_LOADER_H_
// Copyright 2018 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 "components/drive/chromeos/about_resource_root_folder_id_loader.h"
#include <memory>
#include "base/bind.h"
#include "components/drive/chromeos/about_resource_loader.h"
#include "google_apis/drive/drive_api_parser.h"
namespace drive {
namespace internal {
AboutResourceRootFolderIdLoader::AboutResourceRootFolderIdLoader(
AboutResourceLoader* about_resource_loader)
: about_resource_loader_(about_resource_loader) {}
AboutResourceRootFolderIdLoader::~AboutResourceRootFolderIdLoader() = default;
void AboutResourceRootFolderIdLoader::GetRootFolderId(
const RootFolderIdCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// If we have already read the root folder id, then we can simply return it.
if (!root_folder_id_.empty()) {
callback.Run(FILE_ERROR_OK, root_folder_id_);
return;
}
about_resource_loader_->GetAboutResource(
base::BindRepeating(&AboutResourceRootFolderIdLoader::OnGetAboutResource,
weak_ptr_factory_.GetWeakPtr(), callback));
}
void AboutResourceRootFolderIdLoader::OnGetAboutResource(
const RootFolderIdCallback& callback,
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::AboutResource> about_resource) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
FileError error = GDataToFileError(status);
if (error != FILE_ERROR_OK) {
callback.Run(error, base::nullopt);
return;
}
DCHECK(about_resource);
// The root folder id is immutable so we can save it for subsequent calls.
root_folder_id_ = about_resource->root_folder_id();
callback.Run(error, root_folder_id_);
}
} // namespace internal
} // namespace drive
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_ABOUT_RESOURCE_ROOT_FOLDER_ID_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_ABOUT_RESOURCE_ROOT_FOLDER_ID_LOADER_H_
#include <memory>
#include <string>
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "components/drive/chromeos/root_folder_id_loader.h"
#include "google_apis/drive/drive_api_error_codes.h"
namespace google_apis {
class AboutResource;
} // namespace google_apis
namespace drive {
namespace internal {
class AboutResourceLoader;
// Retrieves the root folder id from the about resource loader. This is used
// to get the root folder ID for the users default corpus. As the value is
// constant we just use GetAboutResource which will usually retrieve a
// cached value.
class AboutResourceRootFolderIdLoader : public RootFolderIdLoader {
public:
explicit AboutResourceRootFolderIdLoader(
AboutResourceLoader* about_resource_loader);
~AboutResourceRootFolderIdLoader() override;
void GetRootFolderId(const RootFolderIdCallback& callback) override;
private:
void OnGetAboutResource(
const RootFolderIdCallback& callback,
google_apis::DriveApiErrorCode error,
std::unique_ptr<google_apis::AboutResource> about_resource);
AboutResourceLoader* about_resource_loader_; // Not owned.
std::string root_folder_id_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<AboutResourceRootFolderIdLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AboutResourceRootFolderIdLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_ABOUT_RESOURCE_ROOT_FOLDER_ID_LOADER_H_
This diff is collapsed.
// Copyright (c) 2012 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 COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "components/drive/file_errors.h"
#include "google_apis/drive/drive_api_error_codes.h"
#include "google_apis/drive/drive_common_callbacks.h"
namespace base {
class AtomicFlag;
class SequencedTaskRunner;
class Time;
} // namespace base
namespace google_apis {
class StartPageToken;
} // namespace google_apis
namespace drive {
class EventLogger;
class JobScheduler;
namespace internal {
class RootFolderIdLoader;
class ChangeList;
class ChangeListLoaderObserver;
class ChangeListProcessor;
class LoaderController;
class ResourceMetadata;
class StartPageTokenLoader;
// ChangeListLoader is used to load the change list, the full resource list,
// and directory contents, from Google Drive API. The class also updates the
// resource metadata with the change list loaded from the server.
//
// Note that the difference between "resource list" and "change list" is
// subtle hence the two words are often used interchangeably. To be precise,
// "resource list" refers to metadata from the server when fetching the full
// resource metadata, or fetching directory contents, whereas "change list"
// refers to metadata from the server when fetching changes (delta).
class ChangeListLoader {
public:
// Resource feed fetcher from the server.
class FeedFetcher;
ChangeListLoader(EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
RootFolderIdLoader* root_folder_id_loader,
StartPageTokenLoader* start_page_token_loader,
LoaderController* apply_task_controller,
const std::string& team_drive_id,
const base::FilePath& root_entry_path);
~ChangeListLoader();
// Indicates whether there is a request for full resource list or change
// list fetching is in flight (i.e. directory contents fetching does not
// count).
bool IsRefreshing() const;
// Adds and removes the observer.
void AddObserver(ChangeListLoaderObserver* observer);
void RemoveObserver(ChangeListLoaderObserver* observer);
// Checks for updates on the server. Does nothing if the change list is now
// being loaded or refreshed. |callback| must not be null.
// Note: |callback| will be called if the check for updates actually
// runs, i.e. it may NOT be called if the checking is ignored.
void CheckForUpdates(const FileOperationCallback& callback);
// Starts the change list loading if needed. If the locally stored metadata is
// available, runs |callback| immediately and starts checking server for
// updates in background. If the locally stored metadata is not available,
// starts loading from the server, and runs |callback| to tell the result to
// the caller when it is finished.
//
// |callback| must not be null.
void LoadIfNeeded(const FileOperationCallback& callback);
private:
// Starts the resource metadata loading and calls |callback| when it's done.
void Load(const FileOperationCallback& callback);
void LoadAfterGetLocalStartPageToken(
bool is_initial_load,
const std::string* local_start_page_token,
FileError error);
void LoadAfterGetRootFolderId(const std::string& local_start_page_token,
FileError error,
base::Optional<std::string> root_folder_id);
void LoadAfterGetStartPageToken(
const std::string& local_start_page_token,
const std::string& root_folder_id,
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::StartPageToken> start_page_token);
// Part of Load().
// This function should be called when the change list load is complete.
// Flushes the callbacks for change list loading and all directory loading.
void OnChangeListLoadComplete(FileError error);
// Called when loading the start page token is completed.
void OnStartPageTokenLoaderUpdated(
google_apis::DriveApiErrorCode error,
std::unique_ptr<google_apis::StartPageToken> start_page_token);
// ================= Implementation for change list loading =================
// Part of LoadFromServerIfNeeded().
// Starts loading the change list since |local_start_page_token|, or the full
// resource list if |local_start_page_token| is empty. If there's no changes
// since then, and there are no new team drives changes to apply from
// team_drives_change_lists, finishes early.
// TODO(sashab): Currently, team_drives_change_lists always contains all of
// the team drives. Update this so team_drives_change_lists is only filled
// when the TD flag is newly turned on or local data cleared. crbug.com/829154
void LoadChangeListFromServer(const std::string& remote_start_page_token,
const std::string& local_start_page_token,
const std::string& root_resource_id);
// Part of LoadChangeListFromServer().
// Called when the entire change list is loaded.
void LoadChangeListFromServerAfterLoadChangeList(
const std::string& start_page_token,
const std::string& root_resource_id,
bool is_delta_update,
FileError error,
std::vector<std::unique_ptr<ChangeList>> change_lists);
// Part of LoadChangeListFromServer().
// Called when the resource metadata is updated.
void LoadChangeListFromServerAfterUpdate(
ChangeListProcessor* change_list_processor,
bool should_notify_changed_directories,
base::Time start_time,
FileError error);
EventLogger* logger_; // Not owned.
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
std::unique_ptr<base::AtomicFlag> in_shutdown_;
ResourceMetadata* resource_metadata_; // Not owned.
JobScheduler* scheduler_; // Not owned.
RootFolderIdLoader* root_folder_id_loader_; // Not owned.
StartPageTokenLoader* start_page_token_loader_; // Not owned.
LoaderController* loader_controller_; // Not owned.
base::ObserverList<ChangeListLoaderObserver>::Unchecked observers_;
std::vector<FileOperationCallback> pending_load_callback_;
FileOperationCallback pending_update_check_callback_;
// Running feed fetcher.
// TODO(slangley): Do not make this stateful by changing the feed_fetcher
// to be base::Owned by the callback.
std::unique_ptr<FeedFetcher> change_feed_fetcher_;
// True if the full resource list is loaded (i.e. the resource metadata is
// stored locally).
bool loaded_;
// The team drive id for the changes being loaded by this change list loader.
const std::string team_drive_id_;
// The formatted team drive id message used for logging.
const std::string team_drive_msg_;
// The root entry path for changes being loaded by this change list loader.
// Can be a team drive root entry or for the users default corpus will be the
// drive root entry.
const base::FilePath root_entry_path_;
THREAD_CHECKER(thread_checker_);
// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<ChangeListLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ChangeListLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_H_
// Copyright (c) 2012 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 COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_OBSERVER_H_
#define COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_OBSERVER_H_
namespace base {
class FilePath;
} // namespace base
namespace drive {
class FileChange;
namespace internal {
// Interface for classes that need to observe events from ChangeListLoader.
// All events are notified on UI thread.
class ChangeListLoaderObserver {
public:
// Triggered when the content of a directory is reloaded. The content may
// changed. |directory_path| is a virtual directory path representing the
// reloaded directory.
virtual void OnDirectoryReloaded(const base::FilePath& directory_path) {}
// Triggered when content(s) in drive has been changed.
virtual void OnFileChanged(const FileChange& changed_files) {}
// Triggered when the users accessible team drives has changed.
virtual void OnTeamDrivesChanged(const FileChange& changed_team_drives) {}
// Triggered when loading from the server is complete.
virtual void OnLoadFromServerComplete() {}
// Triggered when loading is complete for the first time, either from the
// the server or the cache. To be precise, for the latter case, we do not
// load anything from the cache. We just check that the resource metadata
// is stored locally thus can be used.
virtual void OnInitialLoadComplete() {}
protected:
virtual ~ChangeListLoaderObserver() = default;
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_OBSERVER_H_
// Copyright 2018 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 "components/drive/chromeos/default_corpus_change_list_loader.h"
#include <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/time/clock.h"
#include "components/drive/chromeos/about_resource_root_folder_id_loader.h"
#include "components/drive/file_system_core_util.h"
namespace drive {
namespace internal {
DefaultCorpusChangeListLoader::DefaultCorpusChangeListLoader(
EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
AboutResourceLoader* about_resource_loader,
LoaderController* apply_task_controller,
const base::Clock* clock)
: logger_(logger),
blocking_task_runner_(blocking_task_runner),
resource_metadata_(resource_metadata),
scheduler_(scheduler),
loader_controller_(apply_task_controller) {
DCHECK(clock);
root_folder_id_loader_ =
std::make_unique<AboutResourceRootFolderIdLoader>(about_resource_loader);
start_page_token_loader_ = std::make_unique<StartPageTokenLoader>(
util::kTeamDriveIdDefaultCorpus, scheduler_);
change_list_loader_ = std::make_unique<ChangeListLoader>(
logger_, blocking_task_runner_.get(), resource_metadata_, scheduler_,
root_folder_id_loader_.get(), start_page_token_loader_.get(),
loader_controller_, util::kTeamDriveIdDefaultCorpus,
util::GetDriveMyDriveRootPath());
directory_loader_ = std::make_unique<DirectoryLoader>(
logger_, blocking_task_runner_.get(), resource_metadata_, scheduler_,
root_folder_id_loader_.get(), start_page_token_loader_.get(),
loader_controller_, util::GetDriveMyDriveRootPath(),
util::kTeamDriveIdDefaultCorpus, clock);
team_drive_list_loader_ = std::make_unique<TeamDriveListLoader>(
logger_, blocking_task_runner_.get(), resource_metadata, scheduler_,
loader_controller_);
}
DefaultCorpusChangeListLoader::~DefaultCorpusChangeListLoader() = default;
void DefaultCorpusChangeListLoader::AddChangeListLoaderObserver(
ChangeListLoaderObserver* observer) {
change_list_loader_->AddObserver(observer);
directory_loader_->AddObserver(observer);
}
void DefaultCorpusChangeListLoader::RemoveChangeListLoaderObserver(
ChangeListLoaderObserver* observer) {
change_list_loader_->RemoveObserver(observer);
directory_loader_->RemoveObserver(observer);
}
void DefaultCorpusChangeListLoader::AddTeamDriveListObserver(
TeamDriveListObserver* observer) {
team_drive_list_loader_->AddObserver(observer);
}
void DefaultCorpusChangeListLoader::RemoveTeamDriveListObserver(
TeamDriveListObserver* observer) {
team_drive_list_loader_->RemoveObserver(observer);
}
bool DefaultCorpusChangeListLoader::IsRefreshing() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return team_drive_list_loader_->IsRefreshing() ||
change_list_loader_->IsRefreshing();
}
void DefaultCorpusChangeListLoader::LoadIfNeeded(
const FileOperationCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// We execute the change list loader and then the team drive loader when it
// is completed. If the change list loader detects that it has previously
// loaded from the server, then it is a no-op. If it is a fresh load then it
// uses GetAllFiles which does not read any change lists with team drive info.
change_list_loader_->LoadIfNeeded(base::BindRepeating(
&DefaultCorpusChangeListLoader::OnChangeListLoadIfNeeded,
weak_ptr_factory_.GetWeakPtr(), callback));
}
void DefaultCorpusChangeListLoader::OnChangeListLoadIfNeeded(
const FileOperationCallback& callback,
FileError error) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (error != FILE_ERROR_OK) {
callback.Run(error);
return;
}
team_drive_list_loader_->LoadIfNeeded(callback);
}
void DefaultCorpusChangeListLoader::ReadDirectory(
const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
directory_loader_->ReadDirectory(directory_path, std::move(entries_callback),
completion_callback);
// Also start loading all of the user's contents.
LoadIfNeeded(base::DoNothing());
}
void DefaultCorpusChangeListLoader::CheckForUpdates(
const FileOperationCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
change_list_loader_->CheckForUpdates(callback);
}
} // namespace internal
} // namespace drive
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_DEFAULT_CORPUS_CHANGE_LIST_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_DEFAULT_CORPUS_CHANGE_LIST_LOADER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/default_clock.h"
#include "components/drive/chromeos/about_resource_root_folder_id_loader.h"
#include "components/drive/chromeos/change_list_loader.h"
#include "components/drive/chromeos/directory_loader.h"
#include "components/drive/chromeos/drive_change_list_loader.h"
#include "components/drive/chromeos/start_page_token_loader.h"
#include "components/drive/chromeos/team_drive_list_loader.h"
namespace drive {
class EventLogger;
class JobScheduler;
namespace internal {
class AboutResourceLoader;
class ChangeListLoader;
class DirectoryLoader;
class LoaderController;
class ResourceMetadata;
// Loads change lists, the full resource list, and directory contents for the
// users default corpus.
class DefaultCorpusChangeListLoader : public DriveChangeListLoader {
public:
// |clock| can be mocked for testing.
DefaultCorpusChangeListLoader(
EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
AboutResourceLoader* about_resource_loader,
LoaderController* apply_task_controller,
const base::Clock* clock = base::DefaultClock::GetInstance());
~DefaultCorpusChangeListLoader() override;
// DriveChangeListLoader overrides
void AddChangeListLoaderObserver(ChangeListLoaderObserver* observer) override;
void RemoveChangeListLoaderObserver(
ChangeListLoaderObserver* observer) override;
void AddTeamDriveListObserver(TeamDriveListObserver* observer) override;
void RemoveTeamDriveListObserver(TeamDriveListObserver* observer) override;
bool IsRefreshing() override;
void LoadIfNeeded(const FileOperationCallback& callback) override;
void ReadDirectory(const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback) override;
void CheckForUpdates(const FileOperationCallback& callback) override;
private:
// Called after calling LoadIfNeeded on team drives.
void OnChangeListLoadIfNeeded(const FileOperationCallback& callback,
FileError error);
std::unique_ptr<internal::AboutResourceRootFolderIdLoader>
root_folder_id_loader_;
std::unique_ptr<internal::ChangeListLoader> change_list_loader_;
std::unique_ptr<internal::DirectoryLoader> directory_loader_;
std::unique_ptr<internal::StartPageTokenLoader> start_page_token_loader_;
std::unique_ptr<TeamDriveListLoader> team_drive_list_loader_;
EventLogger* logger_; // Not owned.
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
ResourceMetadata* resource_metadata_; // Not owned.
JobScheduler* scheduler_; // Not owned.
LoaderController* loader_controller_; // Not owned.
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<DefaultCorpusChangeListLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DefaultCorpusChangeListLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_DEFAULT_CORPUS_CHANGE_LIST_LOADER_H_
This diff is collapsed.
// Copyright 2014 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 COMPONENTS_DRIVE_CHROMEOS_DIRECTORY_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_DIRECTORY_LOADER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "base/time/default_clock.h"
#include "components/drive/chromeos/file_system_interface.h"
#include "components/drive/file_errors.h"
#include "google_apis/drive/drive_api_error_codes.h"
#include "google_apis/drive/drive_common_callbacks.h"
namespace base {
class Clock;
class SequencedTaskRunner;
} // namespace base
namespace drive {
class EventLogger;
class JobScheduler;
class ResourceEntry;
namespace internal {
class RootFolderIdLoader;
class ChangeListLoaderObserver;
class DirectoryFetchInfo;
class LoaderController;
class ResourceMetadata;
class StartPageTokenLoader;
// DirectoryLoader is used to load directory contents.
class DirectoryLoader {
public:
// |clock| can be mocked for testing
DirectoryLoader(EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
RootFolderIdLoader* root_folder_id_loader,
StartPageTokenLoader* start_page_token_loader,
LoaderController* apply_task_controller,
const base::FilePath& root_entry_path,
const std::string& team_drive_id,
const base::Clock* clock = base::DefaultClock::GetInstance());
~DirectoryLoader();
// Adds and removes the observer.
void AddObserver(ChangeListLoaderObserver* observer);
void RemoveObserver(ChangeListLoaderObserver* observer);
// Reads the directory contents.
// |entries_callback| can be null.
// |completion_callback| must not be null.
void ReadDirectory(const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback);
private:
class FeedFetcher;
struct ReadDirectoryCallbackState;
// Part of ReadDirectory().
void ReadDirectoryAfterGetEntry(
const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback,
bool should_try_loading_parent,
const ResourceEntry* entry,
FileError error);
void ReadDirectoryAfterLoadParent(
const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback,
FileError error);
void ReadDirectoryAfterGetRootFolderId(
const base::FilePath& directory_path,
const std::string& local_id,
FileError error,
base::Optional<std::string> root_folder_id);
void ReadDirectoryAfterGetStartPageToken(
const base::FilePath& directory_path,
const std::string& local_id,
const std::string& root_folder_id,
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::StartPageToken> start_page_token);
void ReadDirectoryAfterCheckLocalState(
const base::FilePath& directory_path,
const std::string& remote_start_page_token,
const std::string& local_id,
const std::string& root_folder_id,
const ResourceEntry* entry,
const std::string* local_start_page_token,
FileError error);
// Part of ReadDirectory().
// This function should be called when the directory load is complete.
// Flushes the callbacks waiting for the directory to be loaded.
void OnDirectoryLoadComplete(const std::string& local_id, FileError error);
void OnDirectoryLoadCompleteAfterRead(const std::string& local_id,
const ResourceEntryVector* entries,
FileError error);
// Sends |entries| to the callbacks.
void SendEntries(const std::string& local_id,
const ResourceEntryVector& entries);
// ================= Implementation for directory loading =================
// Loads the directory contents from server, and updates the local metadata.
// Runs |callback| when it is finished.
void LoadDirectoryFromServer(const DirectoryFetchInfo& directory_fetch_info,
const std::string& root_folder_id);
// Part of LoadDirectoryFromServer() for a normal directory.
void LoadDirectoryFromServerAfterLoad(
const DirectoryFetchInfo& directory_fetch_info,
FeedFetcher* fetcher,
FileError error);
// Part of LoadDirectoryFromServer().
void LoadDirectoryFromServerAfterUpdateStartPageToken(
const DirectoryFetchInfo& directory_fetch_info,
const base::FilePath* directory_path,
FileError error);
EventLogger* logger_; // Not owned.
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
ResourceMetadata* resource_metadata_; // Not owned.
JobScheduler* scheduler_; // Not owned.
RootFolderIdLoader* root_folder_id_loader_; // Not owned.
StartPageTokenLoader* start_page_token_loader_; // Not owned
LoaderController* loader_controller_; // Not owned.
base::ObserverList<ChangeListLoaderObserver>::Unchecked observers_;
typedef std::map<std::string, std::vector<ReadDirectoryCallbackState> >
LoadCallbackMap;
LoadCallbackMap pending_load_callback_;
// Set of the running feed fetcher for the fast fetch.
std::set<std::unique_ptr<FeedFetcher>, base::UniquePtrComparator>
fast_fetch_feed_fetcher_set_;
// The root entry path for changes being loaded by this directory loader.
// Can be a team drive root entry or for the users default corpus will be the
// drive root entry.
const base::FilePath root_entry_path_;
// The team drive id for this directory loader. Used to retrieve the start
// page token when performing a fast fetch.
const std::string team_drive_id_;
const base::Clock* clock_; // Not Owned
THREAD_CHECKER(thread_checker_);
// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<DirectoryLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DirectoryLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_DIRECTORY_LOADER_H_
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
#include "components/drive/chromeos/file_system_interface.h"
#include "components/drive/file_errors.h"
namespace drive {
namespace internal {
class ChangeListLoaderObserver;
class TeamDriveListObserver;
// DriveChangeListLoader provides an abstraction for loading change lists, the
// full resource list amd directory contents, from Google Drive API.
// Implementations of the interface can, for example, include:
// - An implementation to retrieve from the users default corpus.
// - An implementation to retrieve from a specific team drive.
class DriveChangeListLoader {
public:
virtual ~DriveChangeListLoader() = default;
// Adds and removes an observer for change list loading events.
virtual void AddChangeListLoaderObserver(
ChangeListLoaderObserver* observer) = 0;
virtual void RemoveChangeListLoaderObserver(
ChangeListLoaderObserver* observer) = 0;
// Adds and removes an observer for team drive loading events.
virtual void AddTeamDriveListObserver(TeamDriveListObserver* observer) = 0;
virtual void RemoveTeamDriveListObserver(TeamDriveListObserver* observer) = 0;
// Indicates whether there is a request for full resource list or change
// list fetching is in flight (i.e. directory contents fetching does not
// count).
virtual bool IsRefreshing() = 0;
// Starts the change list loading if needed.
// |callback| must not be null.
virtual void LoadIfNeeded(const FileOperationCallback& callback) = 0;
// Check for updates on the server. May do nothing if a change list is
// already in the process of being loaded.
// |callback| must not be null.
virtual void CheckForUpdates(const FileOperationCallback& callback) = 0;
// Reads the given directory contents.
// |entries_callback| can be null.
// |completion_callback| must not be null.
virtual void ReadDirectory(
const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback) = 0;
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
// Copyright 2018 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 "components/drive/chromeos/loader_controller.h"
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
namespace drive {
namespace internal {
LoaderController::LoaderController() : lock_count_(0) {}
LoaderController::~LoaderController() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
std::unique_ptr<base::ScopedClosureRunner> LoaderController::GetLock() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
++lock_count_;
return std::make_unique<base::ScopedClosureRunner>(base::BindOnce(
&LoaderController::Unlock, weak_ptr_factory_.GetWeakPtr()));
}
void LoaderController::ScheduleRun(base::OnceClosure task) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(task);
if (lock_count_ > 0) {
pending_tasks_.push_back(std::move(task));
} else {
std::move(task).Run();
}
}
void LoaderController::Unlock() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_LT(0, lock_count_);
if (--lock_count_ > 0)
return;
std::vector<base::OnceClosure> tasks;
tasks.swap(pending_tasks_);
for (auto& task : tasks)
std::move(task).Run();
}
} // namespace internal
} // namespace drive
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_LOADER_CONTROLLER_H_
#define COMPONENTS_DRIVE_CHROMEOS_LOADER_CONTROLLER_H_
#include <memory>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
namespace base {
class ScopedClosureRunner;
}
namespace drive {
namespace internal {
// Delays execution of tasks as long as more than one lock is alive.
// Used to ensure that ChangeListLoader does not cause race condition by adding
// new entries created by sync tasks before they do.
// All code which may add entries found on the server to the local metadata
// should use this class.
// TODO(slangley): Consider specific unit tests for LoaderController. Currently
// it is tested as an artifact of other unit tests.
class LoaderController {
public:
LoaderController();
~LoaderController();
// Increments the lock count and returns an object which decrements the count
// on its destruction.
// While the lock count is positive, tasks will be pending.
// TODO(slangley): Return ScopedClosureRunner directly, rather than one that
// is wrapped in a unique_ptr.
std::unique_ptr<base::ScopedClosureRunner> GetLock();
// Runs the task if the lock count is 0, otherwise it will be pending.
void ScheduleRun(base::OnceClosure task);
private:
// Decrements the lock count.
void Unlock();
int lock_count_;
std::vector<base::OnceClosure> pending_tasks_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<LoaderController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(LoaderController);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_LOADER_CONTROLLER_H_
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_ROOT_FOLDER_ID_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_ROOT_FOLDER_ID_LOADER_H_
#include <string>
#include "base/callback.h"
#include "base/optional.h"
#include "components/drive/file_errors.h"
namespace drive {
namespace internal {
using RootFolderIdCallback =
base::RepeatingCallback<void(FileError, base::Optional<std::string>)>;
// RootFolderIdLoader is an interface that will load the root_folder_id for
// change list loader and directory loader.
class RootFolderIdLoader {
public:
virtual ~RootFolderIdLoader() = default;
// Retrieve the root folder id, which may be obtained from the server or
// potentially could be a constant value.
virtual void GetRootFolderId(const RootFolderIdCallback& callback) = 0;
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_ROOT_FOLDER_ID_LOADER_H_
// Copyright 2018 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 "components/drive/chromeos/start_page_token_loader.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/drive/job_scheduler.h"
using google_apis::StartPageToken;
using google_apis::StartPageTokenCallback;
namespace drive {
namespace internal {
StartPageTokenLoader::StartPageTokenLoader(const std::string& team_drive_id,
JobScheduler* scheduler)
: team_drive_id_(team_drive_id),
scheduler_(scheduler),
current_update_task_id_(-1),
pending_update_callbacks_(),
cached_start_page_token_() {}
StartPageTokenLoader::~StartPageTokenLoader() = default;
const StartPageToken* StartPageTokenLoader::cached_start_page_token() const {
return cached_start_page_token_.get();
}
void StartPageTokenLoader::GetStartPageToken(
const StartPageTokenCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(callback);
// If the update task is running, then we will wait for it.
if (!pending_update_callbacks_[current_update_task_id_].empty()) {
pending_update_callbacks_[current_update_task_id_].emplace_back(callback);
return;
}
if (cached_start_page_token_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(callback, google_apis::HTTP_NO_CONTENT,
std::make_unique<StartPageToken>(
*cached_start_page_token_)));
} else {
UpdateStartPageToken(callback);
}
}
void StartPageTokenLoader::UpdateStartPageToken(
const StartPageTokenCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(callback);
pending_update_callbacks_[++current_update_task_id_].emplace_back(callback);
scheduler_->GetStartPageToken(
team_drive_id_,
base::BindRepeating(&StartPageTokenLoader::UpdateStartPageTokenAfterGet,
weak_ptr_factory_.GetWeakPtr(),
current_update_task_id_));
}
void StartPageTokenLoader::UpdateStartPageTokenAfterGet(
int task_id,
google_apis::DriveApiErrorCode status,
std::unique_ptr<StartPageToken> start_page_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
FileError error = GDataToFileError(status);
std::vector<StartPageTokenCallback> callbacks =
pending_update_callbacks_[task_id];
pending_update_callbacks_.erase(task_id);
if (error != FILE_ERROR_OK) {
for (auto& callback : callbacks) {
callback.Run(status, nullptr);
}
return;
}
cached_start_page_token_ =
std::make_unique<StartPageToken>(*start_page_token);
for (auto& callback : callbacks) {
callback.Run(status, std::make_unique<StartPageToken>(*start_page_token));
}
}
} // namespace internal
} // namespace drive
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_START_PAGE_TOKEN_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_START_PAGE_TOKEN_LOADER_H_
#include <map>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "google_apis/drive/drive_api_requests.h"
namespace drive {
class JobScheduler;
namespace internal {
// Loads from the server and caches the start page token for a given team drive
// id. This class is used to determine where to start retrieving changes from
// the server, and as an optimization will cache the result until an
// update is triggered using UpdateStartPageToken.
class StartPageTokenLoader {
public:
StartPageTokenLoader(const std::string& team_drive_id,
JobScheduler* scheduler);
~StartPageTokenLoader();
// Returns the cached start page token. If there is no cached start page token
// then nullptr is returned.
const google_apis::StartPageToken* cached_start_page_token() const;
// Gets the most recent start page token and asynchronously runs |callback|.
// How this works is:
// - If there is an UpdateStartPageToken in flight, wait for the result and
// return it.
// - It there is NOT an UpdateStartPageToken in flight, and there is a
// cached start page token, then return the cached value.
// - If neither of the above are true, then start an UpdateStartPageToken
// request and return the result.
void GetStartPageToken(const google_apis::StartPageTokenCallback& callback);
// Gets the start page token from the server, and caches it if successful.
// This function calls JobScheduler::GetStartPageToken internally. The
// cached result will be used by GetStartPageToken.
void UpdateStartPageToken(
const google_apis::StartPageTokenCallback& callback);
private:
// This callback is used when the result of UpdateStartPage token returns from
// the server.
void UpdateStartPageTokenAfterGet(
int task_id,
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::StartPageToken> start_page_token);
// This start page token loader is bound to a single team_drive_id, and will
// always request the token for it. If team_drive_id_ is empty, then it
// retrieves the start page token for the users corpus.
const std::string team_drive_id_;
JobScheduler* scheduler_; // Not owned
THREAD_CHECKER(thread_checker_);
// We may have more than one update in flight at any time (multiple calls
// to UpdateStartPageToken will produce this scenario). We ensure that any
// calls to GetStartPageToken are bound to the update that was in progress
// when the GetStartPageToken was called, using the callback map below.
int current_update_task_id_;
std::map<int, std::vector<google_apis::StartPageTokenCallback>>
pending_update_callbacks_;
std::unique_ptr<google_apis::StartPageToken> cached_start_page_token_;
base::WeakPtrFactory<StartPageTokenLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(StartPageTokenLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_START_PAGE_TOKEN_LOADER_H_
// Copyright 2018 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 "components/drive/chromeos/team_drive_change_list_loader.h"
#include <memory>
#include "base/sequenced_task_runner.h"
#include "components/drive/chromeos/change_list_loader.h"
#include "components/drive/chromeos/directory_loader.h"
#include "components/drive/chromeos/root_folder_id_loader.h"
#include "components/drive/chromeos/start_page_token_loader.h"
namespace drive {
namespace internal {
namespace {
class ConstantRootFolderIdLoader : public RootFolderIdLoader {
public:
explicit ConstantRootFolderIdLoader(const std::string& team_drive_id)
: team_drive_id_(team_drive_id) {}
~ConstantRootFolderIdLoader() override = default;
void GetRootFolderId(const RootFolderIdCallback& callback) override {
callback.Run(FILE_ERROR_OK, team_drive_id_);
}
private:
const std::string team_drive_id_;
};
} // namespace
TeamDriveChangeListLoader::TeamDriveChangeListLoader(
const std::string& team_drive_id,
const base::FilePath& root_entry_path,
EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
LoaderController* apply_task_controller)
: team_drive_id_(team_drive_id), root_entry_path_(root_entry_path) {
root_folder_id_loader_ =
std::make_unique<ConstantRootFolderIdLoader>(team_drive_id_);
start_page_token_loader_ =
std::make_unique<StartPageTokenLoader>(team_drive_id_, scheduler);
change_list_loader_ = std::make_unique<ChangeListLoader>(
logger, blocking_task_runner, resource_metadata, scheduler,
root_folder_id_loader_.get(), start_page_token_loader_.get(),
apply_task_controller, team_drive_id_, root_entry_path_);
change_list_loader_->AddObserver(this);
directory_loader_ = std::make_unique<DirectoryLoader>(
logger, blocking_task_runner, resource_metadata, scheduler,
root_folder_id_loader_.get(), start_page_token_loader_.get(),
apply_task_controller, root_entry_path_, team_drive_id);
directory_loader_->AddObserver(this);
}
TeamDriveChangeListLoader::~TeamDriveChangeListLoader() = default;
base::WeakPtr<TeamDriveChangeListLoader>
TeamDriveChangeListLoader::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
// DriveChangeListLoader overrides
void TeamDriveChangeListLoader::AddChangeListLoaderObserver(
ChangeListLoaderObserver* observer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
change_list_loader_observers_.AddObserver(observer);
}
void TeamDriveChangeListLoader::RemoveChangeListLoaderObserver(
ChangeListLoaderObserver* observer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
change_list_loader_observers_.RemoveObserver(observer);
}
void TeamDriveChangeListLoader::AddTeamDriveListObserver(
TeamDriveListObserver* observer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void TeamDriveChangeListLoader::RemoveTeamDriveListObserver(
TeamDriveListObserver* observer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
bool TeamDriveChangeListLoader::IsRefreshing() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return change_list_loader_->IsRefreshing();
}
void TeamDriveChangeListLoader::LoadIfNeeded(
const FileOperationCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
change_list_loader_->LoadIfNeeded(callback);
}
void TeamDriveChangeListLoader::ReadDirectory(
const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(root_entry_path_ == directory_path ||
root_entry_path_.IsParent(directory_path))
<< "Directory paths are not related: " << root_entry_path_.value()
<< " -> " << directory_path.value();
directory_loader_->ReadDirectory(directory_path, std::move(entries_callback),
completion_callback);
}
void TeamDriveChangeListLoader::CheckForUpdates(
const FileOperationCallback& callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
change_list_loader_->CheckForUpdates(callback);
}
void TeamDriveChangeListLoader::OnDirectoryReloaded(
const base::FilePath& directory_path) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : change_list_loader_observers_) {
observer.OnDirectoryReloaded(directory_path);
}
}
void TeamDriveChangeListLoader::OnFileChanged(const FileChange& changed_files) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : change_list_loader_observers_) {
observer.OnFileChanged(changed_files);
}
}
void TeamDriveChangeListLoader::OnLoadFromServerComplete() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : change_list_loader_observers_) {
observer.OnLoadFromServerComplete();
}
}
void TeamDriveChangeListLoader::OnInitialLoadComplete() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : change_list_loader_observers_) {
observer.OnInitialLoadComplete();
}
}
} // namespace internal
} // namespace drive
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_TEAM_DRIVE_CHANGE_LIST_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_TEAM_DRIVE_CHANGE_LIST_LOADER_H_
#include <memory>
#include <string>
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "components/drive/chromeos/change_list_loader_observer.h"
#include "components/drive/chromeos/drive_change_list_loader.h"
namespace drive {
class EventLogger;
class JobScheduler;
namespace internal {
class ChangeListLoader;
class DirectoryLoader;
class LoaderController;
class RootFolderIdLoader;
class StartPageTokenLoader;
// TeamDriveChangeListLoader loads change lists for a specific team drive id.
// It uses directory loader and change list loader to retrieve change lists
// into resouce metadata. There should be one TeamDriveChangeListLoader created
// for every team drive that the user has access to.
class TeamDriveChangeListLoader : public DriveChangeListLoader,
public ChangeListLoaderObserver {
public:
TeamDriveChangeListLoader(const std::string& team_drive_id,
const base::FilePath& root_entry_path,
EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
LoaderController* apply_task_controller);
~TeamDriveChangeListLoader() override;
const base::FilePath& root_entry_path() const { return root_entry_path_; }
base::WeakPtr<TeamDriveChangeListLoader> GetWeakPtr();
// DriveChangeListLoader overrides
void AddChangeListLoaderObserver(ChangeListLoaderObserver* observer) override;
void RemoveChangeListLoaderObserver(
ChangeListLoaderObserver* observer) override;
void AddTeamDriveListObserver(TeamDriveListObserver* observer) override;
void RemoveTeamDriveListObserver(TeamDriveListObserver* observer) override;
bool IsRefreshing() override;
void LoadIfNeeded(const FileOperationCallback& callback) override;
void ReadDirectory(const base::FilePath& directory_path,
ReadDirectoryEntriesCallback entries_callback,
const FileOperationCallback& completion_callback) override;
void CheckForUpdates(const FileOperationCallback& callback) override;
// ChangeListLoaderObserver overrides
void OnDirectoryReloaded(const base::FilePath& directory_path) override;
void OnFileChanged(const FileChange& changed_files) override;
void OnLoadFromServerComplete() override;
void OnInitialLoadComplete() override;
private:
std::unique_ptr<RootFolderIdLoader> root_folder_id_loader_;
std::unique_ptr<StartPageTokenLoader> start_page_token_loader_;
std::unique_ptr<ChangeListLoader> change_list_loader_;
std::unique_ptr<DirectoryLoader> directory_loader_;
const std::string team_drive_id_;
const base::FilePath root_entry_path_;
base::ObserverList<ChangeListLoaderObserver>::Unchecked
change_list_loader_observers_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<TeamDriveChangeListLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(TeamDriveChangeListLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_TEAM_DRIVE_CHANGE_LIST_LOADER_H_
This diff is collapsed.
// Copyright 2018 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 COMPONENTS_DRIVE_CHROMEOS_TEAM_DRIVE_LIST_LOADER_H_
#define COMPONENTS_DRIVE_CHROMEOS_TEAM_DRIVE_LIST_LOADER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "components/drive/chromeos/resource_metadata.h"
#include "components/drive/chromeos/team_drive_list_observer.h"
#include "components/drive/file_errors.h"
#include "google_apis/drive/drive_api_requests.h"
namespace base {
class AtomicFlag;
class SequencedTaskRunner;
} // namespace base
namespace drive {
class EventLogger;
class JobScheduler;
namespace internal {
class ChangeList;
class LoaderController;
// Loads from the server the complete list of the users team drives. This class
// is used to obtain the initial list of team drives that a user has access to,
// so that team drive specific change lists and XMPP notifications can be
// accessed.
// Upon loading the resource metadata will be updated to reflect the team drives
// that the user has access to.
class TeamDriveListLoader {
public:
TeamDriveListLoader(EventLogger* logger,
base::SequencedTaskRunner* blocking_task_runner,
ResourceMetadata* resource_metadata,
JobScheduler* scheduler,
LoaderController* apply_task_controller);
~TeamDriveListLoader();
// Indicates whether there is a request for the team drives list in progress.
bool IsRefreshing() const;
// Gets the team drive list for the user from the server. |callback| must not
// be null.
void CheckForUpdates(const FileOperationCallback& callback);
// Loads the state of the users team drives. |callback| must not be null.
void LoadIfNeeded(const FileOperationCallback& callback);
// Adds or removes an observer for team drive related changes.
void AddObserver(TeamDriveListObserver* observer);
void RemoveObserver(TeamDriveListObserver* observer);
private:
struct TeamDriveUpdateData;
void OnTeamDriveListLoaded(
google_apis::DriveApiErrorCode status,
std::unique_ptr<google_apis::TeamDriveList> team_drives);
void OnReadDirectoryByPath(ResourceEntryVector* local_resources,
ResourceEntryVector remote_resources,
FileError error);
void OnTeamDrivesRemoved(ResourceEntryVector remote_resources,
TeamDriveUpdateData team_drive_updates,
FileError error);
void OnAddOrUpdateTeamDrives(TeamDriveUpdateData team_drive_updates,
FileError error);
void OnTeamDriveListLoadComplete(FileError error);
EventLogger* logger_; // Not owned.
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
std::unique_ptr<base::AtomicFlag> in_shutdown_;
std::vector<std::unique_ptr<ChangeList>> change_lists_;
std::vector<FileOperationCallback> pending_load_callbacks_;
bool loaded_ = false;
base::ObserverList<TeamDriveListObserver>::Unchecked observers_;
ResourceMetadata* resource_metadata_; // Not owned.
JobScheduler* scheduler_; // Not owned.
LoaderController* loader_controller_; // Not owned.
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<TeamDriveListLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(TeamDriveListLoader);
};
} // namespace internal
} // namespace drive
#endif // COMPONENTS_DRIVE_CHROMEOS_TEAM_DRIVE_LIST_LOADER_H_
This diff is collapsed.
// Copyright 2018 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 "components/drive/chromeos/start_page_token_loader.h"
#include <memory>
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/drive/chromeos/drive_test_util.h"
#include "components/drive/chromeos/file_cache.h"
#include "components/drive/chromeos/resource_metadata.h"
#include "components/drive/event_logger.h"
#include "components/drive/job_scheduler.h"
#include "components/drive/resource_metadata_storage.h"
#include "components/drive/service/fake_drive_service.h"
#include "components/drive/service/test_util.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace drive {
namespace internal {
class StartPageTokenLoaderTest : public testing::Test {
protected:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
test_util::RegisterDrivePrefs(pref_service_->registry());
logger_ = std::make_unique<EventLogger>();
drive_service_ = std::make_unique<FakeDriveService>();
ASSERT_TRUE(test_util::SetUpTestEntries(drive_service_.get()));
network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
network::mojom::ConnectionType::CONNECTION_WIFI);
scheduler_ = std::make_unique<JobScheduler>(
pref_service_.get(), logger_.get(), drive_service_.get(),
network::TestNetworkConnectionTracker::GetInstance(),
base::ThreadTaskRunnerHandle::Get().get(), mojo::NullRemote());
metadata_storage_.reset(new ResourceMetadataStorage(
temp_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get().get()));
ASSERT_TRUE(metadata_storage_->Initialize());
cache_.reset(new FileCache(metadata_storage_.get(), temp_dir_.GetPath(),
base::ThreadTaskRunnerHandle::Get().get(),
nullptr /* free_disk_space_getter */));
ASSERT_TRUE(cache_->Initialize());
metadata_.reset(
new ResourceMetadata(metadata_storage_.get(), cache_.get(),
base::ThreadTaskRunnerHandle::Get().get()));
ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
start_page_token_loader_ = std::make_unique<StartPageTokenLoader>(
empty_team_drive_id_, scheduler_.get());
}
// Adds a new file to the root directory of the service.
std::unique_ptr<google_apis::FileResource> AddNewFile(
const std::string& title) {
google_apis::DriveApiErrorCode error = google_apis::DRIVE_FILE_ERROR;
std::unique_ptr<google_apis::FileResource> entry;
drive_service_->AddNewFile(
"text/plain", "content text", drive_service_->GetRootResourceId(),
title,
false, // shared_with_me
google_apis::test_util::CreateCopyResultCallback(&error, &entry));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_CREATED, error);
return entry;
}
// Empty team drive id equates to the users default corpus.
const std::string empty_team_drive_id_;
content::BrowserTaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<EventLogger> logger_;
std::unique_ptr<FakeDriveService> drive_service_;
std::unique_ptr<JobScheduler> scheduler_;
std::unique_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
metadata_storage_;
std::unique_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
std::unique_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
std::unique_ptr<StartPageTokenLoader> start_page_token_loader_;
};
TEST_F(StartPageTokenLoaderTest, SingleStartPageTokenLoader) {
google_apis::DriveApiErrorCode error[6] = {};
std::unique_ptr<google_apis::StartPageToken> start_page_token[6];
EXPECT_EQ(0, drive_service_->start_page_token_load_count());
ASSERT_FALSE(start_page_token_loader_->cached_start_page_token());
start_page_token_loader_->GetStartPageToken(
google_apis::test_util::CreateCopyResultCallback(error + 0,
start_page_token + 0));
start_page_token_loader_->GetStartPageToken(
google_apis::test_util::CreateCopyResultCallback(error + 1,
start_page_token + 1));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[0]);
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[1]);
const std::string& first_token = start_page_token[0]->start_page_token();
EXPECT_EQ(first_token, start_page_token[1]->start_page_token());
ASSERT_TRUE(start_page_token_loader_->cached_start_page_token());
ASSERT_EQ(
first_token,
start_page_token_loader_->cached_start_page_token()->start_page_token());
// Create a new change, which should change the start page token.
AddNewFile("temp");
start_page_token_loader_->UpdateStartPageToken(
google_apis::test_util::CreateCopyResultCallback(error + 2,
start_page_token + 2));
start_page_token_loader_->GetStartPageToken(
google_apis::test_util::CreateCopyResultCallback(error + 3,
start_page_token + 3));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[2]);
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[3]);
const std::string& second_token = start_page_token[2]->start_page_token();
EXPECT_NE(first_token, second_token);
EXPECT_EQ(second_token, start_page_token[3]->start_page_token());
ASSERT_EQ(
second_token,
start_page_token_loader_->cached_start_page_token()->start_page_token());
// Create a new change, which should change the start page token.
AddNewFile("temp2");
start_page_token_loader_->GetStartPageToken(
google_apis::test_util::CreateCopyResultCallback(error + 4,
start_page_token + 4));
start_page_token_loader_->UpdateStartPageToken(
google_apis::test_util::CreateCopyResultCallback(error + 5,
start_page_token + 5));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error[4]);
EXPECT_EQ(google_apis::HTTP_SUCCESS, error[5]);
EXPECT_EQ(second_token, start_page_token[4]->start_page_token());
const std::string& third_token = start_page_token[5]->start_page_token();
EXPECT_NE(first_token, third_token);
EXPECT_NE(second_token, third_token);
ASSERT_EQ(
third_token,
start_page_token_loader_->cached_start_page_token()->start_page_token());
EXPECT_EQ(3, drive_service_->start_page_token_load_count());
}
} // namespace internal
} // namespace drive
This diff is collapsed.
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