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

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

Issue 9662041: Implement copy and move operations within the same remote file system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: rebase to HEAD Created 8 years, 9 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/gdata.h" 5 #include "chrome/browser/chromeos/gdata/gdata.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 17 matching lines...) Expand all
28 #include "chrome/browser/signin/token_service.h" 28 #include "chrome/browser/signin/token_service.h"
29 #include "chrome/browser/signin/token_service_factory.h" 29 #include "chrome/browser/signin/token_service_factory.h"
30 #include "chrome/common/chrome_notification_types.h" 30 #include "chrome/common/chrome_notification_types.h"
31 #include "chrome/common/libxml_utils.h" 31 #include "chrome/common/libxml_utils.h"
32 #include "chrome/common/net/gaia/gaia_constants.h" 32 #include "chrome/common/net/gaia/gaia_constants.h"
33 #include "chrome/common/net/gaia/gaia_urls.h" 33 #include "chrome/common/net/gaia/gaia_urls.h"
34 #include "content/public/browser/browser_thread.h" 34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/notification_details.h" 35 #include "content/public/browser/notification_details.h"
36 #include "content/public/browser/notification_source.h" 36 #include "content/public/browser/notification_source.h"
37 #include "content/public/browser/notification_types.h" 37 #include "content/public/browser/notification_types.h"
38 #include "net/base/escape.h"
38 #include "net/base/file_stream.h" 39 #include "net/base/file_stream.h"
39 #include "net/base/load_flags.h" 40 #include "net/base/load_flags.h"
40 #include "net/http/http_response_headers.h" 41 #include "net/http/http_response_headers.h"
41 #include "net/http/http_util.h" 42 #include "net/http/http_util.h"
42 43
43 using content::BrowserThread; 44 using content::BrowserThread;
44 using content::URLFetcher; 45 using content::URLFetcher;
45 using content::URLFetcherDelegate; 46 using content::URLFetcherDelegate;
46 47
47 namespace gdata { 48 namespace gdata {
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 callback_(callback), 328 callback_(callback),
328 // MessageLoopProxy is used to run |callback| on the origin thread. 329 // MessageLoopProxy is used to run |callback| on the origin thread.
329 relay_proxy_(base::MessageLoopProxy::current()), 330 relay_proxy_(base::MessageLoopProxy::current()),
330 re_authenticate_count_(0), 331 re_authenticate_count_(0),
331 save_temp_file_(false) { 332 save_temp_file_(false) {
332 } 333 }
333 334
334 // Overridden from GDataOperationInterface. 335 // Overridden from GDataOperationInterface.
335 virtual void Start(const std::string& auth_token) OVERRIDE { 336 virtual void Start(const std::string& auth_token) OVERRIDE {
336 DCHECK(!auth_token.empty()); 337 DCHECK(!auth_token.empty());
338
337 GURL url = GetURL(); 339 GURL url = GetURL();
338 url_fetcher_.reset(URLFetcher::Create( 340 DCHECK(!url.is_empty());
339 url, GetRequestType(), this)); 341 DVLOG(1) << "URL: " << url.spec();
342
343 url_fetcher_.reset(URLFetcher::Create(url, GetRequestType(), this));
340 url_fetcher_->SetRequestContext(profile_->GetRequestContext()); 344 url_fetcher_->SetRequestContext(profile_->GetRequestContext());
341 // Always set flags to neither send nor save cookies. 345 // Always set flags to neither send nor save cookies.
342 url_fetcher_->SetLoadFlags( 346 url_fetcher_->SetLoadFlags(
343 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); 347 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
344 if (save_temp_file_) { 348 if (save_temp_file_) {
345 url_fetcher_->SaveResponseToTemporaryFile( 349 url_fetcher_->SaveResponseToTemporaryFile(
346 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 350 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
347 } 351 }
348 352
349 // Add request headers. 353 // Add request headers.
350 // Note that SetExtraRequestHeaders clears the current headers and sets it 354 // Note that SetExtraRequestHeaders clears the current headers and sets it
351 // to the passed-in headers, so calling it for each header will result in 355 // to the passed-in headers, so calling it for each header will result in
352 // only the last header being set in request headers. 356 // only the last header being set in request headers.
353 url_fetcher_->AddExtraRequestHeader(kGDataVersionHeader); 357 url_fetcher_->AddExtraRequestHeader(kGDataVersionHeader);
354 url_fetcher_->AddExtraRequestHeader( 358 url_fetcher_->AddExtraRequestHeader(
355 base::StringPrintf(kAuthorizationHeaderFormat, auth_token.data())); 359 base::StringPrintf(kAuthorizationHeaderFormat, auth_token.data()));
356 std::vector<std::string> headers = GetExtraRequestHeaders(); 360 std::vector<std::string> headers = GetExtraRequestHeaders();
357 for (size_t i = 0; i < headers.size(); ++i) { 361 for (size_t i = 0; i < headers.size(); ++i) {
358 url_fetcher_->AddExtraRequestHeader(headers[i]); 362 url_fetcher_->AddExtraRequestHeader(headers[i]);
359 DVLOG(1) << "Extra header " << headers[i]; 363 DVLOG(1) << "Extra header: " << headers[i];
360 } 364 }
361 365
362 // Set upload data if available. 366 // Set upload data if available.
363 std::string upload_content_type; 367 std::string upload_content_type;
364 std::string upload_content; 368 std::string upload_content;
365 if (GetContentData(&upload_content_type, &upload_content)) { 369 if (GetContentData(&upload_content_type, &upload_content)) {
366 url_fetcher_->SetUploadData(upload_content_type, upload_content); 370 url_fetcher_->SetUploadData(upload_content_type, upload_content);
367 } 371 }
368 372
369 // Register to operation registry. 373 // Register to operation registry.
370 NotifyStart(); 374 NotifyStart();
371 375
372 url_fetcher_->Start(); 376 url_fetcher_->Start();
373 } 377 }
374 378
375 // Overridden from GDataOperationInterface. 379 // Overridden from GDataOperationInterface.
376 virtual void SetReAuthenticateCallback( 380 virtual void SetReAuthenticateCallback(
377 const ReAuthenticateCallback& callback) OVERRIDE { 381 const ReAuthenticateCallback& callback) OVERRIDE {
378 DCHECK(re_authenticate_callback_.is_null()); 382 DCHECK(re_authenticate_callback_.is_null());
379 383
380 re_authenticate_callback_ = callback; 384 re_authenticate_callback_ = callback;
381 } 385 }
382 386
383 protected: 387 protected:
384 virtual ~UrlFetchOperation() {} 388 virtual ~UrlFetchOperation() {}
385 // Gets URL for GET request. 389 // Gets URL for the request.
386 virtual GURL GetURL() const = 0; 390 virtual GURL GetURL() const = 0;
391 // Returns the request type. A derived class should override this method
392 // for a request type other than HTTP GET.
387 virtual URLFetcher::RequestType GetRequestType() const { 393 virtual URLFetcher::RequestType GetRequestType() const {
388 return URLFetcher::GET; 394 return URLFetcher::GET;
389 } 395 }
396 // Returns the extra HTTP headers for the request. A derived class should
397 // override this method to specify any extra headers needed for the request.
390 virtual std::vector<std::string> GetExtraRequestHeaders() const { 398 virtual std::vector<std::string> GetExtraRequestHeaders() const {
391 return std::vector<std::string>(); 399 return std::vector<std::string>();
392 } 400 }
401 // Used by a derived class to add any content data to the request.
402 // Returns true if |upload_content_type| and |upload_content| are updated
403 // with the content type and data for the request.
393 virtual bool GetContentData(std::string* upload_content_type, 404 virtual bool GetContentData(std::string* upload_content_type,
394 std::string* upload_content) { 405 std::string* upload_content) {
395 return false; 406 return false;
396 } 407 }
397 408
398 // Invoked by OnURLFetchComplete when the operation completes without an 409 // Invoked by OnURLFetchComplete when the operation completes without an
399 // authentication error. Must be implemented by a derived class. 410 // authentication error. Must be implemented by a derived class.
400 virtual void ProcessURLFetchResults(const URLFetcher* source) = 0; 411 virtual void ProcessURLFetchResults(const URLFetcher* source) = 0;
401 412
402 // Invoked by this base class upon an authentication error. 413 // Invoked by this base class upon an authentication error.
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 xml_writer.WriteElement("title", directory_name_); 788 xml_writer.WriteElement("title", directory_name_);
778 789
779 xml_writer.EndElement(); // Ends "entry" element. 790 xml_writer.EndElement(); // Ends "entry" element.
780 xml_writer.StopWriting(); 791 xml_writer.StopWriting();
781 upload_content->assign(xml_writer.GetWrittenString()); 792 upload_content->assign(xml_writer.GetWrittenString());
782 DVLOG(1) << "CreateDirectory data: " << *upload_content_type << ", [" 793 DVLOG(1) << "CreateDirectory data: " << *upload_content_type << ", ["
783 << *upload_content << "]"; 794 << *upload_content << "]";
784 return true; 795 return true;
785 } 796 }
786 797
798 //=========================== CopyDocumentOperation ============================
799
800 // Operation for making a copy of a document.
801 class CopyDocumentOperation : public GetDataOperation {
802 public:
803 CopyDocumentOperation(GDataOperationRegistry* registry,
804 Profile* profile,
805 const GetDataCallback& callback,
806 const GURL& document_url,
807 const FilePath::StringType& new_name);
808 virtual ~CopyDocumentOperation() {}
809
810 private:
811 // Overridden from GetDataOperation.
812 virtual URLFetcher::RequestType GetRequestType() const OVERRIDE;
813
814 // Overridden from UrlFetchOperation.
815 virtual GURL GetURL() const OVERRIDE;
816 virtual bool GetContentData(std::string* upload_content_type,
817 std::string* upload_content) OVERRIDE;
818
819 GURL document_url_;
820 FilePath::StringType new_name_;
821
822 DISALLOW_COPY_AND_ASSIGN(CopyDocumentOperation);
823 };
824
825 CopyDocumentOperation::CopyDocumentOperation(
826 GDataOperationRegistry* registry,
827 Profile* profile,
828 const GetDataCallback& callback,
829 const GURL& document_url,
830 const FilePath::StringType& new_name)
831 : GetDataOperation(registry, profile, callback),
832 document_url_(document_url),
833 new_name_(new_name) {
834 }
835
836 URLFetcher::RequestType CopyDocumentOperation::GetRequestType() const {
837 return URLFetcher::POST;
838 }
839
840 GURL CopyDocumentOperation::GetURL() const {
841 return AddStandardUrlParams(GURL(kDocumentListRootURL));
842 }
843
844 bool CopyDocumentOperation::GetContentData(std::string* upload_content_type,
845 std::string* upload_content) {
846 upload_content_type->assign("application/atom+xml");
847 XmlWriter xml_writer;
848 xml_writer.StartWriting();
849 xml_writer.StartElement("entry");
850 xml_writer.AddAttribute("xmlns", "http://www.w3.org/2005/Atom");
851
852 xml_writer.WriteElement("id", document_url_.spec());
853 xml_writer.WriteElement("title", new_name_);
854
855 xml_writer.EndElement(); // Ends "entry" element.
856 xml_writer.StopWriting();
857 upload_content->assign(xml_writer.GetWrittenString());
858 DVLOG(1) << "CopyDocumentOperation data: " << *upload_content_type << ", ["
859 << *upload_content << "]";
860 return true;
861 }
862
863 //=========================== RenameResourceOperation ==========================
864
865 class RenameResourceOperation : public EntryActionOperation {
866 public:
867 RenameResourceOperation(GDataOperationRegistry* registry,
868 Profile* profile,
869 const EntryActionCallback& callback,
870 const GURL& document_url,
871 const FilePath::StringType& new_name);
872 virtual ~RenameResourceOperation() {}
873
874 private:
875 // Overridden from EntryActionOperation.
876 virtual URLFetcher::RequestType GetRequestType() const OVERRIDE;
877 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
878
879 // Overridden from UrlFetchOperation.
880 virtual bool GetContentData(std::string* upload_content_type,
881 std::string* upload_content) OVERRIDE;
882
883 FilePath::StringType new_name_;
884
885 DISALLOW_COPY_AND_ASSIGN(RenameResourceOperation);
886 };
887
888 RenameResourceOperation::RenameResourceOperation(
889 GDataOperationRegistry* registry,
890 Profile* profile,
891 const EntryActionCallback& callback,
892 const GURL& document_url,
893 const FilePath::StringType& new_name)
894 : EntryActionOperation(registry, profile, callback, document_url),
895 new_name_(new_name) {
896 }
897
898 URLFetcher::RequestType RenameResourceOperation::GetRequestType() const {
899 return URLFetcher::PUT;
900 }
901
902 std::vector<std::string>
903 RenameResourceOperation::GetExtraRequestHeaders() const {
904 std::vector<std::string> headers;
905 headers.push_back(kIfMatchAllHeader);
906 return headers;
907 }
908
909 bool RenameResourceOperation::GetContentData(std::string* upload_content_type,
910 std::string* upload_content) {
911 upload_content_type->assign("application/atom+xml");
912 XmlWriter xml_writer;
913 xml_writer.StartWriting();
914 xml_writer.StartElement("entry");
915 xml_writer.AddAttribute("xmlns", "http://www.w3.org/2005/Atom");
916
917 xml_writer.WriteElement("title", new_name_);
918
919 xml_writer.EndElement(); // Ends "entry" element.
920 xml_writer.StopWriting();
921 upload_content->assign(xml_writer.GetWrittenString());
922 DVLOG(1) << "RenameResourceOperation data: " << *upload_content_type << ", ["
923 << *upload_content << "]";
924 return true;
925 }
926
927 //=========================== AddResourceToDirectoryOperation ==================
928
929 class AddResourceToDirectoryOperation : public EntryActionOperation {
930 public:
931 AddResourceToDirectoryOperation(GDataOperationRegistry* registry,
932 Profile* profile,
933 const EntryActionCallback& callback,
934 const GURL& parent_content_url,
935 const GURL& document_url);
936 virtual ~AddResourceToDirectoryOperation() {}
937
938 private:
939 // Overridden from EntryActionOperation.
940 virtual GURL GetURL() const OVERRIDE;
941
942 // Overridden from UrlFetchOperation.
943 virtual URLFetcher::RequestType GetRequestType() const OVERRIDE;
944 virtual bool GetContentData(std::string* upload_content_type,
945 std::string* upload_content) OVERRIDE;
946
947 const GURL parent_content_url_;
948
949 DISALLOW_COPY_AND_ASSIGN(AddResourceToDirectoryOperation);
950 };
951
952 AddResourceToDirectoryOperation::AddResourceToDirectoryOperation(
953 GDataOperationRegistry* registry,
954 Profile* profile,
955 const EntryActionCallback& callback,
956 const GURL& parent_content_url,
957 const GURL& document_url)
958 : EntryActionOperation(registry, profile, callback, document_url),
959 parent_content_url_(parent_content_url) {
960 }
961
962 GURL AddResourceToDirectoryOperation::GetURL() const {
963 if (!parent_content_url_.is_empty())
964 return AddStandardUrlParams(parent_content_url_);
965
966 return AddStandardUrlParams(GURL(kDocumentListRootURL));
967 }
968
969 URLFetcher::RequestType
970 AddResourceToDirectoryOperation::GetRequestType() const {
971 return URLFetcher::POST;
972 }
973
974 bool AddResourceToDirectoryOperation::GetContentData(
975 std::string* upload_content_type, std::string* upload_content) {
976 upload_content_type->assign("application/atom+xml");
977 XmlWriter xml_writer;
978 xml_writer.StartWriting();
979 xml_writer.StartElement("entry");
980 xml_writer.AddAttribute("xmlns", "http://www.w3.org/2005/Atom");
981
982 xml_writer.WriteElement("id", document_url_.spec());
983
984 xml_writer.EndElement(); // Ends "entry" element.
985 xml_writer.StopWriting();
986 upload_content->assign(xml_writer.GetWrittenString());
987 DVLOG(1) << "AddResourceToDirectoryOperation data: " << *upload_content_type
988 << ", [" << *upload_content << "]";
989 return true;
990 }
991
992 //=========================== RemoveResourceFromDirectoryOperation =============
993
994 class RemoveResourceFromDirectoryOperation : public EntryActionOperation {
995 public:
996 RemoveResourceFromDirectoryOperation(GDataOperationRegistry* registry,
997 Profile* profile,
998 const EntryActionCallback& callback,
999 const GURL& parent_content_url,
1000 const GURL& document_url,
1001 const std::string& resource_id);
1002 virtual ~RemoveResourceFromDirectoryOperation() {}
1003
1004 private:
1005 // Overridden from EntryActionOperation.
1006 virtual GURL GetURL() const OVERRIDE;
1007
1008 // Overridden from UrlFetchOperation.
1009 virtual URLFetcher::RequestType GetRequestType() const OVERRIDE;
1010 virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
1011
1012 const std::string resource_id_;
1013 const GURL parent_content_url_;
1014
1015 DISALLOW_COPY_AND_ASSIGN(RemoveResourceFromDirectoryOperation);
1016 };
1017
1018 RemoveResourceFromDirectoryOperation::RemoveResourceFromDirectoryOperation(
1019 GDataOperationRegistry* registry,
1020 Profile* profile,
1021 const EntryActionCallback& callback,
1022 const GURL& parent_content_url,
1023 const GURL& document_url,
1024 const std::string& document_resource_id)
1025 : EntryActionOperation(registry, profile, callback, document_url),
1026 resource_id_(document_resource_id),
1027 parent_content_url_(parent_content_url) {
1028 }
1029
1030 GURL RemoveResourceFromDirectoryOperation::GetURL() const {
1031 std::string escaped_resource_id = net::EscapePath(resource_id_);
1032 GURL edit_url(base::StringPrintf("%s/%s",
1033 parent_content_url_.spec().c_str(),
1034 escaped_resource_id.c_str()));
1035 return AddStandardUrlParams(edit_url);
1036 }
1037
1038 URLFetcher::RequestType
1039 RemoveResourceFromDirectoryOperation::GetRequestType() const {
1040 return URLFetcher::DELETE_REQUEST;
1041 }
1042
1043 std::vector<std::string>
1044 RemoveResourceFromDirectoryOperation::GetExtraRequestHeaders() const {
1045 std::vector<std::string> headers;
1046 headers.push_back(kIfMatchAllHeader);
1047 return headers;
1048 }
1049
787 //=========================== InitiateUploadOperation ========================== 1050 //=========================== InitiateUploadOperation ==========================
788 1051
789 class InitiateUploadOperation 1052 class InitiateUploadOperation
790 : public UrlFetchOperation<InitiateUploadCallback> { 1053 : public UrlFetchOperation<InitiateUploadCallback> {
791 public: 1054 public:
792 InitiateUploadOperation(GDataOperationRegistry* registry, 1055 InitiateUploadOperation(GDataOperationRegistry* registry,
793 Profile* profile, 1056 Profile* profile,
794 const InitiateUploadCallback& callback, 1057 const InitiateUploadCallback& callback,
795 const InitiateUploadParams& params); 1058 const InitiateUploadParams& params);
796 1059
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 void DocumentsService::CreateDirectory( 1459 void DocumentsService::CreateDirectory(
1197 const GURL& parent_content_url, 1460 const GURL& parent_content_url,
1198 const FilePath::StringType& directory_name, 1461 const FilePath::StringType& directory_name,
1199 const GetDataCallback& callback) { 1462 const GetDataCallback& callback) {
1200 StartOperationOnUIThread( 1463 StartOperationOnUIThread(
1201 new CreateDirectoryOperation(operation_registry_.get(), profile_, 1464 new CreateDirectoryOperation(operation_registry_.get(), profile_,
1202 callback, parent_content_url, 1465 callback, parent_content_url,
1203 directory_name)); 1466 directory_name));
1204 } 1467 }
1205 1468
1469 void DocumentsService::CopyDocument(const GURL& document_url,
1470 const FilePath::StringType& new_name,
1471 const GetDataCallback& callback) {
1472 StartOperationOnUIThread(
1473 new CopyDocumentOperation(operation_registry_.get(), profile_, callback,
1474 document_url, new_name));
1475 }
1476
1477 void DocumentsService::RenameResource(const GURL& resource_url,
1478 const FilePath::StringType& new_name,
1479 const EntryActionCallback& callback) {
1480 StartOperationOnUIThread(
1481 new RenameResourceOperation(operation_registry_.get(), profile_, callback,
1482 resource_url, new_name));
1483 }
1484
1485 void DocumentsService::AddResourceToDirectory(
1486 const GURL& parent_content_url,
1487 const GURL& resource_url,
1488 const EntryActionCallback& callback) {
1489 StartOperationOnUIThread(
1490 new AddResourceToDirectoryOperation(operation_registry_.get(),
1491 profile_,
1492 callback,
1493 parent_content_url,
1494 resource_url));
1495 }
1496
1497 void DocumentsService::RemoveResourceFromDirectory(
1498 const GURL& parent_content_url,
1499 const GURL& resource_url,
1500 const std::string& resource_id,
1501 const EntryActionCallback& callback) {
1502 StartOperationOnUIThread(
1503 new RemoveResourceFromDirectoryOperation(operation_registry_.get(),
1504 profile_,
1505 callback,
1506 parent_content_url,
1507 resource_url,
1508 resource_id));
1509 }
1510
1206 void DocumentsService::InitiateUpload(const InitiateUploadParams& params, 1511 void DocumentsService::InitiateUpload(const InitiateUploadParams& params,
1207 const InitiateUploadCallback& callback) { 1512 const InitiateUploadCallback& callback) {
1208 if (params.resumable_create_media_link.is_empty()) { 1513 if (params.resumable_create_media_link.is_empty()) {
1209 if (!callback.is_null()) { 1514 if (!callback.is_null()) {
1210 callback.Run(HTTP_BAD_REQUEST, GURL()); 1515 callback.Run(HTTP_BAD_REQUEST, GURL());
1211 } 1516 }
1212 return; 1517 return;
1213 } 1518 }
1214 1519
1215 StartOperationOnUIThread( 1520 StartOperationOnUIThread(
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 void DocumentsService::RetryOperation(GDataOperationInterface* operation) { 1579 void DocumentsService::RetryOperation(GDataOperationInterface* operation) {
1275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1276 1581
1277 gdata_auth_service_->ClearOAuth2Token(); 1582 gdata_auth_service_->ClearOAuth2Token();
1278 // User authentication might have expired - rerun the request to force 1583 // User authentication might have expired - rerun the request to force
1279 // auth token refresh. 1584 // auth token refresh.
1280 StartOperation(operation); 1585 StartOperation(operation);
1281 } 1586 }
1282 1587
1283 } // namespace gdata 1588 } // namespace gdata
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata.h ('k') | chrome/browser/chromeos/gdata/gdata_file_system.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698