Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: chrome/browser/chromeos/gdata/operations_base.cc

Issue 10808027: gdrive: Get JSON feeds parsing off the UI thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Call NotifyFinish/NotifySuccess after parse. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
70 void OnDataParsed(
71 gdata::GDataErrorCode fetch_error_code,
72 scoped_ptr<base::Value>* value,
73 const gdata::GetDataCallback& callback,
74 const gdata::ProcessURLFetchResultsCallBack& result_callback) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
76
77 bool ret = true;
78
79 if (!value->get()) {
80 fetch_error_code = gdata::GDATA_PARSE_ERROR;
81 ret = false;
82 }
83
84 // The ownership of the parsed json object is transfered to RunCallBack(),
85 // keeping the ownership of the |value| here.
86 if (!callback.is_null())
87 callback.Run(fetch_error_code, value->Pass());
88
89 result_callback.Run(ret);
90
91 DCHECK(!value->get());
92
93 // |value| will be deleted after return beause it is base::Owned()'d.
94 }
95
48 } // namespace 96 } // namespace
49 97
50 namespace gdata { 98 namespace gdata {
51 99
52 //================================ AuthOperation =============================== 100 //================================ AuthOperation ===============================
53 101
54 AuthOperation::AuthOperation(GDataOperationRegistry* registry, 102 AuthOperation::AuthOperation(GDataOperationRegistry* registry,
55 Profile* profile, 103 Profile* profile,
56 const AuthStatusCallback& callback, 104 const AuthStatusCallback& callback,
57 const std::string& refresh_token) 105 const std::string& refresh_token)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 } 169 }
122 170
123 //============================ UrlFetchOperationBase =========================== 171 //============================ UrlFetchOperationBase ===========================
124 172
125 UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry, 173 UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry,
126 Profile* profile) 174 Profile* profile)
127 : GDataOperationRegistry::Operation(registry), 175 : GDataOperationRegistry::Operation(registry),
128 profile_(profile), 176 profile_(profile),
129 re_authenticate_count_(0), 177 re_authenticate_count_(0),
130 save_temp_file_(false), 178 save_temp_file_(false),
131 started_(false) { 179 started_(false),
180 weak_ptr_factory_(this) {
132 } 181 }
133 182
134 UrlFetchOperationBase::UrlFetchOperationBase( 183 UrlFetchOperationBase::UrlFetchOperationBase(
135 GDataOperationRegistry* registry, 184 GDataOperationRegistry* registry,
136 GDataOperationRegistry::OperationType type, 185 GDataOperationRegistry::OperationType type,
137 const FilePath& path, 186 const FilePath& path,
138 Profile* profile) 187 Profile* profile)
139 : GDataOperationRegistry::Operation(registry, type, path), 188 : GDataOperationRegistry::Operation(registry, type, path),
140 profile_(profile), 189 profile_(profile),
141 re_authenticate_count_(0), 190 re_authenticate_count_(0),
142 save_temp_file_(false) { 191 save_temp_file_(false),
192 weak_ptr_factory_(this) {
143 } 193 }
144 194
145 UrlFetchOperationBase::~UrlFetchOperationBase() {} 195 UrlFetchOperationBase::~UrlFetchOperationBase() {}
146 196
147 void UrlFetchOperationBase::Start(const std::string& auth_token) { 197 void UrlFetchOperationBase::Start(const std::string& auth_token) {
148 DCHECK(!auth_token.empty()); 198 DCHECK(!auth_token.empty());
149 199
150 GURL url = GetURL(); 200 GURL url = GetURL();
151 DCHECK(!url.is_empty()); 201 DCHECK(!url.is_empty());
152 DVLOG(1) << "URL: " << url.spec(); 202 DVLOG(1) << "URL: " << url.spec();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 const URLFetcher* source) const { 272 const URLFetcher* source) const {
223 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); 273 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode());
224 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { 274 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) {
225 // If the HTTP response code is SUCCESS yet the URL request failed, it is 275 // If the HTTP response code is SUCCESS yet the URL request failed, it is
226 // likely that the failure is due to loss of connection. 276 // likely that the failure is due to loss of connection.
227 code = GDATA_NO_CONNECTION; 277 code = GDATA_NO_CONNECTION;
228 } 278 }
229 return code; 279 return code;
230 } 280 }
231 281
282 void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) {
283 if (result)
284 NotifySuccessToOperationRegistry();
285 else
286 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED);
287 }
288
232 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { 289 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) {
233 GDataErrorCode code = GetErrorCode(source); 290 GDataErrorCode code = GetErrorCode(source);
234 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); 291 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source);
235 292
236 if (code == HTTP_UNAUTHORIZED) { 293 if (code == HTTP_UNAUTHORIZED) {
237 if (!re_authenticate_callback_.is_null() && 294 if (!re_authenticate_callback_.is_null() &&
238 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { 295 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) {
239 re_authenticate_callback_.Run(this); 296 re_authenticate_callback_.Run(this);
240 return; 297 return;
241 } 298 }
242 299
243 OnAuthFailed(code); 300 OnAuthFailed(code);
244 return; 301 return;
245 } 302 }
246 303
247 // Overridden by each specialization 304 // Overridden by each specialization
248 bool success = ProcessURLFetchResults(source); 305 ProcessURLFetchResults(
249 if (success) 306 source,
250 NotifySuccessToOperationRegistry(); 307 base::Bind(&UrlFetchOperationBase::OnProcessURLFetchResultsComplete,
251 else 308 weak_ptr_factory_.GetWeakPtr()));
hashimoto 2012/07/20 04:07:37 nit: Fix indent
yoshiki 2012/07/24 16:58:32 Done.
252 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED);
253 } 309 }
254 310
255 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { 311 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() {
256 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); 312 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED);
257 } 313 }
258 314
259 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { 315 void UrlFetchOperationBase::NotifyStartToOperationRegistry() {
260 NotifyStart(); 316 NotifyStart();
261 } 317 }
262 318
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 Profile* profile, 358 Profile* profile,
303 const EntryActionCallback& callback, 359 const EntryActionCallback& callback,
304 const GURL& document_url) 360 const GURL& document_url)
305 : UrlFetchOperationBase(registry, profile), 361 : UrlFetchOperationBase(registry, profile),
306 callback_(callback), 362 callback_(callback),
307 document_url_(document_url) { 363 document_url_(document_url) {
308 } 364 }
309 365
310 EntryActionOperation::~EntryActionOperation() {} 366 EntryActionOperation::~EntryActionOperation() {}
311 367
312 bool EntryActionOperation::ProcessURLFetchResults( 368 void EntryActionOperation::ProcessURLFetchResults(
313 const URLFetcher* source) { 369 const URLFetcher* source,
370 const ProcessURLFetchResultsCallBack& result_callback) {
314 if (!callback_.is_null()) { 371 if (!callback_.is_null()) {
315 GDataErrorCode code = GetErrorCode(source); 372 GDataErrorCode code = GetErrorCode(source);
316 callback_.Run(code, document_url_); 373 callback_.Run(code, document_url_);
317 } 374 }
318 return true; 375 result_callback.Run(true);
319 } 376 }
320 377
321 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { 378 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) {
322 if (!callback_.is_null()) 379 if (!callback_.is_null())
323 callback_.Run(code, document_url_); 380 callback_.Run(code, document_url_);
324 } 381 }
325 382
326 //============================== GetDataOperation ============================== 383 //============================== GetDataOperation ==============================
327 384
328 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, 385 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry,
329 Profile* profile, 386 Profile* profile,
330 const GetDataCallback& callback) 387 const GetDataCallback& callback)
331 : UrlFetchOperationBase(registry, profile), callback_(callback) { 388 : UrlFetchOperationBase(registry, profile),
389 callback_(callback) {
332 } 390 }
333 391
334 GetDataOperation::~GetDataOperation() {} 392 GetDataOperation::~GetDataOperation() {}
335 393
336 bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { 394 void GetDataOperation::ProcessURLFetchResults(
395 const URLFetcher* source,
396 const ProcessURLFetchResultsCallBack& result_callback) {
337 std::string data; 397 std::string data;
338 source->GetResponseAsString(&data); 398 source->GetResponseAsString(&data);
339 scoped_ptr<base::Value> root_value; 399 scoped_ptr<base::Value> root_value;
340 GDataErrorCode code = GetErrorCode(source); 400 GDataErrorCode fetch_error_code = GetErrorCode(source);
341 401
342 switch (code) { 402 switch (fetch_error_code) {
343 case HTTP_SUCCESS: 403 case HTTP_SUCCESS:
344 case HTTP_CREATED: { 404 case HTTP_CREATED:
345 root_value.reset(ParseResponse(data)); 405 ParseResponse(fetch_error_code, data, result_callback);
346 if (!root_value.get())
347 code = GDATA_PARSE_ERROR;
348
349 break; 406 break;
350 }
351 default: 407 default:
408 RunCallback(fetch_error_code, scoped_ptr<base::Value>());
409 result_callback.Run(false);
352 break; 410 break;
353 } 411 }
354
355 if (!callback_.is_null())
356 callback_.Run(code, root_value.Pass());
357 return root_value.get() != NULL;
358 }
359
360 void GetDataOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) {
361 if (!callback_.is_null()) {
362 scoped_ptr<base::Value> root_value;
363 callback_.Run(code, root_value.Pass());
364 }
365 } 412 }
366 413
367 base::Value* GetDataOperation::ParseResponse(const std::string& data) { 414 void GetDataOperation::RunCallbackOnPrematureFailure(
368 int error_code = -1; 415 GDataErrorCode fetch_error_code) {
369 std::string error_message; 416 if (!callback_.is_null()) {
370 scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( 417 scoped_ptr<base::Value> root_value;
371 data, base::JSON_PARSE_RFC, &error_code, &error_message)); 418 callback_.Run(fetch_error_code, root_value.Pass());
372 if (!root_value.get()) {
373 LOG(ERROR) << "Error while parsing entry response: "
374 << error_message
375 << ", code: "
376 << error_code
377 << ", data:\n"
378 << data;
379 return NULL;
380 } 419 }
381 return root_value.release(); 420 }
421
422 void GetDataOperation::ParseResponse(
423 GDataErrorCode fetch_error_code,
424 const std::string& data,
425 const ProcessURLFetchResultsCallBack& result_callback) {
426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
427
428 // Uses this hack to avoid deep-copy of json object because json might be so
429 // big.
430 // This pointer of scped_ptr is to ensure a deletion of the parsed json value
431 // object, even when OnDataParsed() is not called.
432 scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>();
433
434 BrowserThread::PostBlockingPoolTaskAndReply(
435 FROM_HERE,
436 base::Bind(&ParseJsonOnBlockingPool,
437 data,
438 parsed_value),
439 base::Bind(&OnDataParsed,
440 fetch_error_code,
441 base::Owned(parsed_value),
442 callback_,
443 result_callback));
444 }
445
446 void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code,
447 scoped_ptr<base::Value> value) {
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
449 if (!callback_.is_null())
450 callback_.Run(fetch_error_code, value.Pass());
382 } 451 }
383 452
384 } // namespace gdata 453 } // namespace gdata
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698