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.
4
5 #include "google_apis/drive/drive_api_url_generator.h"
6
7 #include "base/check_op.h"
8 #include "base/command_line.h"
9 #include "base/notreached.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "google_apis/google_api_keys.h"
13 #include "net/base/escape.h"
14 #include "net/base/url_util.h"
15
16 namespace google_apis {
17
18 namespace {
19
20 // Hard coded URLs for communication with a google drive server.
21 // TODO(yamaguchi): Make a utility function to compose some of these URLs by a
22 // version and a resource name.
23 const char kDriveV2AboutUrl[] = "drive/v2/about";
24 const char kDriveV2ChangelistUrl[] = "drive/v2/changes";
25 const char kDriveV2StartPageTokenUrl[] = "drive/v2/changes/startPageToken";
26 const char kDriveV2FilesUrl[] = "drive/v2/files";
27 const char kDriveV2FileUrlPrefix[] = "drive/v2/files/";
28 const char kDriveV2ChildrenUrlFormat[] = "drive/v2/files/%s/children";
29 const char kDriveV2ChildrenUrlForRemovalFormat[] =
30 "drive/v2/files/%s/children/%s";
31 const char kDriveV2FileCopyUrlFormat[] = "drive/v2/files/%s/copy";
32 const char kDriveV2FileDeleteUrlFormat[] = "drive/v2/files/%s";
33 const char kDriveV2FileTrashUrlFormat[] = "drive/v2/files/%s/trash";
34 const char kDriveV2UploadNewFileUrl[] = "upload/drive/v2/files";
35 const char kDriveV2UploadExistingFileUrlPrefix[] = "upload/drive/v2/files/";
36 const char kDriveV2BatchUploadUrl[] = "upload/drive";
37 const char kDriveV2PermissionsUrlFormat[] = "drive/v2/files/%s/permissions";
38 const char kDriveV2DownloadUrlFormat[] = "drive/v2/files/%s?alt=media";
39 const char kDriveV2ThumbnailUrlFormat[] = "d/%s=w%d-h%d";
40 const char kDriveV2ThumbnailUrlWithCropFormat[] = "d/%s=w%d-h%d-c";
41 const char kDriveV2TeamDrivesUrl[] = "drive/v2/teamdrives";
42
43 const char kIncludeTeamDriveItems[] = "includeTeamDriveItems";
44 const char kSupportsTeamDrives[] = "supportsTeamDrives";
45 const char kCorpora[] = "corpora";
46 const char kCorporaAllTeamDrives[] = "default,allTeamDrives";
47 const char kCorporaDefault[] = "default";
48 const char kCorporaTeamDrive[] = "teamDrive";
49 const char kTeamDriveId[] = "teamDriveId";
50
AddResumableUploadParam(const GURL & url)51 GURL AddResumableUploadParam(const GURL& url) {
52 return net::AppendOrReplaceQueryParameter(url, "uploadType", "resumable");
53 }
54
AddMultipartUploadParam(const GURL & url)55 GURL AddMultipartUploadParam(const GURL& url) {
56 return net::AppendOrReplaceQueryParameter(url, "uploadType", "multipart");
57 }
58
GetCorporaString(FilesListCorpora corpora)59 const char* GetCorporaString(FilesListCorpora corpora) {
60 switch (corpora) {
61 case FilesListCorpora::DEFAULT:
62 return kCorporaDefault;
63 case FilesListCorpora::TEAM_DRIVE:
64 return kCorporaTeamDrive;
65 case FilesListCorpora::ALL_TEAM_DRIVES:
66 return kCorporaAllTeamDrives;
67 }
68 NOTREACHED();
69 return kCorporaDefault;
70 }
71
72 } // namespace
73
DriveApiUrlGenerator(const GURL & base_url,const GURL & base_thumbnail_url)74 DriveApiUrlGenerator::DriveApiUrlGenerator(const GURL& base_url,
75 const GURL& base_thumbnail_url)
76 : base_url_(base_url), base_thumbnail_url_(base_thumbnail_url) {
77 // Do nothing.
78 }
79
80 DriveApiUrlGenerator::DriveApiUrlGenerator(const DriveApiUrlGenerator& src) =
81 default;
82
~DriveApiUrlGenerator()83 DriveApiUrlGenerator::~DriveApiUrlGenerator() {
84 // Do nothing.
85 }
86
87 const char DriveApiUrlGenerator::kBaseUrlForProduction[] =
88 "https://www.googleapis.com";
89
90 const char DriveApiUrlGenerator::kBaseThumbnailUrlForProduction[] =
91 "https://lh3.googleusercontent.com";
92
GetAboutGetUrl() const93 GURL DriveApiUrlGenerator::GetAboutGetUrl() const {
94 return base_url_.Resolve(kDriveV2AboutUrl);
95 }
96
GetFilesGetUrl(const std::string & file_id,const GURL & embed_origin) const97 GURL DriveApiUrlGenerator::GetFilesGetUrl(const std::string& file_id,
98 const GURL& embed_origin) const {
99 GURL url =
100 base_url_.Resolve(kDriveV2FileUrlPrefix + net::EscapePath(file_id));
101 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
102
103 if (!embed_origin.is_empty()) {
104 // Construct a valid serialized embed origin from an url, according to
105 // WD-html5-20110525. Such string has to be built manually, since
106 // GURL::spec() always adds the trailing slash. Moreover, ports are
107 // currently not supported.
108 DCHECK(!embed_origin.has_port());
109 DCHECK(!embed_origin.has_path() || embed_origin.path() == "/");
110 const std::string serialized_embed_origin =
111 embed_origin.scheme() + "://" + embed_origin.host();
112 url = net::AppendOrReplaceQueryParameter(
113 url, "embedOrigin", serialized_embed_origin);
114 }
115 return url;
116 }
117
GetFilesInsertUrl(const std::string & visibility) const118 GURL DriveApiUrlGenerator::GetFilesInsertUrl(
119 const std::string& visibility) const {
120 GURL url = base_url_.Resolve(kDriveV2FilesUrl);
121
122 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
123 if (!visibility.empty())
124 url = net::AppendOrReplaceQueryParameter(url, "visibility", visibility);
125
126 return url;
127 }
128
GetFilesPatchUrl(const std::string & file_id,bool set_modified_date,bool update_viewed_date) const129 GURL DriveApiUrlGenerator::GetFilesPatchUrl(const std::string& file_id,
130 bool set_modified_date,
131 bool update_viewed_date) const {
132 GURL url =
133 base_url_.Resolve(kDriveV2FileUrlPrefix + net::EscapePath(file_id));
134
135 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
136 // setModifiedDate is "false" by default.
137 if (set_modified_date)
138 url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
139
140 // updateViewedDate is "true" by default.
141 if (!update_viewed_date)
142 url = net::AppendOrReplaceQueryParameter(url, "updateViewedDate", "false");
143
144 return url;
145 }
146
GetFilesCopyUrl(const std::string & file_id,const std::string & visibility) const147 GURL DriveApiUrlGenerator::GetFilesCopyUrl(
148 const std::string& file_id,
149 const std::string& visibility) const {
150 GURL url = base_url_.Resolve(base::StringPrintf(
151 kDriveV2FileCopyUrlFormat, net::EscapePath(file_id).c_str()));
152
153 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
154 if (!visibility.empty())
155 url = net::AppendOrReplaceQueryParameter(url, "visibility", visibility);
156
157 return url;
158 }
159
GetFilesListUrl(int max_results,const std::string & page_token,FilesListCorpora corpora,const std::string & team_drive_id,const std::string & q) const160 GURL DriveApiUrlGenerator::GetFilesListUrl(int max_results,
161 const std::string& page_token,
162 FilesListCorpora corpora,
163 const std::string& team_drive_id,
164 const std::string& q) const {
165 GURL url = base_url_.Resolve(kDriveV2FilesUrl);
166 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
167 url = net::AppendOrReplaceQueryParameter(url, kIncludeTeamDriveItems, "true");
168 url = net::AppendOrReplaceQueryParameter(url, kCorpora,
169 GetCorporaString(corpora));
170 if (!team_drive_id.empty())
171 url = net::AppendOrReplaceQueryParameter(url, kTeamDriveId, team_drive_id);
172 // maxResults is 100 by default.
173 if (max_results != 100) {
174 url = net::AppendOrReplaceQueryParameter(url, "maxResults",
175 base::NumberToString(max_results));
176 }
177
178 if (!page_token.empty())
179 url = net::AppendOrReplaceQueryParameter(url, "pageToken", page_token);
180
181 if (!q.empty())
182 url = net::AppendOrReplaceQueryParameter(url, "q", q);
183
184 return url;
185 }
186
GetFilesDeleteUrl(const std::string & file_id) const187 GURL DriveApiUrlGenerator::GetFilesDeleteUrl(const std::string& file_id) const {
188 GURL url = base_url_.Resolve(base::StringPrintf(
189 kDriveV2FileDeleteUrlFormat, net::EscapePath(file_id).c_str()));
190 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
191 return url;
192 }
193
GetFilesTrashUrl(const std::string & file_id) const194 GURL DriveApiUrlGenerator::GetFilesTrashUrl(const std::string& file_id) const {
195 GURL url = base_url_.Resolve(base::StringPrintf(
196 kDriveV2FileTrashUrlFormat, net::EscapePath(file_id).c_str()));
197 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
198 return url;
199 }
200
GetChangesListUrl(bool include_deleted,int max_results,const std::string & page_token,int64_t start_change_id,const std::string & team_drive_id) const201 GURL DriveApiUrlGenerator::GetChangesListUrl(
202 bool include_deleted,
203 int max_results,
204 const std::string& page_token,
205 int64_t start_change_id,
206 const std::string& team_drive_id) const {
207 DCHECK_GE(start_change_id, 0);
208
209 GURL url = base_url_.Resolve(kDriveV2ChangelistUrl);
210 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
211 url = net::AppendOrReplaceQueryParameter(url, kIncludeTeamDriveItems, "true");
212 if (!team_drive_id.empty()) {
213 url = net::AppendOrReplaceQueryParameter(url, kTeamDriveId, team_drive_id);
214 }
215 // includeDeleted is "true" by default.
216 if (!include_deleted)
217 url = net::AppendOrReplaceQueryParameter(url, "includeDeleted", "false");
218
219 // maxResults is "100" by default.
220 if (max_results != 100) {
221 url = net::AppendOrReplaceQueryParameter(url, "maxResults",
222 base::NumberToString(max_results));
223 }
224
225 if (!page_token.empty())
226 url = net::AppendOrReplaceQueryParameter(url, "pageToken", page_token);
227
228 if (start_change_id > 0)
229 url = net::AppendOrReplaceQueryParameter(
230 url, "startChangeId", base::NumberToString(start_change_id));
231
232 return url;
233 }
234
GetChildrenInsertUrl(const std::string & file_id) const235 GURL DriveApiUrlGenerator::GetChildrenInsertUrl(
236 const std::string& file_id) const {
237 GURL url = base_url_.Resolve(base::StringPrintf(
238 kDriveV2ChildrenUrlFormat, net::EscapePath(file_id).c_str()));
239 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
240 return url;
241 }
242
GetChildrenDeleteUrl(const std::string & child_id,const std::string & folder_id) const243 GURL DriveApiUrlGenerator::GetChildrenDeleteUrl(
244 const std::string& child_id, const std::string& folder_id) const {
245 return base_url_.Resolve(
246 base::StringPrintf(kDriveV2ChildrenUrlForRemovalFormat,
247 net::EscapePath(folder_id).c_str(),
248 net::EscapePath(child_id).c_str()));
249 }
250
GetInitiateUploadNewFileUrl(bool set_modified_date) const251 GURL DriveApiUrlGenerator::GetInitiateUploadNewFileUrl(
252 bool set_modified_date) const {
253 GURL url = AddResumableUploadParam(
254 base_url_.Resolve(kDriveV2UploadNewFileUrl));
255
256 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
257 // setModifiedDate is "false" by default.
258 if (set_modified_date)
259 url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
260
261 return url;
262 }
263
GetInitiateUploadExistingFileUrl(const std::string & resource_id,bool set_modified_date) const264 GURL DriveApiUrlGenerator::GetInitiateUploadExistingFileUrl(
265 const std::string& resource_id,
266 bool set_modified_date) const {
267 GURL url = base_url_.Resolve(
268 kDriveV2UploadExistingFileUrlPrefix +
269 net::EscapePath(resource_id));
270 url = AddResumableUploadParam(url);
271
272 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
273 // setModifiedDate is "false" by default.
274 if (set_modified_date)
275 url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
276
277 return url;
278 }
279
GetMultipartUploadNewFileUrl(bool set_modified_date) const280 GURL DriveApiUrlGenerator::GetMultipartUploadNewFileUrl(
281 bool set_modified_date) const {
282 GURL url = AddMultipartUploadParam(
283 base_url_.Resolve(kDriveV2UploadNewFileUrl));
284
285 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
286 // setModifiedDate is "false" by default.
287 if (set_modified_date)
288 url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
289
290 return url;
291 }
292
GetMultipartUploadExistingFileUrl(const std::string & resource_id,bool set_modified_date) const293 GURL DriveApiUrlGenerator::GetMultipartUploadExistingFileUrl(
294 const std::string& resource_id,
295 bool set_modified_date) const {
296 GURL url = base_url_.Resolve(
297 kDriveV2UploadExistingFileUrlPrefix +
298 net::EscapePath(resource_id));
299 url = AddMultipartUploadParam(url);
300
301 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
302 // setModifiedDate is "false" by default.
303 if (set_modified_date)
304 url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
305
306 return url;
307 }
308
GenerateDownloadFileUrl(const std::string & resource_id) const309 GURL DriveApiUrlGenerator::GenerateDownloadFileUrl(
310 const std::string& resource_id) const {
311 GURL url = base_url_.Resolve(base::StringPrintf(
312 kDriveV2DownloadUrlFormat, net::EscapePath(resource_id).c_str()));
313 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
314 return url;
315 }
316
GetPermissionsInsertUrl(const std::string & resource_id) const317 GURL DriveApiUrlGenerator::GetPermissionsInsertUrl(
318 const std::string& resource_id) const {
319 GURL url = base_url_.Resolve(base::StringPrintf(
320 kDriveV2PermissionsUrlFormat, net::EscapePath(resource_id).c_str()));
321 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
322 return url;
323 }
324
GetThumbnailUrl(const std::string & resource_id,int width,int height,bool crop) const325 GURL DriveApiUrlGenerator::GetThumbnailUrl(const std::string& resource_id,
326 int width,
327 int height,
328 bool crop) const {
329 return base_thumbnail_url_.Resolve(
330 base::StringPrintf(
331 crop ? kDriveV2ThumbnailUrlWithCropFormat : kDriveV2ThumbnailUrlFormat,
332 net::EscapePath(resource_id).c_str(), width, height));
333 }
334
GetBatchUploadUrl() const335 GURL DriveApiUrlGenerator::GetBatchUploadUrl() const {
336 GURL url = base_url_.Resolve(kDriveV2BatchUploadUrl);
337 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
338 return url;
339 }
340
GetTeamDriveListUrl(int max_results,const std::string & page_token) const341 GURL DriveApiUrlGenerator::GetTeamDriveListUrl(
342 int max_results,
343 const std::string& page_token) const {
344 GURL url = base_url_.Resolve(kDriveV2TeamDrivesUrl);
345
346 // maxResults is 10 by default.
347 if (max_results != 10) {
348 url = net::AppendOrReplaceQueryParameter(url, "maxResults",
349 base::NumberToString(max_results));
350 }
351 if (!page_token.empty())
352 url = net::AppendOrReplaceQueryParameter(url, "pageToken", page_token);
353
354 return url;
355 }
356
GetStartPageTokenUrl(const std::string & team_drive) const357 GURL DriveApiUrlGenerator::GetStartPageTokenUrl(
358 const std::string& team_drive) const {
359 GURL url = base_url_.Resolve(kDriveV2StartPageTokenUrl);
360
361 url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true");
362
363 if (!team_drive.empty())
364 url = net::AppendOrReplaceQueryParameter(url, kTeamDriveId, team_drive);
365
366 return url;
367 }
368
369 } // namespace google_apis
370