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