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

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: Rebase and Fix conflict and build error. 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 const char kDocsListScope[] = "https://docs.google.com/feeds/"; 45 const char kDocsListScope[] = "https://docs.google.com/feeds/";
46 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/"; 46 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/";
47 const char kUserContentScope[] = "https://docs.googleusercontent.com/"; 47 const char kUserContentScope[] = "https://docs.googleusercontent.com/";
48 48
49 // OAuth scope for the Contacts API. 49 // OAuth scope for the Contacts API.
50 const char kContactsScope[] = "https://www.google.com/m8/feeds/"; 50 const char kContactsScope[] = "https://www.google.com/m8/feeds/";
51 51
52 // OAuth scope for Drive API. 52 // OAuth scope for Drive API.
53 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps"; 53 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps";
54 54
55 // Parse JSON string to base::Value object.
56 void ParseJsonOnBlockingPool(const std::string& data,
57 scoped_ptr<base::Value>* value) {
58 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
59
60 int error_code = -1;
61 std::string error_message;
62 value->reset(base::JSONReader::ReadAndReturnError(data,
63 base::JSON_PARSE_RFC,
64 &error_code,
65 &error_message));
66
67 if (!value->get()) {
68 LOG(ERROR) << "Error while parsing entry response: "
69 << error_message
70 << ", code: "
71 << error_code
72 << ", data:\n"
73 << data;
74 }
75 }
76
55 } // namespace 77 } // namespace
56 78
57 namespace gdata { 79 namespace gdata {
58 80
59 //================================ AuthOperation =============================== 81 //================================ AuthOperation ===============================
60 82
61 AuthOperation::AuthOperation(GDataOperationRegistry* registry, 83 AuthOperation::AuthOperation(GDataOperationRegistry* registry,
62 Profile* profile, 84 Profile* profile,
63 const AuthStatusCallback& callback, 85 const AuthStatusCallback& callback,
64 const std::string& refresh_token) 86 const std::string& refresh_token)
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 const URLFetcher* source) const { 255 const URLFetcher* source) const {
234 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); 256 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode());
235 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { 257 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) {
236 // If the HTTP response code is SUCCESS yet the URL request failed, it is 258 // If the HTTP response code is SUCCESS yet the URL request failed, it is
237 // likely that the failure is due to loss of connection. 259 // likely that the failure is due to loss of connection.
238 code = GDATA_NO_CONNECTION; 260 code = GDATA_NO_CONNECTION;
239 } 261 }
240 return code; 262 return code;
241 } 263 }
242 264
265 void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) {
266 if (result)
267 NotifySuccessToOperationRegistry();
268 else
269 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED);
270 }
271
243 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { 272 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) {
244 GDataErrorCode code = GetErrorCode(source); 273 GDataErrorCode code = GetErrorCode(source);
245 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); 274 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source);
246 275
247 if (code == HTTP_UNAUTHORIZED) { 276 if (code == HTTP_UNAUTHORIZED) {
248 if (!re_authenticate_callback_.is_null() && 277 if (!re_authenticate_callback_.is_null() &&
249 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { 278 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) {
250 re_authenticate_callback_.Run(this); 279 re_authenticate_callback_.Run(this);
251 return; 280 return;
252 } 281 }
253 282
254 OnAuthFailed(code); 283 OnAuthFailed(code);
255 return; 284 return;
256 } 285 }
257 286
258 // Overridden by each specialization 287 // Overridden by each specialization
259 bool success = ProcessURLFetchResults(source); 288 ProcessURLFetchResults(source);
260 if (success)
261 NotifySuccessToOperationRegistry();
262 else
263 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED);
264 } 289 }
265 290
266 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { 291 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() {
267 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); 292 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED);
268 } 293 }
269 294
270 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { 295 void UrlFetchOperationBase::NotifyStartToOperationRegistry() {
271 NotifyStart(); 296 NotifyStart();
272 } 297 }
273 298
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 Profile* profile, 338 Profile* profile,
314 const EntryActionCallback& callback, 339 const EntryActionCallback& callback,
315 const GURL& document_url) 340 const GURL& document_url)
316 : UrlFetchOperationBase(registry, profile), 341 : UrlFetchOperationBase(registry, profile),
317 callback_(callback), 342 callback_(callback),
318 document_url_(document_url) { 343 document_url_(document_url) {
319 } 344 }
320 345
321 EntryActionOperation::~EntryActionOperation() {} 346 EntryActionOperation::~EntryActionOperation() {}
322 347
323 bool EntryActionOperation::ProcessURLFetchResults( 348 void EntryActionOperation::ProcessURLFetchResults(const URLFetcher* source) {
324 const URLFetcher* source) {
325 if (!callback_.is_null()) { 349 if (!callback_.is_null()) {
326 GDataErrorCode code = GetErrorCode(source); 350 GDataErrorCode code = GetErrorCode(source);
327 callback_.Run(code, document_url_); 351 callback_.Run(code, document_url_);
328 } 352 }
329 return true; 353 const bool success = true;
354 OnProcessURLFetchResultsComplete(success);
330 } 355 }
331 356
332 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { 357 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) {
333 if (!callback_.is_null()) 358 if (!callback_.is_null())
334 callback_.Run(code, document_url_); 359 callback_.Run(code, document_url_);
335 } 360 }
336 361
337 //============================== GetDataOperation ============================== 362 //============================== GetDataOperation ==============================
338 363
339 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, 364 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry,
340 Profile* profile, 365 Profile* profile,
341 const GetDataCallback& callback) 366 const GetDataCallback& callback)
342 : UrlFetchOperationBase(registry, profile), callback_(callback) { 367 : UrlFetchOperationBase(registry, profile),
368 callback_(callback),
369 weak_ptr_factory_(this) {
343 } 370 }
344 371
345 GetDataOperation::~GetDataOperation() {} 372 GetDataOperation::~GetDataOperation() {}
346 373
347 bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { 374 void GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) {
348 std::string data; 375 std::string data;
349 source->GetResponseAsString(&data); 376 source->GetResponseAsString(&data);
350 scoped_ptr<base::Value> root_value; 377 scoped_ptr<base::Value> root_value;
351 GDataErrorCode code = GetErrorCode(source); 378 GDataErrorCode fetch_error_code = GetErrorCode(source);
352 379
353 switch (code) { 380 switch (fetch_error_code) {
354 case HTTP_SUCCESS: 381 case HTTP_SUCCESS:
355 case HTTP_CREATED: { 382 case HTTP_CREATED:
356 root_value.reset(ParseResponse(data)); 383 ParseResponse(fetch_error_code, data);
357 if (!root_value.get())
358 code = GDATA_PARSE_ERROR;
359
360 break; 384 break;
361 }
362 default: 385 default:
386 RunCallback(fetch_error_code, scoped_ptr<base::Value>());
387 const bool success = false;
388 OnProcessURLFetchResultsComplete(success);
363 break; 389 break;
364 } 390 }
365
366 if (!callback_.is_null())
367 callback_.Run(code, root_value.Pass());
368 return root_value.get() != NULL;
369 }
370
371 void GetDataOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) {
372 if (!callback_.is_null()) {
373 scoped_ptr<base::Value> root_value;
374 callback_.Run(code, root_value.Pass());
375 }
376 } 391 }
377 392
378 base::Value* GetDataOperation::ParseResponse(const std::string& data) { 393 void GetDataOperation::RunCallbackOnPrematureFailure(
379 int error_code = -1; 394 GDataErrorCode fetch_error_code) {
380 std::string error_message; 395 if (!callback_.is_null()) {
381 scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( 396 scoped_ptr<base::Value> root_value;
382 data, base::JSON_PARSE_RFC, &error_code, &error_message)); 397 callback_.Run(fetch_error_code, root_value.Pass());
383 if (!root_value.get()) {
384 LOG(ERROR) << "Error while parsing entry response: "
385 << error_message
386 << ", code: "
387 << error_code
388 << ", data:\n"
389 << data;
390 return NULL;
391 } 398 }
392 return root_value.release(); 399 }
400
401 void GetDataOperation::ParseResponse(GDataErrorCode fetch_error_code,
402 const std::string& data) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404
405 // Uses this hack to avoid deep-copy of json object because json might be so
406 // big. This pointer of scped_ptr is to ensure a deletion of the parsed json
407 // value object.
408 scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>();
409
410 BrowserThread::PostBlockingPoolTaskAndReply(
411 FROM_HERE,
412 base::Bind(&ParseJsonOnBlockingPool,
413 data,
414 parsed_value),
415 base::Bind(&GetDataOperation::OnDataParsed,
416 weak_ptr_factory_.GetWeakPtr(),
417 fetch_error_code,
418 base::Owned(parsed_value)));
419 }
420
421 void GetDataOperation::OnDataParsed(
422 gdata::GDataErrorCode fetch_error_code,
423 scoped_ptr<base::Value>* value) {
424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
425
426 bool success = true;
427 if (!value->get()) {
428 fetch_error_code = gdata::GDATA_PARSE_ERROR;
429 success = false;
430 }
431
432 // The ownership of the parsed json object is transfered to RunCallBack(),
433 // keeping the ownership of the |value| here.
434 RunCallback(fetch_error_code, value->Pass());
435
436 DCHECK(!value->get());
437
438 OnProcessURLFetchResultsComplete(success);
439 // |value| will be deleted after return beause it is base::Owned()'d.
440 }
441
442 void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code,
443 scoped_ptr<base::Value> value) {
444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445 if (!callback_.is_null())
446 callback_.Run(fetch_error_code, value.Pass());
393 } 447 }
394 448
395 } // namespace gdata 449 } // 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