Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/drive/fake_drive_service.h" | 5 #include "chrome/browser/drive/fake_drive_service.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/file_util.h" | |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/md5.h" | |
| 10 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 11 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 13 #include "base/strings/string_tokenizer.h" | 15 #include "base/strings/string_tokenizer.h" |
| 14 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 17 #include "chrome/browser/google_apis/drive_api_parser.h" | 19 #include "chrome/browser/google_apis/drive_api_parser.h" |
| 18 #include "chrome/browser/google_apis/gdata_wapi_parser.h" | 20 #include "chrome/browser/google_apis/gdata_wapi_parser.h" |
| 19 #include "chrome/browser/google_apis/test_util.h" | 21 #include "chrome/browser/google_apis/test_util.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 // TODO(peria): Deal with other attributes than title. | 91 // TODO(peria): Deal with other attributes than title. |
| 90 if (!key.empty() && key != "title") | 92 if (!key.empty() && key != "title") |
| 91 return false; | 93 return false; |
| 92 // Search query in the title. | 94 // Search query in the title. |
| 93 if (entry.title().find(value) == std::string::npos) | 95 if (entry.title().find(value) == std::string::npos) |
| 94 return false; | 96 return false; |
| 95 } | 97 } |
| 96 return true; | 98 return true; |
| 97 } | 99 } |
| 98 | 100 |
| 99 // Gets the upload URL from the given entry. Returns an empty URL if not | |
| 100 // found. | |
| 101 GURL GetUploadUrl(const base::DictionaryValue& entry) { | |
| 102 std::string upload_url; | |
| 103 const base::ListValue* links = NULL; | |
| 104 if (entry.GetList("link", &links) && links) { | |
| 105 for (size_t link_index = 0; | |
| 106 link_index < links->GetSize(); | |
| 107 ++link_index) { | |
| 108 const base::DictionaryValue* link = NULL; | |
| 109 std::string rel; | |
| 110 if (links->GetDictionary(link_index, &link) && | |
| 111 link && link->GetString("rel", &rel) && | |
| 112 rel == kUploadUrlRel && | |
| 113 link->GetString("href", &upload_url)) { | |
| 114 break; | |
| 115 } | |
| 116 } | |
| 117 } | |
| 118 return GURL(upload_url); | |
| 119 } | |
| 120 | |
| 121 // Returns |url| without query parameter. | 101 // Returns |url| without query parameter. |
| 122 GURL RemoveQueryParameter(const GURL& url) { | 102 GURL RemoveQueryParameter(const GURL& url) { |
| 123 GURL::Replacements replacements; | 103 GURL::Replacements replacements; |
| 124 replacements.ClearQuery(); | 104 replacements.ClearQuery(); |
| 125 return url.ReplaceComponents(replacements); | 105 return url.ReplaceComponents(replacements); |
| 126 } | 106 } |
| 127 | 107 |
| 128 } // namespace | 108 } // namespace |
| 129 | 109 |
| 110 struct FakeDriveService::UploadSession { | |
| 111 std::string content_type; | |
| 112 int64 content_length; | |
| 113 std::string parent_resource_id; | |
| 114 std::string resource_id; | |
| 115 std::string etag; | |
| 116 std::string title; | |
| 117 | |
| 118 int64 uploaded_size; | |
| 119 | |
| 120 UploadSession() | |
| 121 : content_length(0), | |
| 122 uploaded_size(0) {} | |
| 123 | |
| 124 UploadSession( | |
| 125 std::string content_type, | |
| 126 int64 content_length, | |
| 127 std::string parent_resource_id, | |
| 128 std::string resource_id, | |
| 129 std::string etag, | |
| 130 std::string title) | |
| 131 : content_type(content_type), | |
| 132 content_length(content_length), | |
| 133 parent_resource_id(parent_resource_id), | |
| 134 resource_id(resource_id), | |
| 135 etag(etag), | |
| 136 title(title), | |
| 137 uploaded_size(0) { | |
| 138 } | |
| 139 }; | |
| 140 | |
| 130 FakeDriveService::FakeDriveService() | 141 FakeDriveService::FakeDriveService() |
| 131 : largest_changestamp_(0), | 142 : largest_changestamp_(0), |
| 132 published_date_seq_(0), | 143 published_date_seq_(0), |
| 144 next_upload_sequence_number_(0), | |
| 133 default_max_results_(0), | 145 default_max_results_(0), |
| 134 resource_id_count_(0), | 146 resource_id_count_(0), |
| 135 resource_list_load_count_(0), | 147 resource_list_load_count_(0), |
| 136 change_list_load_count_(0), | 148 change_list_load_count_(0), |
| 137 directory_load_count_(0), | 149 directory_load_count_(0), |
| 138 about_resource_load_count_(0), | 150 about_resource_load_count_(0), |
| 139 offline_(false) { | 151 offline_(false), |
| 152 weak_factory_(this) { | |
| 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 141 } | 154 } |
| 142 | 155 |
| 143 FakeDriveService::~FakeDriveService() { | 156 FakeDriveService::~FakeDriveService() { |
| 144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 145 } | 158 } |
| 146 | 159 |
| 147 bool FakeDriveService::LoadResourceListForWapi( | 160 bool FakeDriveService::LoadResourceListForWapi( |
| 148 const std::string& relative_path) { | 161 const std::string& relative_path) { |
| 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 if (!entry) { | 554 if (!entry) { |
| 542 base::MessageLoopProxy::current()->PostTask( | 555 base::MessageLoopProxy::current()->PostTask( |
| 543 FROM_HERE, | 556 FROM_HERE, |
| 544 base::Bind(download_action_callback, HTTP_NOT_FOUND, base::FilePath())); | 557 base::Bind(download_action_callback, HTTP_NOT_FOUND, base::FilePath())); |
| 545 return CancelCallback(); | 558 return CancelCallback(); |
| 546 } | 559 } |
| 547 | 560 |
| 548 // Write "x"s of the file size specified in the entry. | 561 // Write "x"s of the file size specified in the entry. |
| 549 std::string file_size_string; | 562 std::string file_size_string; |
| 550 entry->GetString("docs$size.$t", &file_size_string); | 563 entry->GetString("docs$size.$t", &file_size_string); |
| 551 // TODO(satorux): To be correct, we should update docs$md5Checksum.$t here. | |
| 552 int64 file_size = 0; | 564 int64 file_size = 0; |
| 553 if (base::StringToInt64(file_size_string, &file_size)) { | 565 if (base::StringToInt64(file_size_string, &file_size)) { |
| 554 base::BinaryValue* content_binary_data; | 566 base::BinaryValue* content_binary_data; |
| 555 std::string content_data; | 567 std::string content_data; |
| 556 if (entry->GetBinary("test$data", &content_binary_data)) { | 568 if (entry->GetBinary("test$data", &content_binary_data)) { |
| 557 content_data = std::string(content_binary_data->GetBuffer(), | 569 content_data = std::string(content_binary_data->GetBuffer(), |
| 558 content_binary_data->GetSize()); | 570 content_binary_data->GetSize()); |
| 559 } | 571 } |
| 560 DCHECK_EQ(static_cast<size_t>(file_size), content_data.size()); | 572 DCHECK_EQ(static_cast<size_t>(file_size), content_data.size()); |
| 561 | 573 |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 885 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 897 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 886 DCHECK(!callback.is_null()); | 898 DCHECK(!callback.is_null()); |
| 887 | 899 |
| 888 if (offline_) { | 900 if (offline_) { |
| 889 base::MessageLoop::current()->PostTask( | 901 base::MessageLoop::current()->PostTask( |
| 890 FROM_HERE, | 902 FROM_HERE, |
| 891 base::Bind(callback, GDATA_NO_CONNECTION, GURL())); | 903 base::Bind(callback, GDATA_NO_CONNECTION, GURL())); |
| 892 return CancelCallback(); | 904 return CancelCallback(); |
| 893 } | 905 } |
| 894 | 906 |
| 895 // Content length should be zero, as we'll create an empty file first. The | 907 if (parent_resource_id != GetRootResourceId() && |
| 896 // content will be added in ResumeUpload(). | 908 !FindEntryByResourceId(parent_resource_id)) { |
| 897 const base::DictionaryValue* new_entry = AddNewEntry(content_type, | |
| 898 "", // content_data | |
| 899 parent_resource_id, | |
| 900 title, | |
| 901 false, // shared_with_me | |
| 902 "file"); | |
| 903 if (!new_entry) { | |
| 904 base::MessageLoop::current()->PostTask( | 909 base::MessageLoop::current()->PostTask( |
| 905 FROM_HERE, | 910 FROM_HERE, |
| 906 base::Bind(callback, HTTP_NOT_FOUND, GURL())); | 911 base::Bind(callback, HTTP_NOT_FOUND, GURL())); |
| 907 return CancelCallback(); | 912 return CancelCallback(); |
| 908 } | 913 } |
| 909 const GURL upload_url = GetUploadUrl(*new_entry); | 914 |
| 910 DCHECK(upload_url.is_valid()); | 915 GURL session_url = net::AppendQueryParameter( |
| 916 GetNewUploadSessionUrl(), "mode", "newfile"); | |
| 917 upload_session_[session_url] = | |
| 918 UploadSession(content_type, content_length, | |
| 919 parent_resource_id, | |
| 920 "", // resource_id | |
| 921 "", // etag | |
| 922 title); | |
| 911 | 923 |
| 912 base::MessageLoop::current()->PostTask( | 924 base::MessageLoop::current()->PostTask( |
| 913 FROM_HERE, | 925 FROM_HERE, |
| 914 base::Bind(callback, HTTP_SUCCESS, | 926 base::Bind(callback, HTTP_SUCCESS, session_url)); |
| 915 net::AppendQueryParameter(upload_url, "mode", "newfile"))); | |
| 916 return CancelCallback(); | 927 return CancelCallback(); |
| 917 } | 928 } |
| 918 | 929 |
| 919 CancelCallback FakeDriveService::InitiateUploadExistingFile( | 930 CancelCallback FakeDriveService::InitiateUploadExistingFile( |
| 920 const base::FilePath& drive_file_path, | 931 const base::FilePath& drive_file_path, |
| 921 const std::string& content_type, | 932 const std::string& content_type, |
| 922 int64 content_length, | 933 int64 content_length, |
| 923 const std::string& resource_id, | 934 const std::string& resource_id, |
| 924 const std::string& etag, | 935 const std::string& etag, |
| 925 const InitiateUploadCallback& callback) { | 936 const InitiateUploadCallback& callback) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 942 } | 953 } |
| 943 | 954 |
| 944 std::string entry_etag; | 955 std::string entry_etag; |
| 945 entry->GetString("gd$etag", &entry_etag); | 956 entry->GetString("gd$etag", &entry_etag); |
| 946 if (!etag.empty() && etag != entry_etag) { | 957 if (!etag.empty() && etag != entry_etag) { |
| 947 base::MessageLoop::current()->PostTask( | 958 base::MessageLoop::current()->PostTask( |
| 948 FROM_HERE, | 959 FROM_HERE, |
| 949 base::Bind(callback, HTTP_PRECONDITION, GURL())); | 960 base::Bind(callback, HTTP_PRECONDITION, GURL())); |
| 950 return CancelCallback(); | 961 return CancelCallback(); |
| 951 } | 962 } |
| 952 entry->SetString("docs$size.$t", "0"); | |
| 953 | 963 |
| 954 const GURL upload_url = GetUploadUrl(*entry); | 964 GURL session_url = net::AppendQueryParameter( |
| 955 DCHECK(upload_url.is_valid()); | 965 GetNewUploadSessionUrl(), "mode", "existing"); |
| 966 upload_session_[session_url] = | |
| 967 UploadSession(content_type, content_length, | |
| 968 "", // parent_resource_id | |
| 969 resource_id, | |
| 970 entry_etag, | |
| 971 "" /* title */); | |
| 956 | 972 |
| 957 base::MessageLoop::current()->PostTask( | 973 base::MessageLoop::current()->PostTask( |
| 958 FROM_HERE, | 974 FROM_HERE, |
| 959 base::Bind(callback, HTTP_SUCCESS, | 975 base::Bind(callback, HTTP_SUCCESS, session_url)); |
| 960 net::AppendQueryParameter(upload_url, "mode", "existing"))); | |
| 961 return CancelCallback(); | 976 return CancelCallback(); |
| 962 } | 977 } |
| 963 | 978 |
| 964 CancelCallback FakeDriveService::GetUploadStatus( | 979 CancelCallback FakeDriveService::GetUploadStatus( |
| 965 const base::FilePath& drive_file_path, | 980 const base::FilePath& drive_file_path, |
| 966 const GURL& upload_url, | 981 const GURL& upload_url, |
| 967 int64 content_length, | 982 int64 content_length, |
| 968 const UploadRangeCallback& callback) { | 983 const UploadRangeCallback& callback) { |
| 969 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 984 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 970 DCHECK(!callback.is_null()); | 985 DCHECK(!callback.is_null()); |
| 986 | |
| 987 if (!ContainsKey(upload_session_, upload_url)) { | |
|
hashimoto
2013/06/21 04:16:21
nit: Hmn, I didn't know that we had this function
tzik
2013/06/21 05:06:52
Changed this to count().
They are exactly same in
| |
| 988 base::MessageLoop::current()->PostTask( | |
| 989 FROM_HERE, | |
| 990 base::Bind(callback, UploadRangeResponse(HTTP_NOT_FOUND, 0, 0), | |
| 991 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 992 return CancelCallback(); | |
| 993 } | |
| 994 | |
| 995 const UploadSession& session = upload_session_[upload_url]; | |
| 996 if (session.uploaded_size == session.content_length) { | |
| 997 if (session.resource_id.empty()) { | |
| 998 base::MessageLoop::current()->PostTask( | |
| 999 FROM_HERE, | |
| 1000 base::Bind(callback, UploadRangeResponse(HTTP_CREATED, 0, 0), | |
| 1001 base::Passed(scoped_ptr<ResourceEntry>()))); | |
|
hashimoto
2013/06/21 04:16:21
Why are you returning null pointers even in succes
tzik
2013/06/21 05:06:52
IIUC, the server doesn't return resource entry for
tzik
2013/06/21 05:35:04
Done. I move this part of change to another CL.
| |
| 1002 return CancelCallback(); | |
| 1003 } | |
| 1004 | |
| 1005 base::MessageLoop::current()->PostTask( | |
| 1006 FROM_HERE, | |
| 1007 base::Bind(callback, UploadRangeResponse(HTTP_SUCCESS, 0, 0), | |
| 1008 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 1009 return CancelCallback(); | |
| 1010 } | |
| 1011 | |
| 1012 base::MessageLoop::current()->PostTask( | |
| 1013 FROM_HERE, | |
| 1014 base::Bind(callback, | |
| 1015 UploadRangeResponse(HTTP_RESUME_INCOMPLETE, | |
| 1016 0, session.uploaded_size), | |
| 1017 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 971 return CancelCallback(); | 1018 return CancelCallback(); |
| 972 } | 1019 } |
| 973 | 1020 |
| 974 CancelCallback FakeDriveService::ResumeUpload( | 1021 CancelCallback FakeDriveService::ResumeUpload( |
| 975 const base::FilePath& drive_file_path, | 1022 const base::FilePath& drive_file_path, |
| 976 const GURL& upload_url, | 1023 const GURL& upload_url, |
| 977 int64 start_position, | 1024 int64 start_position, |
| 978 int64 end_position, | 1025 int64 end_position, |
| 979 int64 content_length, | 1026 int64 content_length, |
| 980 const std::string& content_type, | 1027 const std::string& content_type, |
| 981 const base::FilePath& local_file_path, | 1028 const base::FilePath& local_file_path, |
| 982 const UploadRangeCallback& callback, | 1029 const UploadRangeCallback& callback, |
| 983 const ProgressCallback& progress_callback) { | 1030 const ProgressCallback& progress_callback) { |
| 984 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1031 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 985 DCHECK(!callback.is_null()); | 1032 DCHECK(!callback.is_null()); |
| 986 | 1033 |
| 987 scoped_ptr<ResourceEntry> result_entry; | |
| 988 | |
| 989 if (offline_) { | 1034 if (offline_) { |
| 990 base::MessageLoop::current()->PostTask( | 1035 base::MessageLoop::current()->PostTask( |
| 991 FROM_HERE, | 1036 FROM_HERE, |
| 992 base::Bind(callback, | 1037 base::Bind(callback, |
| 993 UploadRangeResponse(GDATA_NO_CONNECTION, | 1038 UploadRangeResponse(GDATA_NO_CONNECTION, |
| 994 start_position, | 1039 start_position, |
| 995 end_position), | 1040 end_position), |
| 996 base::Passed(&result_entry))); | 1041 base::Passed(scoped_ptr<ResourceEntry>()))); |
| 997 return CancelCallback(); | 1042 return CancelCallback(); |
| 998 } | 1043 } |
| 999 | 1044 |
| 1000 DictionaryValue* entry = NULL; | 1045 if (!ContainsKey(upload_session_, upload_url)) { |
| 1001 entry = FindEntryByUploadUrl(RemoveQueryParameter(upload_url)); | |
| 1002 if (!entry) { | |
| 1003 base::MessageLoop::current()->PostTask( | 1046 base::MessageLoop::current()->PostTask( |
| 1004 FROM_HERE, | 1047 FROM_HERE, |
| 1005 base::Bind(callback, | 1048 base::Bind(callback, |
| 1006 UploadRangeResponse(HTTP_NOT_FOUND, | 1049 UploadRangeResponse(HTTP_NOT_FOUND, |
| 1007 start_position, | 1050 start_position, |
| 1008 end_position), | 1051 end_position), |
| 1009 base::Passed(&result_entry))); | 1052 base::Passed(scoped_ptr<ResourceEntry>()))); |
| 1010 return CancelCallback(); | 1053 return CancelCallback(); |
| 1011 } | 1054 } |
| 1012 | 1055 |
| 1056 UploadSession* session = &upload_session_[upload_url]; | |
| 1057 | |
| 1013 // Chunks are required to be sent in such a ways that they fill from the start | 1058 // Chunks are required to be sent in such a ways that they fill from the start |
| 1014 // of the not-yet-uploaded part with no gaps nor overlaps. | 1059 // of the not-yet-uploaded part with no gaps nor overlaps. |
| 1015 std::string current_size_string; | 1060 int64 current_size = session->uploaded_size; |
|
hashimoto
2013/06/21 04:16:21
nit: Do we need this variable?
tzik
2013/06/21 05:06:52
Done.
| |
| 1016 int64 current_size; | 1061 if (current_size != start_position) { |
| 1017 if (!entry->GetString("docs$size.$t", ¤t_size_string) || | |
| 1018 !base::StringToInt64(current_size_string, ¤t_size) || | |
| 1019 current_size != start_position) { | |
| 1020 base::MessageLoop::current()->PostTask( | 1062 base::MessageLoop::current()->PostTask( |
| 1021 FROM_HERE, | 1063 FROM_HERE, |
| 1022 base::Bind(callback, | 1064 base::Bind(callback, |
| 1023 UploadRangeResponse(HTTP_BAD_REQUEST, | 1065 UploadRangeResponse(HTTP_BAD_REQUEST, |
| 1024 start_position, | 1066 start_position, |
| 1025 end_position), | 1067 end_position), |
| 1026 base::Passed(&result_entry))); | 1068 base::Passed(scoped_ptr<ResourceEntry>()))); |
| 1027 return CancelCallback(); | 1069 return CancelCallback(); |
| 1028 } | 1070 } |
| 1029 | 1071 |
| 1030 entry->SetString("docs$size.$t", base::Int64ToString(end_position)); | |
| 1031 | |
| 1032 if (!progress_callback.is_null()) { | 1072 if (!progress_callback.is_null()) { |
| 1033 // In the real GDataWapi/Drive DriveService, progress is reported in | 1073 // In the real GDataWapi/Drive DriveService, progress is reported in |
| 1034 // nondeterministic timing. In this fake implementation, we choose to call | 1074 // nondeterministic timing. In this fake implementation, we choose to call |
| 1035 // it twice per one ResumeUpload. This is for making sure that client code | 1075 // it twice per one ResumeUpload. This is for making sure that client code |
| 1036 // works fine even if the callback is invoked more than once; it is the | 1076 // works fine even if the callback is invoked more than once; it is the |
| 1037 // crucial difference of the progress callback from others. | 1077 // crucial difference of the progress callback from others. |
| 1038 // Note that progress is notified in the relative offset in each chunk. | 1078 // Note that progress is notified in the relative offset in each chunk. |
| 1039 const int64 chunk_size = end_position - start_position; | 1079 const int64 chunk_size = end_position - start_position; |
| 1040 base::MessageLoop::current()->PostTask( | 1080 base::MessageLoop::current()->PostTask( |
| 1041 FROM_HERE, base::Bind(progress_callback, chunk_size / 2, chunk_size)); | 1081 FROM_HERE, base::Bind(progress_callback, chunk_size / 2, chunk_size)); |
| 1042 base::MessageLoop::current()->PostTask( | 1082 base::MessageLoop::current()->PostTask( |
| 1043 FROM_HERE, base::Bind(progress_callback, chunk_size, chunk_size)); | 1083 FROM_HERE, base::Bind(progress_callback, chunk_size, chunk_size)); |
| 1044 } | 1084 } |
| 1045 | 1085 |
| 1046 if (content_length != end_position) { | 1086 if (content_length != end_position) { |
| 1087 session->uploaded_size = end_position; | |
| 1047 base::MessageLoop::current()->PostTask( | 1088 base::MessageLoop::current()->PostTask( |
| 1048 FROM_HERE, | 1089 FROM_HERE, |
| 1049 base::Bind(callback, | 1090 base::Bind(callback, |
| 1050 UploadRangeResponse(HTTP_RESUME_INCOMPLETE, | 1091 UploadRangeResponse(HTTP_RESUME_INCOMPLETE, |
| 1051 start_position, | 1092 start_position, |
| 1052 end_position), | 1093 end_position), |
| 1053 base::Passed(&result_entry))); | 1094 base::Passed(scoped_ptr<ResourceEntry>()))); |
| 1054 return CancelCallback(); | 1095 return CancelCallback(); |
| 1055 } | 1096 } |
| 1056 | 1097 |
| 1098 std::string content_data; | |
| 1099 if (!file_util::ReadFileToString(local_file_path, &content_data)) { | |
| 1100 base::MessageLoop::current()->PostTask( | |
| 1101 FROM_HERE, | |
| 1102 base::Bind(callback, | |
| 1103 UploadRangeResponse(GDATA_FILE_ERROR, | |
| 1104 start_position, | |
| 1105 end_position), | |
| 1106 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 1107 return CancelCallback(); | |
| 1108 } | |
| 1109 session->uploaded_size = end_position; | |
| 1110 | |
| 1111 if (session->resource_id.empty()) { | |
|
hashimoto
2013/06/21 04:16:21
resource_id.empty() is true iff the upload is for
tzik
2013/06/21 05:06:52
Done.
| |
| 1112 const DictionaryValue* new_entry = AddNewEntry( | |
| 1113 session->content_type, | |
| 1114 content_data, | |
| 1115 session->parent_resource_id, | |
| 1116 session->title, | |
| 1117 false, // shared_with_me | |
| 1118 "file"); | |
| 1119 if (!new_entry) { | |
| 1120 base::MessageLoop::current()->PostTask( | |
| 1121 FROM_HERE, | |
| 1122 base::Bind(callback, | |
| 1123 UploadRangeResponse(HTTP_NOT_FOUND, | |
| 1124 start_position, | |
| 1125 end_position), | |
| 1126 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 1127 return CancelCallback(); | |
| 1128 } | |
| 1129 | |
| 1130 base::MessageLoop::current()->PostTask( | |
| 1131 FROM_HERE, | |
| 1132 base::Bind(callback, | |
| 1133 UploadRangeResponse(HTTP_CREATED, | |
| 1134 start_position, | |
| 1135 end_position), | |
| 1136 base::Passed(ResourceEntry::CreateFrom(*new_entry)))); | |
| 1137 return CancelCallback(); | |
| 1138 } | |
| 1139 | |
| 1140 DictionaryValue* entry = FindEntryByResourceId(session->resource_id); | |
| 1141 if (!entry) { | |
| 1142 base::MessageLoop::current()->PostTask( | |
| 1143 FROM_HERE, | |
| 1144 base::Bind(callback, | |
| 1145 UploadRangeResponse(HTTP_NOT_FOUND, | |
| 1146 start_position, | |
| 1147 end_position), | |
| 1148 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 1149 return CancelCallback(); | |
| 1150 } | |
| 1151 | |
| 1152 std::string entry_etag; | |
| 1153 entry->GetString("gd$etag", &entry_etag); | |
| 1154 if (entry_etag.empty() || session->etag != entry_etag) { | |
| 1155 base::MessageLoop::current()->PostTask( | |
| 1156 FROM_HERE, | |
| 1157 base::Bind(callback, | |
| 1158 UploadRangeResponse(HTTP_PRECONDITION, | |
| 1159 start_position, | |
| 1160 end_position), | |
| 1161 base::Passed(scoped_ptr<ResourceEntry>()))); | |
| 1162 return CancelCallback(); | |
| 1163 } | |
| 1164 | |
| 1165 entry->SetString("docs$md5Checksum.$t", base::MD5String(content_data)); | |
| 1166 entry->Set("test$data", | |
| 1167 base::BinaryValue::CreateWithCopiedBuffer( | |
| 1168 content_data.data(), content_data.size())); | |
| 1169 entry->SetString("docs$size.$t", base::Int64ToString(end_position)); | |
| 1057 AddNewChangestamp(entry); | 1170 AddNewChangestamp(entry); |
| 1058 result_entry = ResourceEntry::CreateFrom(*entry).Pass(); | |
| 1059 | |
| 1060 std::string upload_mode; | |
| 1061 bool upload_mode_found = | |
| 1062 net::GetValueForKeyInQuery(upload_url, "mode", &upload_mode); | |
| 1063 DCHECK(upload_mode_found && | |
| 1064 (upload_mode == "newfile" || upload_mode == "existing")); | |
| 1065 | |
| 1066 GDataErrorCode return_code = | |
| 1067 upload_mode == "newfile" ? HTTP_CREATED : HTTP_SUCCESS; | |
| 1068 | 1171 |
| 1069 base::MessageLoop::current()->PostTask( | 1172 base::MessageLoop::current()->PostTask( |
| 1070 FROM_HERE, | 1173 FROM_HERE, |
| 1071 base::Bind(callback, | 1174 base::Bind(callback, |
| 1072 UploadRangeResponse(return_code, | 1175 UploadRangeResponse(HTTP_SUCCESS, |
|
hashimoto
2013/06/21 04:16:21
Please return HTTP_CREATED for new files.
tzik
2013/06/21 05:06:52
Uploads for new file are handled around 1111, so t
hashimoto
2013/06/21 05:41:24
You're right, thanks.
| |
| 1073 start_position, | 1176 start_position, |
| 1074 end_position), | 1177 end_position), |
| 1075 base::Passed(&result_entry))); | 1178 base::Passed(ResourceEntry::CreateFrom(*entry)))); |
| 1076 return CancelCallback(); | 1179 return CancelCallback(); |
| 1077 } | 1180 } |
| 1078 | 1181 |
| 1079 CancelCallback FakeDriveService::AuthorizeApp( | 1182 CancelCallback FakeDriveService::AuthorizeApp( |
| 1080 const std::string& resource_id, | 1183 const std::string& resource_id, |
| 1081 const std::string& app_id, | 1184 const std::string& app_id, |
| 1082 const AuthorizeAppCallback& callback) { | 1185 const AuthorizeAppCallback& callback) { |
| 1083 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1084 DCHECK(!callback.is_null()); | 1187 DCHECK(!callback.is_null()); |
| 1085 return CancelCallback(); | 1188 return CancelCallback(); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1207 entry->GetString("content.src", ¤t_content_url) && | 1310 entry->GetString("content.src", ¤t_content_url) && |
| 1208 content_url == GURL(current_content_url)) { | 1311 content_url == GURL(current_content_url)) { |
| 1209 return entry; | 1312 return entry; |
| 1210 } | 1313 } |
| 1211 } | 1314 } |
| 1212 } | 1315 } |
| 1213 | 1316 |
| 1214 return NULL; | 1317 return NULL; |
| 1215 } | 1318 } |
| 1216 | 1319 |
| 1217 base::DictionaryValue* FakeDriveService::FindEntryByUploadUrl( | |
| 1218 const GURL& upload_url) { | |
| 1219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1220 | |
| 1221 base::ListValue* entries = NULL; | |
| 1222 // Go through entries and return the one that matches |upload_url|. | |
| 1223 if (resource_list_value_->GetList("entry", &entries)) { | |
| 1224 for (size_t i = 0; i < entries->GetSize(); ++i) { | |
| 1225 base::DictionaryValue* entry = NULL; | |
| 1226 base::ListValue* links = NULL; | |
| 1227 if (entries->GetDictionary(i, &entry) && | |
| 1228 entry->GetList("link", &links) && | |
| 1229 links) { | |
| 1230 for (size_t link_index = 0; | |
| 1231 link_index < links->GetSize(); | |
| 1232 ++link_index) { | |
| 1233 base::DictionaryValue* link = NULL; | |
| 1234 std::string rel; | |
| 1235 std::string found_upload_url; | |
| 1236 if (links->GetDictionary(link_index, &link) && | |
| 1237 link && link->GetString("rel", &rel) && | |
| 1238 rel == kUploadUrlRel && | |
| 1239 link->GetString("href", &found_upload_url) && | |
| 1240 GURL(found_upload_url) == upload_url) { | |
| 1241 return entry; | |
| 1242 } | |
| 1243 } | |
| 1244 } | |
| 1245 } | |
| 1246 } | |
| 1247 | |
| 1248 return NULL; | |
| 1249 } | |
| 1250 | |
| 1251 std::string FakeDriveService::GetNewResourceId() { | 1320 std::string FakeDriveService::GetNewResourceId() { |
| 1252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1253 | 1322 |
| 1254 ++resource_id_count_; | 1323 ++resource_id_count_; |
| 1255 return base::StringPrintf("resource_id_%d", resource_id_count_); | 1324 return base::StringPrintf("resource_id_%d", resource_id_count_); |
| 1256 } | 1325 } |
| 1257 | 1326 |
| 1258 void FakeDriveService::AddNewChangestamp(base::DictionaryValue* entry) { | 1327 void FakeDriveService::AddNewChangestamp(base::DictionaryValue* entry) { |
|
hashimoto
2013/06/21 04:16:21
How about renaming this method to something like A
tzik
2013/06/21 05:06:52
Done.
| |
| 1259 ++largest_changestamp_; | 1328 ++largest_changestamp_; |
| 1260 entry->SetString("docs$changestamp.value", | 1329 entry->SetString("docs$changestamp.value", |
| 1261 base::Int64ToString(largest_changestamp_)); | 1330 base::Int64ToString(largest_changestamp_)); |
| 1331 entry->SetString("gd$etag", | |
| 1332 "etag_" + base::Int64ToString(largest_changestamp_)); | |
| 1262 } | 1333 } |
| 1263 | 1334 |
| 1264 const base::DictionaryValue* FakeDriveService::AddNewEntry( | 1335 const base::DictionaryValue* FakeDriveService::AddNewEntry( |
| 1265 const std::string& content_type, | 1336 const std::string& content_type, |
| 1266 const std::string& content_data, | 1337 const std::string& content_data, |
| 1267 const std::string& parent_resource_id, | 1338 const std::string& parent_resource_id, |
| 1268 const std::string& title, | 1339 const std::string& title, |
| 1269 bool shared_with_me, | 1340 bool shared_with_me, |
| 1270 const std::string& entry_kind) { | 1341 const std::string& entry_kind) { |
| 1271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1283 new_entry->SetString("gd$resourceId.$t", resource_id); | 1354 new_entry->SetString("gd$resourceId.$t", resource_id); |
| 1284 new_entry->SetString("title.$t", title); | 1355 new_entry->SetString("title.$t", title); |
| 1285 new_entry->SetString("docs$filename", title); | 1356 new_entry->SetString("docs$filename", title); |
| 1286 // Set the contents, size and MD5 for a file. | 1357 // Set the contents, size and MD5 for a file. |
| 1287 if (entry_kind == "file") { | 1358 if (entry_kind == "file") { |
| 1288 new_entry->Set("test$data", | 1359 new_entry->Set("test$data", |
| 1289 base::BinaryValue::CreateWithCopiedBuffer( | 1360 base::BinaryValue::CreateWithCopiedBuffer( |
| 1290 content_data.c_str(), content_data.size())); | 1361 content_data.c_str(), content_data.size())); |
| 1291 new_entry->SetString("docs$size.$t", | 1362 new_entry->SetString("docs$size.$t", |
| 1292 base::Int64ToString(content_data.size())); | 1363 base::Int64ToString(content_data.size())); |
| 1293 // TODO(satorux): Set the correct MD5 here. | |
| 1294 new_entry->SetString("docs$md5Checksum.$t", | 1364 new_entry->SetString("docs$md5Checksum.$t", |
| 1295 "3b4385ebefec6e743574c76bbd0575de"); | 1365 base::MD5String(content_data)); |
| 1296 } | 1366 } |
| 1297 | 1367 |
| 1298 // Add "category" which sets the resource type to |entry_kind|. | 1368 // Add "category" which sets the resource type to |entry_kind|. |
| 1299 base::ListValue* categories = new base::ListValue; | 1369 base::ListValue* categories = new base::ListValue; |
| 1300 base::DictionaryValue* category = new base::DictionaryValue; | 1370 base::DictionaryValue* category = new base::DictionaryValue; |
| 1301 category->SetString("scheme", "http://schemas.google.com/g/2005#kind"); | 1371 category->SetString("scheme", "http://schemas.google.com/g/2005#kind"); |
| 1302 category->SetString("term", "http://schemas.google.com/docs/2007#" + | 1372 category->SetString("term", "http://schemas.google.com/docs/2007#" + |
| 1303 entry_kind); | 1373 entry_kind); |
| 1304 categories->Append(category); | 1374 categories->Append(category); |
| 1305 new_entry->Set("category", categories); | 1375 new_entry->Set("category", categories); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1470 | 1540 |
| 1471 if (load_counter) | 1541 if (load_counter) |
| 1472 *load_counter += 1; | 1542 *load_counter += 1; |
| 1473 base::MessageLoop::current()->PostTask( | 1543 base::MessageLoop::current()->PostTask( |
| 1474 FROM_HERE, | 1544 FROM_HERE, |
| 1475 base::Bind(callback, | 1545 base::Bind(callback, |
| 1476 HTTP_SUCCESS, | 1546 HTTP_SUCCESS, |
| 1477 base::Passed(&resource_list))); | 1547 base::Passed(&resource_list))); |
| 1478 } | 1548 } |
| 1479 | 1549 |
| 1550 GURL FakeDriveService::GetNewUploadSessionUrl() { | |
| 1551 return GURL("https://upload_session_url/" + | |
| 1552 base::Int64ToString(next_upload_sequence_number_++)); | |
| 1553 } | |
| 1554 | |
| 1480 } // namespace drive | 1555 } // namespace drive |
| OLD | NEW |