Chromium Code Reviews| 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 | |
| 48 } // namespace | 70 } // namespace |
| 49 | 71 |
| 50 namespace gdata { | 72 namespace gdata { |
| 51 | 73 |
| 52 //================================ AuthOperation =============================== | 74 //================================ AuthOperation =============================== |
| 53 | 75 |
| 54 AuthOperation::AuthOperation(GDataOperationRegistry* registry, | 76 AuthOperation::AuthOperation(GDataOperationRegistry* registry, |
| 55 Profile* profile, | 77 Profile* profile, |
| 56 const AuthStatusCallback& callback, | 78 const AuthStatusCallback& callback, |
| 57 const std::string& refresh_token) | 79 const std::string& refresh_token) |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 const URLFetcher* source) const { | 245 const URLFetcher* source) const { |
| 224 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); | 246 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); |
| 225 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { | 247 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { |
| 226 // If the HTTP response code is SUCCESS yet the URL request failed, it is | 248 // 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. | 249 // likely that the failure is due to loss of connection. |
| 228 code = GDATA_NO_CONNECTION; | 250 code = GDATA_NO_CONNECTION; |
| 229 } | 251 } |
| 230 return code; | 252 return code; |
| 231 } | 253 } |
| 232 | 254 |
| 255 void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) { | |
| 256 if (result) | |
| 257 NotifySuccessToOperationRegistry(); | |
| 258 else | |
| 259 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); | |
| 260 } | |
| 261 | |
| 233 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { | 262 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { |
| 234 GDataErrorCode code = GetErrorCode(source); | 263 GDataErrorCode code = GetErrorCode(source); |
| 235 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); | 264 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); |
| 236 | 265 |
| 237 if (code == HTTP_UNAUTHORIZED) { | 266 if (code == HTTP_UNAUTHORIZED) { |
| 238 if (!re_authenticate_callback_.is_null() && | 267 if (!re_authenticate_callback_.is_null() && |
| 239 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { | 268 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { |
| 240 re_authenticate_callback_.Run(this); | 269 re_authenticate_callback_.Run(this); |
| 241 return; | 270 return; |
| 242 } | 271 } |
| 243 | 272 |
| 244 OnAuthFailed(code); | 273 OnAuthFailed(code); |
| 245 return; | 274 return; |
| 246 } | 275 } |
| 247 | 276 |
| 248 // Overridden by each specialization | 277 // Overridden by each specialization |
| 249 bool success = ProcessURLFetchResults(source); | 278 ProcessURLFetchResults(source); |
| 250 if (success) | |
| 251 NotifySuccessToOperationRegistry(); | |
| 252 else | |
| 253 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); | |
| 254 } | 279 } |
| 255 | 280 |
| 256 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { | 281 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { |
| 257 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); | 282 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); |
| 258 } | 283 } |
| 259 | 284 |
| 260 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { | 285 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { |
| 261 NotifyStart(); | 286 NotifyStart(); |
| 262 } | 287 } |
| 263 | 288 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 Profile* profile, | 328 Profile* profile, |
| 304 const EntryActionCallback& callback, | 329 const EntryActionCallback& callback, |
| 305 const GURL& document_url) | 330 const GURL& document_url) |
| 306 : UrlFetchOperationBase(registry, profile), | 331 : UrlFetchOperationBase(registry, profile), |
| 307 callback_(callback), | 332 callback_(callback), |
| 308 document_url_(document_url) { | 333 document_url_(document_url) { |
| 309 } | 334 } |
| 310 | 335 |
| 311 EntryActionOperation::~EntryActionOperation() {} | 336 EntryActionOperation::~EntryActionOperation() {} |
| 312 | 337 |
| 313 bool EntryActionOperation::ProcessURLFetchResults( | 338 void EntryActionOperation::ProcessURLFetchResults(const URLFetcher* source) { |
| 314 const URLFetcher* source) { | |
| 315 if (!callback_.is_null()) { | 339 if (!callback_.is_null()) { |
| 316 GDataErrorCode code = GetErrorCode(source); | 340 GDataErrorCode code = GetErrorCode(source); |
| 317 callback_.Run(code, document_url_); | 341 callback_.Run(code, document_url_); |
| 318 } | 342 } |
| 319 return true; | 343 OnProcessURLFetchResultsComplete(true); |
|
hashimoto
2012/07/26 02:08:44
Do something (replace true with "const bool succes
yoshiki
2012/07/26 17:31:40
Done.
| |
| 320 } | 344 } |
| 321 | 345 |
| 322 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { | 346 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
| 323 if (!callback_.is_null()) | 347 if (!callback_.is_null()) |
| 324 callback_.Run(code, document_url_); | 348 callback_.Run(code, document_url_); |
| 325 } | 349 } |
| 326 | 350 |
| 327 //============================== GetDataOperation ============================== | 351 //============================== GetDataOperation ============================== |
| 328 | 352 |
| 329 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, | 353 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, |
| 330 Profile* profile, | 354 Profile* profile, |
| 331 const GetDataCallback& callback) | 355 const GetDataCallback& callback) |
| 332 : UrlFetchOperationBase(registry, profile), callback_(callback) { | 356 : UrlFetchOperationBase(registry, profile), |
| 357 callback_(callback) { | |
| 333 } | 358 } |
| 334 | 359 |
| 335 GetDataOperation::~GetDataOperation() {} | 360 GetDataOperation::~GetDataOperation() {} |
| 336 | 361 |
| 337 bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { | 362 void GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { |
| 338 std::string data; | 363 std::string data; |
| 339 source->GetResponseAsString(&data); | 364 source->GetResponseAsString(&data); |
| 340 scoped_ptr<base::Value> root_value; | 365 scoped_ptr<base::Value> root_value; |
| 341 GDataErrorCode code = GetErrorCode(source); | 366 GDataErrorCode fetch_error_code = GetErrorCode(source); |
| 342 | 367 |
| 343 switch (code) { | 368 switch (fetch_error_code) { |
| 344 case HTTP_SUCCESS: | 369 case HTTP_SUCCESS: |
| 345 case HTTP_CREATED: { | 370 case HTTP_CREATED: |
| 346 root_value.reset(ParseResponse(data)); | 371 ParseResponse(fetch_error_code, data); |
| 347 if (!root_value.get()) | |
| 348 code = GDATA_PARSE_ERROR; | |
| 349 | |
| 350 break; | 372 break; |
| 351 } | |
| 352 default: | 373 default: |
| 374 RunCallback(fetch_error_code, scoped_ptr<base::Value>()); | |
| 375 OnProcessURLFetchResultsComplete(false); | |
|
hashimoto
2012/07/26 02:08:44
ditto.
yoshiki
2012/07/26 17:31:40
Done.
| |
| 353 break; | 376 break; |
| 354 } | 377 } |
| 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 } | 378 } |
| 367 | 379 |
| 368 base::Value* GetDataOperation::ParseResponse(const std::string& data) { | 380 void GetDataOperation::RunCallbackOnPrematureFailure( |
| 369 int error_code = -1; | 381 GDataErrorCode fetch_error_code) { |
| 370 std::string error_message; | 382 if (!callback_.is_null()) { |
| 371 scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( | 383 scoped_ptr<base::Value> root_value; |
| 372 data, base::JSON_PARSE_RFC, &error_code, &error_message)); | 384 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 } | 385 } |
| 382 return root_value.release(); | 386 } |
| 387 | |
| 388 void GetDataOperation::ParseResponse(GDataErrorCode fetch_error_code, | |
| 389 const std::string& data) { | |
| 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 391 | |
| 392 // Uses this hack to avoid deep-copy of json object because json might be so | |
| 393 // big. This pointer of scped_ptr is to ensure a deletion of the parsed json | |
| 394 // value object. | |
| 395 scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>(); | |
| 396 | |
| 397 BrowserThread::PostBlockingPoolTaskAndReply( | |
| 398 FROM_HERE, | |
| 399 base::Bind(&ParseJsonOnBlockingPool, | |
| 400 data, | |
| 401 parsed_value), | |
| 402 base::Bind(&GetDataOperation::OnDataParsed, | |
| 403 base::Unretained(this), | |
|
hashimoto
2012/07/26 02:08:44
Use WeakPtr
yoshiki
2012/07/26 17:31:40
Done.
| |
| 404 fetch_error_code, | |
| 405 base::Owned(parsed_value), | |
| 406 callback_)); | |
| 407 } | |
| 408 | |
| 409 void GetDataOperation::OnDataParsed( | |
| 410 gdata::GDataErrorCode fetch_error_code, | |
| 411 scoped_ptr<base::Value>* value, | |
| 412 const gdata::GetDataCallback& callback) { | |
|
hashimoto
2012/07/26 02:08:44
Since |callback_| is always passed, this argument
yoshiki
2012/07/26 17:31:40
Done.
| |
| 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 414 | |
| 415 bool ret = true; | |
|
hashimoto
2012/07/26 02:08:44
|ret| is ambiguous, rename this variable to |succe
yoshiki
2012/07/26 17:31:40
Done.
| |
| 416 if (!value->get()) { | |
| 417 fetch_error_code = gdata::GDATA_PARSE_ERROR; | |
| 418 ret = false; | |
| 419 } | |
| 420 | |
| 421 // The ownership of the parsed json object is transfered to RunCallBack(), | |
| 422 // keeping the ownership of the |value| here. | |
| 423 if (!callback.is_null()) | |
|
hashimoto
2012/07/26 02:08:44
Call RunCallback() instead.
yoshiki
2012/07/26 17:31:40
Done.
| |
| 424 callback.Run(fetch_error_code, value->Pass()); | |
| 425 | |
| 426 DCHECK(!value->get()); | |
| 427 | |
| 428 OnProcessURLFetchResultsComplete(ret); | |
| 429 // |value| will be deleted after return beause it is base::Owned()'d. | |
| 430 } | |
| 431 | |
| 432 void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code, | |
| 433 scoped_ptr<base::Value> value) { | |
| 434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 435 if (!callback_.is_null()) | |
| 436 callback_.Run(fetch_error_code, value.Pass()); | |
| 383 } | 437 } |
| 384 | 438 |
| 385 } // namespace gdata | 439 } // namespace gdata |
| OLD | NEW |