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/chromeos/gdata/operations_base.h" | 5 #include "chrome/browser/chromeos/gdata/operations_base.h" |
6 | 6 |
7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 const char kGDataVersionHeader[] = "GData-Version: 3.0"; | 38 const char kGDataVersionHeader[] = "GData-Version: 3.0"; |
39 | 39 |
40 // Maximum number of attempts for re-authentication per operation. | 40 // Maximum number of attempts for re-authentication per operation. |
41 const int kMaxReAuthenticateAttemptsPerOperation = 1; | 41 const int kMaxReAuthenticateAttemptsPerOperation = 1; |
42 | 42 |
43 // OAuth scope for the documents API. | 43 // OAuth scope for the documents API. |
44 const char kDocsListScope[] = "https://docs.google.com/feeds/"; | 44 const char kDocsListScope[] = "https://docs.google.com/feeds/"; |
45 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/"; | 45 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/"; |
46 const char kUserContentScope[] = "https://docs.googleusercontent.com/"; | 46 const char kUserContentScope[] = "https://docs.googleusercontent.com/"; |
47 | 47 |
48 // Parse JSON string to base::Value object. | |
49 void ParseJsonOnBlockingPool(const std::string& data, | |
50 scoped_ptr<base::Value>* value) { | |
51 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
52 | |
53 int error_code = -1; | |
54 std::string error_message; | |
55 value->reset(base::JSONReader::ReadAndReturnError(data, | |
56 base::JSON_PARSE_RFC, | |
57 &error_code, | |
58 &error_message)); | |
59 | |
60 if (!value->get()) { | |
61 LOG(ERROR) << "Error while parsing entry response: " | |
62 << error_message | |
63 << ", code: " | |
64 << error_code | |
65 << ", data:\n" | |
66 << data; | |
67 } | |
68 } | |
69 | |
70 void OnDataParsed( | |
hashimoto
2012/07/25 06:14:21
Function comment is needed.
yoshiki
2012/07/25 17:24:27
Done.
| |
71 gdata::GDataErrorCode fetch_error_code, | |
72 scoped_ptr<base::Value>* value, | |
73 const gdata::GetDataCallback& callback, | |
74 const gdata::ProcessURLFetchResultsCallback& result_callback) { | |
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
76 | |
77 bool ret = true; | |
78 | |
79 if (!value->get()) { | |
80 fetch_error_code = gdata::GDATA_PARSE_ERROR; | |
81 ret = false; | |
82 } | |
83 | |
84 // The ownership of the parsed json object is transfered to RunCallBack(), | |
85 // keeping the ownership of the |value| here. | |
86 if (!callback.is_null()) | |
87 callback.Run(fetch_error_code, value->Pass()); | |
88 | |
89 result_callback.Run(ret); | |
90 | |
91 DCHECK(!value->get()); | |
92 | |
93 // |value| will be deleted after return beause it is base::Owned()'d. | |
94 } | |
95 | |
48 } // namespace | 96 } // namespace |
49 | 97 |
50 namespace gdata { | 98 namespace gdata { |
51 | 99 |
52 //================================ AuthOperation =============================== | 100 //================================ AuthOperation =============================== |
53 | 101 |
54 AuthOperation::AuthOperation(GDataOperationRegistry* registry, | 102 AuthOperation::AuthOperation(GDataOperationRegistry* registry, |
55 Profile* profile, | 103 Profile* profile, |
56 const AuthStatusCallback& callback, | 104 const AuthStatusCallback& callback, |
57 const std::string& refresh_token) | 105 const std::string& refresh_token) |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 } | 170 } |
123 | 171 |
124 //============================ UrlFetchOperationBase =========================== | 172 //============================ UrlFetchOperationBase =========================== |
125 | 173 |
126 UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry, | 174 UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry, |
127 Profile* profile) | 175 Profile* profile) |
128 : GDataOperationRegistry::Operation(registry), | 176 : GDataOperationRegistry::Operation(registry), |
129 profile_(profile), | 177 profile_(profile), |
130 re_authenticate_count_(0), | 178 re_authenticate_count_(0), |
131 save_temp_file_(false), | 179 save_temp_file_(false), |
132 started_(false) { | 180 started_(false), |
181 weak_ptr_factory_(this) { | |
133 } | 182 } |
134 | 183 |
135 UrlFetchOperationBase::UrlFetchOperationBase( | 184 UrlFetchOperationBase::UrlFetchOperationBase( |
136 GDataOperationRegistry* registry, | 185 GDataOperationRegistry* registry, |
137 GDataOperationRegistry::OperationType type, | 186 GDataOperationRegistry::OperationType type, |
138 const FilePath& path, | 187 const FilePath& path, |
139 Profile* profile) | 188 Profile* profile) |
140 : GDataOperationRegistry::Operation(registry, type, path), | 189 : GDataOperationRegistry::Operation(registry, type, path), |
141 profile_(profile), | 190 profile_(profile), |
142 re_authenticate_count_(0), | 191 re_authenticate_count_(0), |
143 save_temp_file_(false) { | 192 save_temp_file_(false), |
193 weak_ptr_factory_(this) { | |
144 } | 194 } |
145 | 195 |
146 UrlFetchOperationBase::~UrlFetchOperationBase() {} | 196 UrlFetchOperationBase::~UrlFetchOperationBase() {} |
147 | 197 |
148 void UrlFetchOperationBase::Start(const std::string& auth_token) { | 198 void UrlFetchOperationBase::Start(const std::string& auth_token) { |
149 DCHECK(!auth_token.empty()); | 199 DCHECK(!auth_token.empty()); |
150 | 200 |
151 GURL url = GetURL(); | 201 GURL url = GetURL(); |
152 DCHECK(!url.is_empty()); | 202 DCHECK(!url.is_empty()); |
153 DVLOG(1) << "URL: " << url.spec(); | 203 DVLOG(1) << "URL: " << url.spec(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 const URLFetcher* source) const { | 273 const URLFetcher* source) const { |
224 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); | 274 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); |
225 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { | 275 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { |
226 // If the HTTP response code is SUCCESS yet the URL request failed, it is | 276 // If the HTTP response code is SUCCESS yet the URL request failed, it is |
227 // likely that the failure is due to loss of connection. | 277 // likely that the failure is due to loss of connection. |
228 code = GDATA_NO_CONNECTION; | 278 code = GDATA_NO_CONNECTION; |
229 } | 279 } |
230 return code; | 280 return code; |
231 } | 281 } |
232 | 282 |
283 void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) { | |
284 if (result) | |
285 NotifySuccessToOperationRegistry(); | |
286 else | |
287 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); | |
288 } | |
289 | |
233 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { | 290 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { |
234 GDataErrorCode code = GetErrorCode(source); | 291 GDataErrorCode code = GetErrorCode(source); |
235 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); | 292 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); |
236 | 293 |
237 if (code == HTTP_UNAUTHORIZED) { | 294 if (code == HTTP_UNAUTHORIZED) { |
238 if (!re_authenticate_callback_.is_null() && | 295 if (!re_authenticate_callback_.is_null() && |
239 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { | 296 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { |
240 re_authenticate_callback_.Run(this); | 297 re_authenticate_callback_.Run(this); |
241 return; | 298 return; |
242 } | 299 } |
243 | 300 |
244 OnAuthFailed(code); | 301 OnAuthFailed(code); |
245 return; | 302 return; |
246 } | 303 } |
247 | 304 |
248 // Overridden by each specialization | 305 // Overridden by each specialization |
249 bool success = ProcessURLFetchResults(source); | 306 ProcessURLFetchResults( |
250 if (success) | 307 source, |
251 NotifySuccessToOperationRegistry(); | 308 base::Bind(&UrlFetchOperationBase::OnProcessURLFetchResultsComplete, |
252 else | 309 weak_ptr_factory_.GetWeakPtr())); |
253 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); | |
254 } | 310 } |
255 | 311 |
256 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { | 312 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { |
257 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); | 313 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); |
258 } | 314 } |
259 | 315 |
260 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { | 316 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { |
261 NotifyStart(); | 317 NotifyStart(); |
262 } | 318 } |
263 | 319 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 Profile* profile, | 359 Profile* profile, |
304 const EntryActionCallback& callback, | 360 const EntryActionCallback& callback, |
305 const GURL& document_url) | 361 const GURL& document_url) |
306 : UrlFetchOperationBase(registry, profile), | 362 : UrlFetchOperationBase(registry, profile), |
307 callback_(callback), | 363 callback_(callback), |
308 document_url_(document_url) { | 364 document_url_(document_url) { |
309 } | 365 } |
310 | 366 |
311 EntryActionOperation::~EntryActionOperation() {} | 367 EntryActionOperation::~EntryActionOperation() {} |
312 | 368 |
313 bool EntryActionOperation::ProcessURLFetchResults( | 369 void EntryActionOperation::ProcessURLFetchResults( |
314 const URLFetcher* source) { | 370 const URLFetcher* source, |
371 const ProcessURLFetchResultsCallback& result_callback) { | |
315 if (!callback_.is_null()) { | 372 if (!callback_.is_null()) { |
316 GDataErrorCode code = GetErrorCode(source); | 373 GDataErrorCode code = GetErrorCode(source); |
317 callback_.Run(code, document_url_); | 374 callback_.Run(code, document_url_); |
318 } | 375 } |
319 return true; | 376 result_callback.Run(true); |
320 } | 377 } |
321 | 378 |
322 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { | 379 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
323 if (!callback_.is_null()) | 380 if (!callback_.is_null()) |
324 callback_.Run(code, document_url_); | 381 callback_.Run(code, document_url_); |
325 } | 382 } |
326 | 383 |
327 //============================== GetDataOperation ============================== | 384 //============================== GetDataOperation ============================== |
328 | 385 |
329 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, | 386 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, |
330 Profile* profile, | 387 Profile* profile, |
331 const GetDataCallback& callback) | 388 const GetDataCallback& callback) |
332 : UrlFetchOperationBase(registry, profile), callback_(callback) { | 389 : UrlFetchOperationBase(registry, profile), |
390 callback_(callback) { | |
333 } | 391 } |
334 | 392 |
335 GetDataOperation::~GetDataOperation() {} | 393 GetDataOperation::~GetDataOperation() {} |
336 | 394 |
337 bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { | 395 void GetDataOperation::ProcessURLFetchResults( |
396 const URLFetcher* source, | |
397 const ProcessURLFetchResultsCallback& result_callback) { | |
338 std::string data; | 398 std::string data; |
339 source->GetResponseAsString(&data); | 399 source->GetResponseAsString(&data); |
340 scoped_ptr<base::Value> root_value; | 400 scoped_ptr<base::Value> root_value; |
341 GDataErrorCode code = GetErrorCode(source); | 401 GDataErrorCode fetch_error_code = GetErrorCode(source); |
342 | 402 |
343 switch (code) { | 403 switch (fetch_error_code) { |
344 case HTTP_SUCCESS: | 404 case HTTP_SUCCESS: |
345 case HTTP_CREATED: { | 405 case HTTP_CREATED: |
346 root_value.reset(ParseResponse(data)); | 406 ParseResponse(fetch_error_code, data, result_callback); |
347 if (!root_value.get()) | |
348 code = GDATA_PARSE_ERROR; | |
349 | |
350 break; | 407 break; |
351 } | |
352 default: | 408 default: |
409 RunCallback(fetch_error_code, scoped_ptr<base::Value>()); | |
410 result_callback.Run(false); | |
353 break; | 411 break; |
354 } | 412 } |
355 | |
356 if (!callback_.is_null()) | |
357 callback_.Run(code, root_value.Pass()); | |
358 return root_value.get() != NULL; | |
359 } | |
360 | |
361 void GetDataOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { | |
362 if (!callback_.is_null()) { | |
363 scoped_ptr<base::Value> root_value; | |
364 callback_.Run(code, root_value.Pass()); | |
365 } | |
366 } | 413 } |
367 | 414 |
368 base::Value* GetDataOperation::ParseResponse(const std::string& data) { | 415 void GetDataOperation::RunCallbackOnPrematureFailure( |
369 int error_code = -1; | 416 GDataErrorCode fetch_error_code) { |
370 std::string error_message; | 417 if (!callback_.is_null()) { |
371 scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( | 418 scoped_ptr<base::Value> root_value; |
372 data, base::JSON_PARSE_RFC, &error_code, &error_message)); | 419 callback_.Run(fetch_error_code, root_value.Pass()); |
373 if (!root_value.get()) { | |
374 LOG(ERROR) << "Error while parsing entry response: " | |
375 << error_message | |
376 << ", code: " | |
377 << error_code | |
378 << ", data:\n" | |
379 << data; | |
380 return NULL; | |
381 } | 420 } |
382 return root_value.release(); | 421 } |
422 | |
423 void GetDataOperation::ParseResponse( | |
424 GDataErrorCode fetch_error_code, | |
425 const std::string& data, | |
426 const ProcessURLFetchResultsCallback& result_callback) { | |
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
428 | |
429 // Uses this hack to avoid deep-copy of json object because json might be so | |
430 // big. | |
431 // This pointer of scped_ptr is to ensure a deletion of the parsed json value | |
432 // object, even when OnDataParsed() is not called. | |
433 scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>(); | |
434 | |
435 BrowserThread::PostBlockingPoolTaskAndReply( | |
436 FROM_HERE, | |
437 base::Bind(&ParseJsonOnBlockingPool, | |
438 data, | |
439 parsed_value), | |
440 base::Bind(&OnDataParsed, | |
441 fetch_error_code, | |
442 base::Owned(parsed_value), | |
443 callback_, | |
444 result_callback)); | |
445 } | |
446 | |
447 void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code, | |
448 scoped_ptr<base::Value> value) { | |
449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
450 if (!callback_.is_null()) | |
451 callback_.Run(fetch_error_code, value.Pass()); | |
383 } | 452 } |
384 | 453 |
385 } // namespace gdata | 454 } // namespace gdata |
OLD | NEW |