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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 const int kMaxReAuthenticateAttemptsPerOperation = 1; | 42 const int kMaxReAuthenticateAttemptsPerOperation = 1; |
43 | 43 |
44 // OAuth scope for the documents API. | 44 // OAuth scope for the documents API. |
45 const char kDocsListScope[] = "https://docs.google.com/feeds/"; | 45 const char kDocsListScope[] = "https://docs.google.com/feeds/"; |
46 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/"; | 46 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/"; |
47 const char kUserContentScope[] = "https://docs.googleusercontent.com/"; | 47 const char kUserContentScope[] = "https://docs.googleusercontent.com/"; |
48 | 48 |
49 // OAuth scope for Drive API. | 49 // OAuth scope for Drive API. |
50 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps"; | 50 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps"; |
51 | 51 |
52 // Parse JSON string to base::Value object. | |
53 void ParseJsonOnBlockingPool(const std::string& data, | |
54 scoped_ptr<base::Value>* value) { | |
55 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
56 | |
57 int error_code = -1; | |
58 std::string error_message; | |
59 value->reset(base::JSONReader::ReadAndReturnError(data, | |
60 base::JSON_PARSE_RFC, | |
61 &error_code, | |
62 &error_message)); | |
63 | |
64 if (!value->get()) { | |
65 LOG(ERROR) << "Error while parsing entry response: " | |
66 << error_message | |
67 << ", code: " | |
68 << error_code | |
69 << ", data:\n" | |
70 << data; | |
71 } | |
72 } | |
73 | |
74 } // namespace | 52 } // namespace |
75 | 53 |
76 namespace gdata { | 54 namespace gdata { |
77 | 55 |
78 //================================ AuthOperation =============================== | 56 //================================ AuthOperation =============================== |
79 | 57 |
80 AuthOperation::AuthOperation(GDataOperationRegistry* registry, | 58 AuthOperation::AuthOperation(GDataOperationRegistry* registry, |
81 Profile* profile, | 59 Profile* profile, |
82 const AuthStatusCallback& callback, | 60 const AuthStatusCallback& callback, |
83 const std::string& refresh_token) | 61 const std::string& refresh_token) |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 const URLFetcher* source) const { | 229 const URLFetcher* source) const { |
252 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); | 230 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); |
253 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { | 231 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { |
254 // If the HTTP response code is SUCCESS yet the URL request failed, it is | 232 // If the HTTP response code is SUCCESS yet the URL request failed, it is |
255 // likely that the failure is due to loss of connection. | 233 // likely that the failure is due to loss of connection. |
256 code = GDATA_NO_CONNECTION; | 234 code = GDATA_NO_CONNECTION; |
257 } | 235 } |
258 return code; | 236 return code; |
259 } | 237 } |
260 | 238 |
261 void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) { | |
262 if (result) | |
263 NotifySuccessToOperationRegistry(); | |
264 else | |
265 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); | |
266 } | |
267 | |
268 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { | 239 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { |
269 GDataErrorCode code = GetErrorCode(source); | 240 GDataErrorCode code = GetErrorCode(source); |
270 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); | 241 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); |
271 | 242 |
272 if (code == HTTP_UNAUTHORIZED) { | 243 if (code == HTTP_UNAUTHORIZED) { |
273 if (!re_authenticate_callback_.is_null() && | 244 if (!re_authenticate_callback_.is_null() && |
274 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { | 245 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { |
275 re_authenticate_callback_.Run(this); | 246 re_authenticate_callback_.Run(this); |
276 return; | 247 return; |
277 } | 248 } |
278 | 249 |
279 OnAuthFailed(code); | 250 OnAuthFailed(code); |
280 return; | 251 return; |
281 } | 252 } |
282 | 253 |
283 // Overridden by each specialization | 254 // Overridden by each specialization |
284 ProcessURLFetchResults(source); | 255 bool success = ProcessURLFetchResults(source); |
| 256 if (success) |
| 257 NotifySuccessToOperationRegistry(); |
| 258 else |
| 259 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); |
285 } | 260 } |
286 | 261 |
287 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { | 262 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { |
288 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); | 263 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); |
289 } | 264 } |
290 | 265 |
291 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { | 266 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { |
292 NotifyStart(); | 267 NotifyStart(); |
293 } | 268 } |
294 | 269 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 Profile* profile, | 309 Profile* profile, |
335 const EntryActionCallback& callback, | 310 const EntryActionCallback& callback, |
336 const GURL& document_url) | 311 const GURL& document_url) |
337 : UrlFetchOperationBase(registry, profile), | 312 : UrlFetchOperationBase(registry, profile), |
338 callback_(callback), | 313 callback_(callback), |
339 document_url_(document_url) { | 314 document_url_(document_url) { |
340 } | 315 } |
341 | 316 |
342 EntryActionOperation::~EntryActionOperation() {} | 317 EntryActionOperation::~EntryActionOperation() {} |
343 | 318 |
344 void EntryActionOperation::ProcessURLFetchResults(const URLFetcher* source) { | 319 bool EntryActionOperation::ProcessURLFetchResults( |
| 320 const URLFetcher* source) { |
345 if (!callback_.is_null()) { | 321 if (!callback_.is_null()) { |
346 GDataErrorCode code = GetErrorCode(source); | 322 GDataErrorCode code = GetErrorCode(source); |
347 callback_.Run(code, document_url_); | 323 callback_.Run(code, document_url_); |
348 } | 324 } |
349 const bool success = true; | 325 return true; |
350 OnProcessURLFetchResultsComplete(success); | |
351 } | 326 } |
352 | 327 |
353 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { | 328 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
354 if (!callback_.is_null()) | 329 if (!callback_.is_null()) |
355 callback_.Run(code, document_url_); | 330 callback_.Run(code, document_url_); |
356 } | 331 } |
357 | 332 |
358 //============================== GetDataOperation ============================== | 333 //============================== GetDataOperation ============================== |
359 | 334 |
360 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, | 335 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, |
361 Profile* profile, | 336 Profile* profile, |
362 const GetDataCallback& callback) | 337 const GetDataCallback& callback) |
363 : UrlFetchOperationBase(registry, profile), | 338 : UrlFetchOperationBase(registry, profile), callback_(callback) { |
364 callback_(callback), | |
365 weak_ptr_factory_(this) { | |
366 } | 339 } |
367 | 340 |
368 GetDataOperation::~GetDataOperation() {} | 341 GetDataOperation::~GetDataOperation() {} |
369 | 342 |
370 void GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { | 343 bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { |
371 std::string data; | 344 std::string data; |
372 source->GetResponseAsString(&data); | 345 source->GetResponseAsString(&data); |
373 scoped_ptr<base::Value> root_value; | 346 scoped_ptr<base::Value> root_value; |
374 GDataErrorCode fetch_error_code = GetErrorCode(source); | 347 GDataErrorCode code = GetErrorCode(source); |
375 | 348 |
376 switch (fetch_error_code) { | 349 switch (code) { |
377 case HTTP_SUCCESS: | 350 case HTTP_SUCCESS: |
378 case HTTP_CREATED: | 351 case HTTP_CREATED: { |
379 ParseResponse(fetch_error_code, data); | 352 root_value.reset(ParseResponse(data)); |
| 353 if (!root_value.get()) |
| 354 code = GDATA_PARSE_ERROR; |
| 355 |
380 break; | 356 break; |
| 357 } |
381 default: | 358 default: |
382 RunCallback(fetch_error_code, scoped_ptr<base::Value>()); | |
383 const bool success = false; | |
384 OnProcessURLFetchResultsComplete(success); | |
385 break; | 359 break; |
386 } | 360 } |
| 361 |
| 362 if (!callback_.is_null()) |
| 363 callback_.Run(code, root_value.Pass()); |
| 364 return root_value.get() != NULL; |
| 365 } |
| 366 |
| 367 void GetDataOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
| 368 if (!callback_.is_null()) { |
| 369 scoped_ptr<base::Value> root_value; |
| 370 callback_.Run(code, root_value.Pass()); |
| 371 } |
387 } | 372 } |
388 | 373 |
389 void GetDataOperation::RunCallbackOnPrematureFailure( | 374 base::Value* GetDataOperation::ParseResponse(const std::string& data) { |
390 GDataErrorCode fetch_error_code) { | 375 int error_code = -1; |
391 if (!callback_.is_null()) { | 376 std::string error_message; |
392 scoped_ptr<base::Value> root_value; | 377 scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( |
393 callback_.Run(fetch_error_code, root_value.Pass()); | 378 data, base::JSON_PARSE_RFC, &error_code, &error_message)); |
| 379 if (!root_value.get()) { |
| 380 LOG(ERROR) << "Error while parsing entry response: " |
| 381 << error_message |
| 382 << ", code: " |
| 383 << error_code |
| 384 << ", data:\n" |
| 385 << data; |
| 386 return NULL; |
394 } | 387 } |
395 } | 388 return root_value.release(); |
396 | |
397 void GetDataOperation::ParseResponse(GDataErrorCode fetch_error_code, | |
398 const std::string& data) { | |
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
400 | |
401 // Uses this hack to avoid deep-copy of json object because json might be so | |
402 // big. This pointer of scped_ptr is to ensure a deletion of the parsed json | |
403 // value object. | |
404 scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>(); | |
405 | |
406 BrowserThread::PostBlockingPoolTaskAndReply( | |
407 FROM_HERE, | |
408 base::Bind(&ParseJsonOnBlockingPool, | |
409 data, | |
410 parsed_value), | |
411 base::Bind(&GetDataOperation::OnDataParsed, | |
412 weak_ptr_factory_.GetWeakPtr(), | |
413 fetch_error_code, | |
414 base::Owned(parsed_value))); | |
415 } | |
416 | |
417 void GetDataOperation::OnDataParsed( | |
418 gdata::GDataErrorCode fetch_error_code, | |
419 scoped_ptr<base::Value>* value) { | |
420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
421 | |
422 bool success = true; | |
423 if (!value->get()) { | |
424 fetch_error_code = gdata::GDATA_PARSE_ERROR; | |
425 success = false; | |
426 } | |
427 | |
428 // The ownership of the parsed json object is transfered to RunCallBack(), | |
429 // keeping the ownership of the |value| here. | |
430 RunCallback(fetch_error_code, value->Pass()); | |
431 | |
432 DCHECK(!value->get()); | |
433 | |
434 OnProcessURLFetchResultsComplete(success); | |
435 // |value| will be deleted after return beause it is base::Owned()'d. | |
436 } | |
437 | |
438 void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code, | |
439 scoped_ptr<base::Value> value) { | |
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
441 if (!callback_.is_null()) | |
442 callback_.Run(fetch_error_code, value.Pass()); | |
443 } | 389 } |
444 | 390 |
445 } // namespace gdata | 391 } // namespace gdata |
OLD | NEW |