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

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: making OnDataParsed() a private method of GetDataOperation Created 8 years, 4 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
« no previous file with comments | « chrome/browser/chromeos/gdata/operations_base.h ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/gdata/operations_base.h ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698