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