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

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: fix reviews and rebase 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(
hashimoto 2012/07/25 06:14:21 Function comment is needed.
yoshiki 2012/07/25 17:24:27 Done.
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 } 170 }
123 171
124 //============================ UrlFetchOperationBase =========================== 172 //============================ UrlFetchOperationBase ===========================
125 173
126 UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry, 174 UrlFetchOperationBase::UrlFetchOperationBase(GDataOperationRegistry* registry,
127 Profile* profile) 175 Profile* profile)
128 : GDataOperationRegistry::Operation(registry), 176 : GDataOperationRegistry::Operation(registry),
129 profile_(profile), 177 profile_(profile),
130 re_authenticate_count_(0), 178 re_authenticate_count_(0),
131 save_temp_file_(false), 179 save_temp_file_(false),
132 started_(false) { 180 started_(false),
181 weak_ptr_factory_(this) {
133 } 182 }
134 183
135 UrlFetchOperationBase::UrlFetchOperationBase( 184 UrlFetchOperationBase::UrlFetchOperationBase(
136 GDataOperationRegistry* registry, 185 GDataOperationRegistry* registry,
137 GDataOperationRegistry::OperationType type, 186 GDataOperationRegistry::OperationType type,
138 const FilePath& path, 187 const FilePath& path,
139 Profile* profile) 188 Profile* profile)
140 : GDataOperationRegistry::Operation(registry, type, path), 189 : GDataOperationRegistry::Operation(registry, type, path),
141 profile_(profile), 190 profile_(profile),
142 re_authenticate_count_(0), 191 re_authenticate_count_(0),
143 save_temp_file_(false) { 192 save_temp_file_(false),
193 weak_ptr_factory_(this) {
144 } 194 }
145 195
146 UrlFetchOperationBase::~UrlFetchOperationBase() {} 196 UrlFetchOperationBase::~UrlFetchOperationBase() {}
147 197
148 void UrlFetchOperationBase::Start(const std::string& auth_token) { 198 void UrlFetchOperationBase::Start(const std::string& auth_token) {
149 DCHECK(!auth_token.empty()); 199 DCHECK(!auth_token.empty());
150 200
151 GURL url = GetURL(); 201 GURL url = GetURL();
152 DCHECK(!url.is_empty()); 202 DCHECK(!url.is_empty());
153 DVLOG(1) << "URL: " << url.spec(); 203 DVLOG(1) << "URL: " << url.spec();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 const URLFetcher* source) const { 273 const URLFetcher* source) const {
224 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode()); 274 GDataErrorCode code = static_cast<GDataErrorCode>(source->GetResponseCode());
225 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) { 275 if (code == HTTP_SUCCESS && !source->GetStatus().is_success()) {
226 // If the HTTP response code is SUCCESS yet the URL request failed, it is 276 // 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. 277 // likely that the failure is due to loss of connection.
228 code = GDATA_NO_CONNECTION; 278 code = GDATA_NO_CONNECTION;
229 } 279 }
230 return code; 280 return code;
231 } 281 }
232 282
283 void UrlFetchOperationBase::OnProcessURLFetchResultsComplete(bool result) {
284 if (result)
285 NotifySuccessToOperationRegistry();
286 else
287 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED);
288 }
289
233 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) { 290 void UrlFetchOperationBase::OnURLFetchComplete(const URLFetcher* source) {
234 GDataErrorCode code = GetErrorCode(source); 291 GDataErrorCode code = GetErrorCode(source);
235 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source); 292 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source);
236 293
237 if (code == HTTP_UNAUTHORIZED) { 294 if (code == HTTP_UNAUTHORIZED) {
238 if (!re_authenticate_callback_.is_null() && 295 if (!re_authenticate_callback_.is_null() &&
239 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) { 296 ++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerOperation) {
240 re_authenticate_callback_.Run(this); 297 re_authenticate_callback_.Run(this);
241 return; 298 return;
242 } 299 }
243 300
244 OnAuthFailed(code); 301 OnAuthFailed(code);
245 return; 302 return;
246 } 303 }
247 304
248 // Overridden by each specialization 305 // Overridden by each specialization
249 bool success = ProcessURLFetchResults(source); 306 ProcessURLFetchResults(
250 if (success) 307 source,
251 NotifySuccessToOperationRegistry(); 308 base::Bind(&UrlFetchOperationBase::OnProcessURLFetchResultsComplete,
252 else 309 weak_ptr_factory_.GetWeakPtr()));
253 NotifyFinish(GDataOperationRegistry::OPERATION_FAILED);
254 } 310 }
255 311
256 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() { 312 void UrlFetchOperationBase::NotifySuccessToOperationRegistry() {
257 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED); 313 NotifyFinish(GDataOperationRegistry::OPERATION_COMPLETED);
258 } 314 }
259 315
260 void UrlFetchOperationBase::NotifyStartToOperationRegistry() { 316 void UrlFetchOperationBase::NotifyStartToOperationRegistry() {
261 NotifyStart(); 317 NotifyStart();
262 } 318 }
263 319
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 Profile* profile, 359 Profile* profile,
304 const EntryActionCallback& callback, 360 const EntryActionCallback& callback,
305 const GURL& document_url) 361 const GURL& document_url)
306 : UrlFetchOperationBase(registry, profile), 362 : UrlFetchOperationBase(registry, profile),
307 callback_(callback), 363 callback_(callback),
308 document_url_(document_url) { 364 document_url_(document_url) {
309 } 365 }
310 366
311 EntryActionOperation::~EntryActionOperation() {} 367 EntryActionOperation::~EntryActionOperation() {}
312 368
313 bool EntryActionOperation::ProcessURLFetchResults( 369 void EntryActionOperation::ProcessURLFetchResults(
314 const URLFetcher* source) { 370 const URLFetcher* source,
371 const ProcessURLFetchResultsCallback& result_callback) {
315 if (!callback_.is_null()) { 372 if (!callback_.is_null()) {
316 GDataErrorCode code = GetErrorCode(source); 373 GDataErrorCode code = GetErrorCode(source);
317 callback_.Run(code, document_url_); 374 callback_.Run(code, document_url_);
318 } 375 }
319 return true; 376 result_callback.Run(true);
320 } 377 }
321 378
322 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) { 379 void EntryActionOperation::RunCallbackOnPrematureFailure(GDataErrorCode code) {
323 if (!callback_.is_null()) 380 if (!callback_.is_null())
324 callback_.Run(code, document_url_); 381 callback_.Run(code, document_url_);
325 } 382 }
326 383
327 //============================== GetDataOperation ============================== 384 //============================== GetDataOperation ==============================
328 385
329 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry, 386 GetDataOperation::GetDataOperation(GDataOperationRegistry* registry,
330 Profile* profile, 387 Profile* profile,
331 const GetDataCallback& callback) 388 const GetDataCallback& callback)
332 : UrlFetchOperationBase(registry, profile), callback_(callback) { 389 : UrlFetchOperationBase(registry, profile),
390 callback_(callback) {
333 } 391 }
334 392
335 GetDataOperation::~GetDataOperation() {} 393 GetDataOperation::~GetDataOperation() {}
336 394
337 bool GetDataOperation::ProcessURLFetchResults(const URLFetcher* source) { 395 void GetDataOperation::ProcessURLFetchResults(
396 const URLFetcher* source,
397 const ProcessURLFetchResultsCallback& result_callback) {
338 std::string data; 398 std::string data;
339 source->GetResponseAsString(&data); 399 source->GetResponseAsString(&data);
340 scoped_ptr<base::Value> root_value; 400 scoped_ptr<base::Value> root_value;
341 GDataErrorCode code = GetErrorCode(source); 401 GDataErrorCode fetch_error_code = GetErrorCode(source);
342 402
343 switch (code) { 403 switch (fetch_error_code) {
344 case HTTP_SUCCESS: 404 case HTTP_SUCCESS:
345 case HTTP_CREATED: { 405 case HTTP_CREATED:
346 root_value.reset(ParseResponse(data)); 406 ParseResponse(fetch_error_code, data, result_callback);
347 if (!root_value.get())
348 code = GDATA_PARSE_ERROR;
349
350 break; 407 break;
351 }
352 default: 408 default:
409 RunCallback(fetch_error_code, scoped_ptr<base::Value>());
410 result_callback.Run(false);
353 break; 411 break;
354 } 412 }
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 } 413 }
367 414
368 base::Value* GetDataOperation::ParseResponse(const std::string& data) { 415 void GetDataOperation::RunCallbackOnPrematureFailure(
369 int error_code = -1; 416 GDataErrorCode fetch_error_code) {
370 std::string error_message; 417 if (!callback_.is_null()) {
371 scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( 418 scoped_ptr<base::Value> root_value;
372 data, base::JSON_PARSE_RFC, &error_code, &error_message)); 419 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 } 420 }
382 return root_value.release(); 421 }
422
423 void GetDataOperation::ParseResponse(
424 GDataErrorCode fetch_error_code,
425 const std::string& data,
426 const ProcessURLFetchResultsCallback& result_callback) {
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
428
429 // Uses this hack to avoid deep-copy of json object because json might be so
430 // big.
431 // This pointer of scped_ptr is to ensure a deletion of the parsed json value
432 // object, even when OnDataParsed() is not called.
433 scoped_ptr<base::Value>* parsed_value = new scoped_ptr<base::Value>();
434
435 BrowserThread::PostBlockingPoolTaskAndReply(
436 FROM_HERE,
437 base::Bind(&ParseJsonOnBlockingPool,
438 data,
439 parsed_value),
440 base::Bind(&OnDataParsed,
441 fetch_error_code,
442 base::Owned(parsed_value),
443 callback_,
444 result_callback));
445 }
446
447 void GetDataOperation::RunCallback(GDataErrorCode fetch_error_code,
448 scoped_ptr<base::Value> value) {
449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
450 if (!callback_.is_null())
451 callback_.Run(fetch_error_code, value.Pass());
383 } 452 }
384 453
385 } // namespace gdata 454 } // namespace gdata
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698