Chromium Code Reviews| Index: chrome/browser/chromeos/gdata/operations_base.cc |
| diff --git a/chrome/browser/chromeos/gdata/operations_base.cc b/chrome/browser/chromeos/gdata/operations_base.cc |
| index 44d7a426f4bbfbfeb6d4cc7c1b30bdafac8bf5f8..2790f8ed39d53e95a4ee3722f52de951789f638b 100644 |
| --- a/chrome/browser/chromeos/gdata/operations_base.cc |
| +++ b/chrome/browser/chromeos/gdata/operations_base.cc |
| @@ -45,6 +45,54 @@ const char kDocsListScope[] = "https://docs.google.com/feeds/"; |
| const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/"; |
| const char kUserContentScope[] = "https://docs.googleusercontent.com/"; |
| +// Parse JSON string to base::Value object. |
| +void ParseJsonOnBlockingPool(const std::string& data, |
| + scoped_ptr<base::Value>* value) { |
| + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + int error_code = -1; |
| + std::string error_message; |
| + value->reset(base::JSONReader::ReadAndReturnError(data, |
| + base::JSON_PARSE_RFC, |
| + &error_code, |
| + &error_message)); |
| + |
| + if (!value->get()) { |
| + LOG(ERROR) << "Error while parsing entry response: " |
| + << error_message |
| + << ", code: " |
| + << error_code |
| + << ", data:\n" |
| + << data; |
| + } |
| +} |
| + |
| +void OnDataParsed( |
| + gdata::GDataErrorCode fetch_error_code, |
| + scoped_ptr<base::Value>* value, |
| + const gdata::GetDataCallback& callback, |
| + const gdata::ProcessURLFetchResultsCallBack& result_callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + bool ret = true; |
| + |
| + if (!value->get()) { |
| + fetch_error_code = gdata::GDATA_PARSE_ERROR; |
| + ret = false; |
| + } |
| + |
| + // The ownership of the parsed json object is transfered to RunCallBack(), |
| + // keeping the ownership of the |value| here. |
| + if (!callback.is_null()) |
| + callback.Run(fetch_error_code, value->Pass()); |
| + |
| + result_callback.Run(ret); |
| + |
| + DCHECK(!value->get()); |
| + |
| + // |value| will be deleted after return beause it is base::Owned()'d. |
| +} |
| + |
| } // namespace |
| namespace gdata { |
| @@ -128,7 +176,8 @@ UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry, |
| profile_(profile), |
| re_authenticate_count_(0), |
| save_temp_file_(false), |
| - started_(false) { |
| + started_(false), |
| + weak_ptr_factory_(this) { |
| } |
| UrlFetchOperationBase::UrlFetchOperationBase( |
| @@ -139,7 +188,8 @@ UrlFetchOperationBase::UrlFetchOperationBase( |
| : GDataOperationRegistry::Operation(registry, type, path), |
| profile_(profile), |
| re_authenticate_count_(0), |
| - save_temp_file_(false) { |
| + save_temp_file_(false), |
| + weak_ptr_factory_(this) { |
| } |
| UrlFetchOperationBase::~UrlFetchOperationBase() {} |
| @@ -229,6 +279,13 @@ GDataErrorCode UrlFetchOperationBase::GetErrorCode( |
| return code; |
| } |
| +void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) { |
| + if (result) |
| + NotifySuccessToOperationRegistry(); |
| + else |
| + NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); |
| +} |
| + |
| void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { |
| GDataErrorCode code = GetErrorCode(source); |
| DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); |
| @@ -245,11 +302,10 @@ void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { |
| } |
| // Overridden by each specialization |
| - bool success = ProcessURLFetchResults(source); |
| - if (success) |
| - NotifySuccessToOperationRegistry(); |
| - else |
| - NotifyFinish(GDataOperationRegistry::OPERATION_FAILED); |
| + ProcessURLFetchResults( |
| + source, |
| + base::Bind(&UrlFetchOperationBase::OnProcessURLFetchResultsComplete, |
| + weak_ptr_factory_.GetWeakPtr())); |
|
hashimoto
2012/07/20 04:07:37
nit: Fix indent
yoshiki
2012/07/24 16:58:32
Done.
|
| } |
| void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { |
| @@ -309,13 +365,14 @@ EntryActionOperation::EntryActionOperation(GDataOperationRegistry* registry, |
| EntryActionOperation::~EntryActionOperation() {} |
| -bool EntryActionOperation::ProcessURLFetchResults( |
| - const URLFetcher* source) { |
| +void EntryActionOperation::ProcessURLFetchResults( |
| + const URLFetcher* source, |
| + const ProcessURLFetchResultsCallBack& result_callback) { |
| if (!callback_.is_null()) { |
| GDataErrorCode code = GetErrorCode(source); |
| callback_.Run(code, document_url_); |
| } |
| - return true; |
| + result_callback.Run(true); |
| } |
| void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
| @@ -328,57 +385,69 @@ void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
| GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, |
| Profile* profile, |
| const GetDataCallback& callback) |
| - : UrlFetchOperationBase(registry, profile), callback_(callback) { |
| + : UrlFetchOperationBase(registry, profile), |
| + callback_(callback) { |
| } |
| GetDataOperation::~GetDataOperation() {} |
| -bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { |
| +void GetDataOperation::ProcessURLFetchResults( |
| + const URLFetcher* source, |
| + const ProcessURLFetchResultsCallBack& result_callback) { |
| std::string data; |
| source->GetResponseAsString(&data); |
| scoped_ptr<base::Value> root_value; |
| - GDataErrorCode code = GetErrorCode(source); |
| + GDataErrorCode fetch_error_code = GetErrorCode(source); |
| - switch (code) { |
| + switch (fetch_error_code) { |
| case HTTP_SUCCESS: |
| - case HTTP_CREATED: { |
| - root_value.reset(ParseResponse(data)); |
| - if (!root_value.get()) |
| - code = GDATA_PARSE_ERROR; |
| - |
| + case HTTP_CREATED: |
| + ParseResponse(fetch_error_code, data, result_callback); |
| break; |
| - } |
| default: |
| + RunCallback(fetch_error_code, scoped_ptr<base::Value>()); |
| + result_callback.Run(false); |
| break; |
| } |
| - |
| - if (!callback_.is_null()) |
| - callback_.Run(code, root_value.Pass()); |
| - return root_value.get() != NULL; |
| } |
| -void GetDataOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { |
| +void GetDataOperation::RunCallbackOnPrematureFailure( |
| + GDataErrorCode fetch_error_code) { |
| if (!callback_.is_null()) { |
| scoped_ptr<base::Value> root_value; |
| - callback_.Run(code, root_value.Pass()); |
| + callback_.Run(fetch_error_code, root_value.Pass()); |
| } |
| } |
| -base::Value* GetDataOperation::ParseResponse(const std::string& data) { |
| - int error_code = -1; |
| - std::string error_message; |
| - scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( |
| - data, base::JSON_PARSE_RFC, &error_code, &error_message)); |
| - if (!root_value.get()) { |
| - LOG(ERROR) << "Error while parsing entry response: " |
| - << error_message |
| - << ", code: " |
| - << error_code |
| - << ", data:\n" |
| - << data; |
| - return NULL; |
| - } |
| - return root_value.release(); |
| +void GetDataOperation::ParseResponse( |
| + GDataErrorCode fetch_error_code, |
| + const std::string& data, |
| + const ProcessURLFetchResultsCallBack& result_callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + // Uses this hack to avoid deep-copy of json object because json might be so |
| + // big. |
| + // This pointer of scped_ptr is to ensure a deletion of the parsed json value |
| + // object, even when OnDataParsed() is not called. |
| + scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>(); |
| + |
| + BrowserThread::PostBlockingPoolTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&ParseJsonOnBlockingPool, |
| + data, |
| + parsed_value), |
| + base::Bind(&OnDataParsed, |
| + fetch_error_code, |
| + base::Owned(parsed_value), |
| + callback_, |
| + result_callback)); |
| +} |
| + |
| +void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code, |
| + scoped_ptr<base::Value> value) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (!callback_.is_null()) |
| + callback_.Run(fetch_error_code, value.Pass()); |
| } |
| } // namespace gdata |