Give names to all utility processes.
[chromium-blink-merge.git] / chrome / browser / drive / drive_api_util.cc
blob8dc64623c49faad2347f4d4fb0739ed5024e1177
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
3 // found in the LICENSE file.
5 #include "chrome/browser/drive/drive_api_util.h"
7 #include <string>
9 #include "base/files/file.h"
10 #include "base/logging.h"
11 #include "base/md5.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "google_apis/drive/drive_api_parser.h"
18 #include "net/base/escape.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/net_errors.h"
21 #include "storage/browser/fileapi/file_stream_reader.h"
22 #include "third_party/re2/re2/re2.h"
23 #include "url/gurl.h"
25 namespace drive {
26 namespace util {
27 namespace {
29 struct HostedDocumentKind {
30 const char* mime_type;
31 const char* extension;
34 const HostedDocumentKind kHostedDocumentKinds[] = {
35 {kGoogleDocumentMimeType, ".gdoc"},
36 {kGoogleSpreadsheetMimeType, ".gsheet"},
37 {kGooglePresentationMimeType, ".gslides"},
38 {kGoogleDrawingMimeType, ".gdraw"},
39 {kGoogleTableMimeType, ".gtable"},
40 {kGoogleFormMimeType, ".gform"},
41 {kGoogleMapMimeType, ".gmaps"},
44 const char kUnknownHostedDocumentExtension[] = ".glink";
46 const int kMd5DigestBufferSize = 512 * 1024; // 512 kB.
48 } // namespace
50 std::string EscapeQueryStringValue(const std::string& str) {
51 std::string result;
52 result.reserve(str.size());
53 for (size_t i = 0; i < str.size(); ++i) {
54 if (str[i] == '\\' || str[i] == '\'') {
55 result.push_back('\\');
57 result.push_back(str[i]);
59 return result;
62 std::string TranslateQuery(const std::string& original_query) {
63 // In order to handle non-ascii white spaces correctly, convert to UTF16.
64 base::string16 query = base::UTF8ToUTF16(original_query);
65 const base::string16 kDelimiter(
66 base::kWhitespaceUTF16 + base::ASCIIToUTF16("\""));
68 std::string result;
69 for (size_t index = query.find_first_not_of(base::kWhitespaceUTF16);
70 index != base::string16::npos;
71 index = query.find_first_not_of(base::kWhitespaceUTF16, index)) {
72 bool is_exclusion = (query[index] == '-');
73 if (is_exclusion)
74 ++index;
75 if (index == query.length()) {
76 // Here, the token is '-' and it should be ignored.
77 continue;
80 size_t begin_token = index;
81 base::string16 token;
82 if (query[begin_token] == '"') {
83 // Quoted query.
84 ++begin_token;
85 size_t end_token = query.find('"', begin_token);
86 if (end_token == base::string16::npos) {
87 // This is kind of syntax error, since quoted string isn't finished.
88 // However, the query is built by user manually, so here we treat
89 // whole remaining string as a token as a fallback, by appending
90 // a missing double-quote character.
91 end_token = query.length();
92 query.push_back('"');
95 token = query.substr(begin_token, end_token - begin_token);
96 index = end_token + 1; // Consume last '"', too.
97 } else {
98 size_t end_token = query.find_first_of(kDelimiter, begin_token);
99 if (end_token == base::string16::npos) {
100 end_token = query.length();
103 token = query.substr(begin_token, end_token - begin_token);
104 index = end_token;
107 if (token.empty()) {
108 // Just ignore an empty token.
109 continue;
112 if (!result.empty()) {
113 // If there are two or more tokens, need to connect with "and".
114 result.append(" and ");
117 // The meaning of "fullText" should include title, description and content.
118 base::StringAppendF(
119 &result,
120 "%sfullText contains \'%s\'",
121 is_exclusion ? "not " : "",
122 EscapeQueryStringValue(base::UTF16ToUTF8(token)).c_str());
125 return result;
128 std::string CanonicalizeResourceId(const std::string& resource_id) {
129 // If resource ID is in the old WAPI format starting with a prefix like
130 // "document:", strip it and return the remaining part.
131 std::string stripped_resource_id;
132 if (RE2::FullMatch(resource_id, "^[a-z-]+(?::|%3A)([\\w-]+)$",
133 &stripped_resource_id))
134 return stripped_resource_id;
135 return resource_id;
138 std::string GetMd5Digest(const base::FilePath& file_path) {
139 base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
140 if (!file.IsValid())
141 return std::string();
143 base::MD5Context context;
144 base::MD5Init(&context);
146 int64 offset = 0;
147 scoped_ptr<char[]> buffer(new char[kMd5DigestBufferSize]);
148 while (true) {
149 int result = file.Read(offset, buffer.get(), kMd5DigestBufferSize);
150 if (result < 0) {
151 // Found an error.
152 return std::string();
155 if (result == 0) {
156 // End of file.
157 break;
160 offset += result;
161 base::MD5Update(&context, base::StringPiece(buffer.get(), result));
164 base::MD5Digest digest;
165 base::MD5Final(&digest, &context);
166 return MD5DigestToBase16(digest);
169 FileStreamMd5Digester::FileStreamMd5Digester()
170 : buffer_(new net::IOBuffer(kMd5DigestBufferSize)) {
173 FileStreamMd5Digester::~FileStreamMd5Digester() {
176 void FileStreamMd5Digester::GetMd5Digest(
177 scoped_ptr<storage::FileStreamReader> stream_reader,
178 const ResultCallback& callback) {
179 reader_ = stream_reader.Pass();
180 base::MD5Init(&md5_context_);
182 // Start the read/hash.
183 ReadNextChunk(callback);
186 void FileStreamMd5Digester::ReadNextChunk(const ResultCallback& callback) {
187 const int result =
188 reader_->Read(buffer_.get(), kMd5DigestBufferSize,
189 base::Bind(&FileStreamMd5Digester::OnChunkRead,
190 base::Unretained(this), callback));
191 if (result != net::ERR_IO_PENDING)
192 OnChunkRead(callback, result);
195 void FileStreamMd5Digester::OnChunkRead(const ResultCallback& callback,
196 int bytes_read) {
197 if (bytes_read < 0) {
198 // Error - just return empty string.
199 callback.Run("");
200 return;
201 } else if (bytes_read == 0) {
202 // EOF.
203 base::MD5Digest digest;
204 base::MD5Final(&digest, &md5_context_);
205 std::string result = MD5DigestToBase16(digest);
206 callback.Run(result);
207 return;
210 // Read data and digest it.
211 base::MD5Update(&md5_context_,
212 base::StringPiece(buffer_->data(), bytes_read));
214 // Kick off the next read.
215 ReadNextChunk(callback);
218 std::string GetHostedDocumentExtension(const std::string& mime_type) {
219 for (size_t i = 0; i < arraysize(kHostedDocumentKinds); ++i) {
220 if (mime_type == kHostedDocumentKinds[i].mime_type)
221 return kHostedDocumentKinds[i].extension;
223 return kUnknownHostedDocumentExtension;
226 bool IsKnownHostedDocumentMimeType(const std::string& mime_type) {
227 for (size_t i = 0; i < arraysize(kHostedDocumentKinds); ++i) {
228 if (mime_type == kHostedDocumentKinds[i].mime_type)
229 return true;
231 return false;
234 bool HasHostedDocumentExtension(const base::FilePath& path) {
235 const std::string extension = base::FilePath(path.Extension()).AsUTF8Unsafe();
236 for (size_t i = 0; i < arraysize(kHostedDocumentKinds); ++i) {
237 if (extension == kHostedDocumentKinds[i].extension)
238 return true;
240 return extension == kUnknownHostedDocumentExtension;
243 } // namespace util
244 } // namespace drive