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 5890d19f08683a479fb0d7a5b9f1a7020380f526..d60be97d5ae05914d88a600c40faac4df1185ce1 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( |
hashimoto
2012/07/25 06:14:21
Function comment is needed.
yoshiki
2012/07/25 17:24:27
Done.
|
+ 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 { |
@@ -129,7 +177,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( |
@@ -140,7 +189,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() {} |
@@ -230,6 +280,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); |
@@ -246,11 +303,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())); |
} |
void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { |
@@ -310,13 +366,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) { |
@@ -329,57 +386,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 |