#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/browser/drive/drive_api_util.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/drive/drive_api_parser.h"
#include "google_apis/drive/gdata_wapi_parser.h"
#include "google_apis/drive/test_util.h"
-#include "google_apis/drive/time_util.h"
#include "net/base/escape.h"
#include "net/base/url_util.h"
using content::BrowserThread;
using google_apis::AboutResource;
using google_apis::AboutResourceCallback;
-using google_apis::AccountMetadata;
using google_apis::AppList;
using google_apis::AppListCallback;
using google_apis::AuthStatusCallback;
namespace drive {
namespace {
-// Mime type of directories.
-const char kDriveFolderMimeType[] = "application/vnd.google-apps.folder";
-
// Returns true if a resource entry matches with the search query.
// Supports queries consist of following format.
// - Phrases quoted by double/single quotes
app_list_load_count_(0),
blocked_resource_list_load_count_(0),
offline_(false),
- never_return_all_resource_list_(false) {
+ never_return_all_resource_list_(false),
+ share_url_base_("https://share_url/") {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ about_resource_->set_largest_change_id(654321);
+ about_resource_->set_quota_bytes_total(9876543210);
+ about_resource_->set_quota_bytes_used(6789012345);
+ about_resource_->set_root_folder_id(GetRootResourceId());
}
FakeDriveService::~FakeDriveService() {
STLDeleteValues(&entries_);
}
-bool FakeDriveService::LoadResourceListForWapi(
- const std::string& relative_path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_ptr<base::Value> raw_value = test_util::LoadJSONFile(relative_path);
- base::DictionaryValue* as_dict = NULL;
- scoped_ptr<base::Value> feed;
- base::DictionaryValue* feed_as_dict = NULL;
-
- // Extract the "feed" from the raw value and take the ownership.
- // Note that Remove() transfers the ownership to |feed|.
- if (raw_value->GetAsDictionary(&as_dict) &&
- as_dict->Remove("feed", &feed) &&
- feed->GetAsDictionary(&feed_as_dict)) {
- base::ListValue* entries = NULL;
- if (feed_as_dict->GetList("entry", &entries)) {
- for (size_t i = 0; i < entries->GetSize(); ++i) {
- base::DictionaryValue* entry = NULL;
- if (entries->GetDictionary(i, &entry)) {
- scoped_ptr<ResourceEntry> resource_entry =
- ResourceEntry::CreateFrom(*entry);
-
- const std::string resource_id = resource_entry->resource_id();
- EntryInfoMap::iterator it = entries_.find(resource_id);
- if (it == entries_.end()) {
- it = entries_.insert(
- std::make_pair(resource_id, new EntryInfo)).first;
- }
- EntryInfo* new_entry = it->second;
-
- ChangeResource* change = &new_entry->change_resource;
- change->set_change_id(resource_entry->changestamp());
- change->set_file_id(resource_id);
- change->set_file(
- util::ConvertResourceEntryToFileResource(*resource_entry));
-
- const Link* share_url =
- resource_entry->GetLinkByType(Link::LINK_SHARE);
- if (share_url)
- new_entry->share_url = share_url->href();
-
- entry->GetString("test$data", &new_entry->content_data);
- }
- }
- }
- }
-
- return feed_as_dict;
-}
-
-bool FakeDriveService::LoadAccountMetadataForWapi(
- const std::string& relative_path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- scoped_ptr<base::Value> value = test_util::LoadJSONFile(relative_path);
- if (!value)
- return false;
-
- about_resource_ = util::ConvertAccountMetadataToAboutResource(
- *AccountMetadata::CreateFrom(*value), GetRootResourceId());
- if (!about_resource_)
- return false;
-
- // Add the largest changestamp to the existing entries.
- // This will be used to generate change lists in GetResourceList().
- for (EntryInfoMap::iterator it = entries_.begin(); it != entries_.end();
- ++it) {
- it->second->change_resource.set_change_id(
- about_resource_->largest_change_id());
- }
- return true;
-}
-
bool FakeDriveService::LoadAppListForDriveApi(
const std::string& relative_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!next_link.is_empty());
DCHECK(!callback.is_null());
- return GetRemainingResourceList(next_link, callback);
+ // "changestamp", "q", "parent" and "start-offset" are parameters to
+ // implement "paging" of the result on FakeDriveService.
+ // The URL should be the one filled in GetResourceListInternal of the
+ // previous method invocation, so it should start with "http://localhost/?".
+ // See also GetResourceListInternal.
+ DCHECK_EQ(next_link.host(), "localhost");
+ DCHECK_EQ(next_link.path(), "/");
+
+ int64 start_changestamp = 0;
+ std::string search_query;
+ std::string directory_resource_id;
+ int start_offset = 0;
+ int max_results = default_max_results_;
+ std::vector<std::pair<std::string, std::string> > parameters;
+ if (base::SplitStringIntoKeyValuePairs(
+ next_link.query(), '=', '&', ¶meters)) {
+ for (size_t i = 0; i < parameters.size(); ++i) {
+ if (parameters[i].first == "changestamp") {
+ base::StringToInt64(parameters[i].second, &start_changestamp);
+ } else if (parameters[i].first == "q") {
+ search_query =
+ net::UnescapeURLComponent(parameters[i].second,
+ net::UnescapeRule::URL_SPECIAL_CHARS);
+ } else if (parameters[i].first == "parent") {
+ directory_resource_id =
+ net::UnescapeURLComponent(parameters[i].second,
+ net::UnescapeRule::URL_SPECIAL_CHARS);
+ } else if (parameters[i].first == "start-offset") {
+ base::StringToInt(parameters[i].second, &start_offset);
+ } else if (parameters[i].first == "max-results") {
+ base::StringToInt(parameters[i].second, &max_results);
+ }
+ }
+ }
+
+ GetResourceListInternal(
+ start_changestamp, search_query, directory_resource_id,
+ start_offset, max_results, NULL, callback);
+ return CancelCallback();
}
CancelCallback FakeDriveService::GetRemainingFileList(
DCHECK(!next_link.is_empty());
DCHECK(!callback.is_null());
- return GetRemainingResourceList(next_link, callback);
+ return GetRemainingChangeList(next_link, callback);
}
CancelCallback FakeDriveService::GetResourceEntry(
scoped_ptr<EntryInfo> copied_entry(new EntryInfo);
copied_entry->content_data = entry->content_data;
copied_entry->share_url = entry->share_url;
-
- // TODO(hashimoto): Implement a proper way to copy FileResource.
- scoped_ptr<ResourceEntry> copied_resource_entry =
- util::ConvertChangeResourceToResourceEntry(entry->change_resource);
copied_entry->change_resource.set_file(
- util::ConvertResourceEntryToFileResource(*copied_resource_entry));
+ make_scoped_ptr(new FileResource(*entry->change_resource.file())));
ChangeResource* new_change = &copied_entry->change_resource;
FileResource* new_file = new_change->mutable_file();
new_file->set_file_id(new_resource_id);
new_file->set_title(new_title);
- scoped_ptr<ParentReference> parent(new ParentReference);
- parent->set_file_id(parent_resource_id);
- parent->set_parent_link(GetFakeLinkUrl(parent_resource_id));
- parent->set_is_root(parent_resource_id == GetRootResourceId());
- ScopedVector<ParentReference> parents;
- parents.push_back(parent.release());
- new_file->set_parents(parents.Pass());
+ ParentReference parent;
+ parent.set_file_id(parent_resource_id);
+ parent.set_parent_link(GetFakeLinkUrl(parent_resource_id));
+ std::vector<ParentReference> parents;
+ parents.push_back(parent);
+ *new_file->mutable_parents() = parents;
if (!last_modified.is_null())
new_file->set_modified_date(last_modified);
if (entry) {
ChangeResource* change = &entry->change_resource;
FileResource* file = change->mutable_file();
- file->set_title(new_title);
+
+ if (!new_title.empty())
+ file->set_title(new_title);
// Set parent if necessary.
if (!parent_resource_id.empty()) {
- scoped_ptr<ParentReference> parent(new ParentReference);
- parent->set_file_id(parent_resource_id);
- parent->set_parent_link(GetFakeLinkUrl(parent_resource_id));
- parent->set_is_root(parent_resource_id == GetRootResourceId());
-
- ScopedVector<ParentReference> parents;
- parents.push_back(parent.release());
- file->set_parents(parents.Pass());
+ ParentReference parent;
+ parent.set_file_id(parent_resource_id);
+ parent.set_parent_link(GetFakeLinkUrl(parent_resource_id));
+
+ std::vector<ParentReference> parents;
+ parents.push_back(parent);
+ *file->mutable_parents() = parents;
}
if (!last_modified.is_null())
// structure. That is, each resource can have multiple parent.
// We mimic the behavior here; AddResourceToDirectoy just adds
// one more parent, not overwriting old ones.
- scoped_ptr<ParentReference> parent(new ParentReference);
- parent->set_file_id(parent_resource_id);
- parent->set_parent_link(GetFakeLinkUrl(parent_resource_id));
- parent->set_is_root(parent_resource_id == GetRootResourceId());
- change->mutable_file()->mutable_parents()->push_back(parent.release());
+ ParentReference parent;
+ parent.set_file_id(parent_resource_id);
+ parent.set_parent_link(GetFakeLinkUrl(parent_resource_id));
+ change->mutable_file()->mutable_parents()->push_back(parent);
AddNewChangestamp(change);
base::MessageLoop::current()->PostTask(
if (entry) {
ChangeResource* change = &entry->change_resource;
FileResource* file = change->mutable_file();
- ScopedVector<ParentReference>* parents = file->mutable_parents();
+ std::vector<ParentReference>* parents = file->mutable_parents();
for (size_t i = 0; i < parents->size(); ++i) {
- if ((*parents)[i]->file_id() == parent_resource_id) {
+ if ((*parents)[i].file_id() == parent_resource_id) {
parents->erase(parents->begin() + i);
AddNewChangestamp(change);
base::MessageLoop::current()->PostTask(
const std::string& directory_title,
const AddNewDirectoryOptions& options,
const GetResourceEntryCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!callback.is_null());
-
- if (offline_) {
- scoped_ptr<ResourceEntry> null;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback,
- GDATA_NO_CONNECTION,
- base::Passed(&null)));
- return CancelCallback();
- }
-
- const EntryInfo* new_entry = AddNewEntry(kDriveFolderMimeType,
- "", // content_data
- parent_resource_id,
- directory_title,
- false); // shared_with_me
- if (!new_entry) {
- scoped_ptr<ResourceEntry> null;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, HTTP_NOT_FOUND, base::Passed(&null)));
- return CancelCallback();
- }
-
- scoped_ptr<ResourceEntry> parsed_entry(
- util::ConvertChangeResourceToResourceEntry(new_entry->change_resource));
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, HTTP_CREATED, base::Passed(&parsed_entry)));
- return CancelCallback();
+ return AddNewDirectoryWithResourceId(
+ "",
+ parent_resource_id.empty() ? GetRootResourceId() : parent_resource_id,
+ directory_title,
+ options,
+ callback);
}
CancelCallback FakeDriveService::InitiateUploadNewFile(
DCHECK(!session->parent_resource_id.empty());
DCHECK(!session->title.empty());
const EntryInfo* new_entry = AddNewEntry(
+ "", // auto generate resource id.
session->content_type,
content_data,
session->parent_resource_id,
return CancelCallback();
}
-CancelCallback FakeDriveService::GetResourceListInDirectoryByWapi(
- const std::string& directory_resource_id,
- const google_apis::GetResourceListCallback& callback) {
- return GetResourceListInDirectory(
- directory_resource_id == util::kWapiRootDirectoryResourceId ?
- GetRootResourceId() :
- directory_resource_id,
- callback);
-}
-
-CancelCallback FakeDriveService::GetRemainingResourceList(
- const GURL& next_link,
- const google_apis::GetResourceListCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!next_link.is_empty());
- DCHECK(!callback.is_null());
-
- // "changestamp", "q", "parent" and "start-offset" are parameters to
- // implement "paging" of the result on FakeDriveService.
- // The URL should be the one filled in GetResourceListInternal of the
- // previous method invocation, so it should start with "http://localhost/?".
- // See also GetResourceListInternal.
- DCHECK_EQ(next_link.host(), "localhost");
- DCHECK_EQ(next_link.path(), "/");
-
- int64 start_changestamp = 0;
- std::string search_query;
- std::string directory_resource_id;
- int start_offset = 0;
- int max_results = default_max_results_;
- std::vector<std::pair<std::string, std::string> > parameters;
- if (base::SplitStringIntoKeyValuePairs(
- next_link.query(), '=', '&', ¶meters)) {
- for (size_t i = 0; i < parameters.size(); ++i) {
- if (parameters[i].first == "changestamp") {
- base::StringToInt64(parameters[i].second, &start_changestamp);
- } else if (parameters[i].first == "q") {
- search_query =
- net::UnescapeURLComponent(parameters[i].second,
- net::UnescapeRule::URL_SPECIAL_CHARS);
- } else if (parameters[i].first == "parent") {
- directory_resource_id =
- net::UnescapeURLComponent(parameters[i].second,
- net::UnescapeRule::URL_SPECIAL_CHARS);
- } else if (parameters[i].first == "start-offset") {
- base::StringToInt(parameters[i].second, &start_offset);
- } else if (parameters[i].first == "max-results") {
- base::StringToInt(parameters[i].second, &max_results);
- }
- }
- }
-
- GetResourceListInternal(
- start_changestamp, search_query, directory_resource_id,
- start_offset, max_results, NULL, callback);
- return CancelCallback();
-}
-
void FakeDriveService::AddNewFile(const std::string& content_type,
const std::string& content_data,
const std::string& parent_resource_id,
const std::string& title,
bool shared_with_me,
const GetResourceEntryCallback& callback) {
+ AddNewFileWithResourceId("", content_type, content_data, parent_resource_id,
+ title, shared_with_me, callback);
+}
+
+void FakeDriveService::AddNewFileWithResourceId(
+ const std::string& resource_id,
+ const std::string& content_type,
+ const std::string& content_data,
+ const std::string& parent_resource_id,
+ const std::string& title,
+ bool shared_with_me,
+ const GetResourceEntryCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
return;
}
- const EntryInfo* new_entry = AddNewEntry(content_type,
+ const EntryInfo* new_entry = AddNewEntry(resource_id,
+ content_type,
content_data,
parent_resource_id,
title,
base::Bind(callback, HTTP_CREATED, base::Passed(&parsed_entry)));
}
+CancelCallback FakeDriveService::AddNewDirectoryWithResourceId(
+ const std::string& resource_id,
+ const std::string& parent_resource_id,
+ const std::string& directory_title,
+ const AddNewDirectoryOptions& options,
+ const GetResourceEntryCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ if (offline_) {
+ scoped_ptr<ResourceEntry> null;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback,
+ GDATA_NO_CONNECTION,
+ base::Passed(&null)));
+ return CancelCallback();
+ }
+
+ const EntryInfo* new_entry = AddNewEntry(resource_id,
+ util::kDriveFolderMimeType,
+ "", // content_data
+ parent_resource_id,
+ directory_title,
+ false); // shared_with_me
+ if (!new_entry) {
+ scoped_ptr<ResourceEntry> null;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, HTTP_NOT_FOUND, base::Passed(&null)));
+ return CancelCallback();
+ }
+
+ scoped_ptr<ResourceEntry> parsed_entry(
+ util::ConvertChangeResourceToResourceEntry(new_entry->change_resource));
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, HTTP_CREATED, base::Passed(&parsed_entry)));
+ return CancelCallback();
+}
+
void FakeDriveService::SetLastModifiedTime(
const std::string& resource_id,
const base::Time& last_modified_time,
}
const FakeDriveService::EntryInfo* FakeDriveService::AddNewEntry(
+ const std::string& given_resource_id,
const std::string& content_type,
const std::string& content_data,
const std::string& parent_resource_id,
return NULL;
}
- std::string resource_id = GetNewResourceId();
+ const std::string resource_id =
+ given_resource_id.empty() ? GetNewResourceId() : given_resource_id;
+ if (entries_.count(resource_id))
+ return NULL;
GURL upload_url = GURL("https://xxx/upload/" + resource_id);
scoped_ptr<EntryInfo> new_entry(new EntryInfo);
new_file->set_file_id(resource_id);
new_file->set_title(title);
// Set the contents, size and MD5 for a file.
- if (content_type != kDriveFolderMimeType) {
+ if (content_type != util::kDriveFolderMimeType) {
new_entry->content_data = content_data;
new_file->set_file_size(content_data.size());
new_file->set_md5_checksum(base::MD5String(content_data));
std::string escaped_resource_id = net::EscapePath(resource_id);
- // Set download URL and mime type.
- new_file->set_download_url(
- GURL("https://xxx/content/" + escaped_resource_id));
+ // Set mime type.
new_file->set_mime_type(content_type);
+ // Set alternate link if needed.
+ if (content_type == util::kGoogleDocumentMimeType)
+ new_file->set_alternate_link(GURL("https://document_alternate_link"));
+
// Set parents.
- scoped_ptr<ParentReference> parent(new ParentReference);
- if (parent_resource_id.empty())
- parent->set_file_id(GetRootResourceId());
- else
- parent->set_file_id(parent_resource_id);
- parent->set_parent_link(GetFakeLinkUrl(parent->file_id()));
- parent->set_is_root(parent->file_id() == GetRootResourceId());
- ScopedVector<ParentReference> parents;
- parents.push_back(parent.release());
- new_file->set_parents(parents.Pass());
-
- new_file->set_self_link(GURL("https://xxx/edit/" + escaped_resource_id));
+ if (!parent_resource_id.empty()) {
+ ParentReference parent;
+ parent.set_file_id(parent_resource_id);
+ parent.set_parent_link(GetFakeLinkUrl(parent.file_id()));
+ std::vector<ParentReference> parents;
+ parents.push_back(parent);
+ *new_file->mutable_parents() = parents;
+ }
new_entry->share_url = net::AppendOrReplaceQueryParameter(
share_url_base_, "name", title);
base::Int64ToString(next_upload_sequence_number_++));
}
+google_apis::CancelCallback FakeDriveService::AddPermission(
+ const std::string& resource_id,
+ const std::string& email,
+ google_apis::drive::PermissionRole role,
+ const google_apis::EntryActionCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ NOTREACHED();
+ return CancelCallback();
+}
+
} // namespace drive