OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |