| 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/google_apis/gdata_wapi_operations.h" | 5 #include "chrome/browser/google_apis/gdata_wapi_operations.h" |
| 6 | 6 |
| 7 #include "base/string_number_conversions.h" | 7 #include "base/string_number_conversions.h" |
| 8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
| 9 #include "base/values.h" | 9 #include "base/values.h" |
| 10 #include "chrome/browser/google_apis/gdata_wapi_parser.h" | 10 #include "chrome/browser/google_apis/gdata_wapi_parser.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 InitiateUploadParams::~InitiateUploadParams() { | 81 InitiateUploadParams::~InitiateUploadParams() { |
| 82 } | 82 } |
| 83 | 83 |
| 84 ResumeUploadParams::ResumeUploadParams( | 84 ResumeUploadParams::ResumeUploadParams( |
| 85 UploadMode upload_mode, | 85 UploadMode upload_mode, |
| 86 int64 start_position, | 86 int64 start_position, |
| 87 int64 end_position, | 87 int64 end_position, |
| 88 int64 content_length, | 88 int64 content_length, |
| 89 const std::string& content_type, | 89 const std::string& content_type, |
| 90 scoped_refptr<net::IOBuffer> buf, | 90 scoped_refptr<net::IOBuffer> buf, |
| 91 int64 buffer_offset, |
| 91 const GURL& upload_location, | 92 const GURL& upload_location, |
| 92 const FilePath& drive_file_path) : upload_mode(upload_mode), | 93 const FilePath& drive_file_path) : upload_mode(upload_mode), |
| 93 start_position(start_position), | 94 start_position(start_position), |
| 94 end_position(end_position), | 95 end_position(end_position), |
| 95 content_length(content_length), | 96 content_length(content_length), |
| 96 content_type(content_type), | 97 content_type(content_type), |
| 97 buf(buf), | 98 buf(buf), |
| 99 buffer_offset(buffer_offset), |
| 98 upload_location(upload_location), | 100 upload_location(upload_location), |
| 99 drive_file_path(drive_file_path) { | 101 drive_file_path(drive_file_path) { |
| 100 } | 102 } |
| 101 | 103 |
| 102 ResumeUploadParams::~ResumeUploadParams() { | 104 ResumeUploadParams::~ResumeUploadParams() { |
| 103 } | 105 } |
| 104 | 106 |
| 105 //============================ GetResourceListOperation ======================== | 107 //============================ GetResourceListOperation ======================== |
| 106 | 108 |
| 107 GetResourceListOperation::GetResourceListOperation( | 109 GetResourceListOperation::GetResourceListOperation( |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 "http://schemas.google.com/docs/2007"); | 665 "http://schemas.google.com/docs/2007"); |
| 664 xml_writer.WriteElement("title", params_.title); | 666 xml_writer.WriteElement("title", params_.title); |
| 665 xml_writer.EndElement(); // Ends "entry" element. | 667 xml_writer.EndElement(); // Ends "entry" element. |
| 666 xml_writer.StopWriting(); | 668 xml_writer.StopWriting(); |
| 667 upload_content->assign(xml_writer.GetWrittenString()); | 669 upload_content->assign(xml_writer.GetWrittenString()); |
| 668 DVLOG(1) << "Upload data: " << *upload_content_type << ", [" | 670 DVLOG(1) << "Upload data: " << *upload_content_type << ", [" |
| 669 << *upload_content << "]"; | 671 << *upload_content << "]"; |
| 670 return true; | 672 return true; |
| 671 } | 673 } |
| 672 | 674 |
| 673 //============================ ResumeUploadOperation =========================== | 675 namespace { |
| 674 | 676 |
| 675 ResumeUploadOperation::ResumeUploadOperation( | 677 bool ProcessURLFetchResultsImpl( |
| 676 OperationRegistry* registry, | 678 GDataErrorCode code, |
| 677 net::URLRequestContextGetter* url_request_context_getter, | 679 const URLFetcher* source, |
| 680 const FilePath& drive_file_path, |
| 678 const ResumeUploadCallback& callback, | 681 const ResumeUploadCallback& callback, |
| 679 const ResumeUploadParams& params) | 682 const ParseJsonCallback& json_callback) { |
| 680 : UrlFetchOperationBase(registry, | |
| 681 url_request_context_getter, | |
| 682 OPERATION_UPLOAD, | |
| 683 params.drive_file_path), | |
| 684 callback_(callback), | |
| 685 params_(params), | |
| 686 last_chunk_completed_(false), | |
| 687 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
| 688 DCHECK(!callback_.is_null()); | |
| 689 } | |
| 690 | |
| 691 ResumeUploadOperation::~ResumeUploadOperation() {} | |
| 692 | |
| 693 GURL ResumeUploadOperation::GetURL() const { | |
| 694 // This is very tricky to get json from this operation. To do that, &alt=json | |
| 695 // has to be appended not here but in InitiateUploadOperation::GetURL(). | |
| 696 return params_.upload_location; | |
| 697 } | |
| 698 | |
| 699 void ResumeUploadOperation::ProcessURLFetchResults(const URLFetcher* source) { | |
| 700 GDataErrorCode code = GetErrorCode(source); | |
| 701 net::HttpResponseHeaders* hdrs = source->GetResponseHeaders(); | 683 net::HttpResponseHeaders* hdrs = source->GetResponseHeaders(); |
| 702 | 684 |
| 703 if (code == HTTP_RESUME_INCOMPLETE) { | 685 if (code == HTTP_RESUME_INCOMPLETE) { |
| 704 // Retrieve value of the first "Range" header. | 686 // Retrieve value of the first "Range" header. |
| 705 int64 start_position_received = -1; | 687 int64 start_position_received = -1; |
| 706 int64 end_position_received = -1; | 688 int64 end_position_received = -1; |
| 707 std::string range_received; | 689 std::string range_received; |
| 708 hdrs->EnumerateHeader(NULL, kUploadResponseRange, &range_received); | 690 hdrs->EnumerateHeader(NULL, kUploadResponseRange, &range_received); |
| 709 if (!range_received.empty()) { // Parse the range header. | 691 if (!range_received.empty()) { // Parse the range header. |
| 710 std::vector<net::HttpByteRange> ranges; | 692 std::vector<net::HttpByteRange> ranges; |
| 711 if (net::HttpUtil::ParseRangeHeader(range_received, &ranges) && | 693 if (net::HttpUtil::ParseRangeHeader(range_received, &ranges) && |
| 712 !ranges.empty() ) { | 694 !ranges.empty() ) { |
| 713 // We only care about the first start-end pair in the range. | 695 // We only care about the first start-end pair in the range. |
| 714 // | 696 // |
| 715 // Range header represents the range inclusively, while we are treating | 697 // Range header represents the range inclusively, while we are treating |
| 716 // ranges exclusively (i.e., end_position_received should be one passed | 698 // ranges exclusively (i.e., end_position_received should be one passed |
| 717 // the last valid index). So "+ 1" is added. | 699 // the last valid index). So "+ 1" is added. |
| 718 start_position_received = ranges[0].first_byte_position(); | 700 start_position_received = ranges[0].first_byte_position(); |
| 719 end_position_received = ranges[0].last_byte_position() + 1; | 701 end_position_received = ranges[0].last_byte_position() + 1; |
| 720 } | 702 } |
| 721 } | 703 } |
| 722 DVLOG(1) << "Got response for [" << params_.drive_file_path.value() | 704 DVLOG(1) << "Got response for [" << drive_file_path.value() |
| 723 << "]: code=" << code | 705 << "]: code=" << code |
| 724 << ", range_hdr=[" << range_received | 706 << ", range_hdr=[" << range_received |
| 725 << "], range_parsed=" << start_position_received | 707 << "], range_parsed=" << start_position_received |
| 726 << "," << end_position_received; | 708 << "," << end_position_received; |
| 727 | 709 |
| 728 callback_.Run(ResumeUploadResponse(code, | 710 callback.Run(ResumeUploadResponse(code, |
| 729 start_position_received, | 711 start_position_received, |
| 730 end_position_received), | 712 end_position_received), |
| 731 scoped_ptr<ResourceEntry>()); | 713 scoped_ptr<ResourceEntry>()); |
| 714 return true; |
| 715 } |
| 732 | 716 |
| 733 OnProcessURLFetchResultsComplete(true); | 717 // There might be explanation of unexpected error code in response. |
| 734 } else { | 718 std::string response_content; |
| 735 // There might be explanation of unexpected error code in response. | 719 source->GetResponseAsString(&response_content); |
| 736 std::string response_content; | 720 DVLOG(1) << "Got response for [" << drive_file_path.value() |
| 737 source->GetResponseAsString(&response_content); | 721 << "]: code=" << code |
| 738 DVLOG(1) << "Got response for [" << params_.drive_file_path.value() | 722 << ", content=[\n" << response_content << "\n]"; |
| 739 << "]: code=" << code | |
| 740 << ", content=[\n" << response_content << "\n]"; | |
| 741 | 723 |
| 742 ParseJson(response_content, | 724 ParseJson(response_content, json_callback); |
| 743 base::Bind(&ResumeUploadOperation::OnDataParsed, | 725 return false; |
| 744 weak_ptr_factory_.GetWeakPtr(), | |
| 745 code)); | |
| 746 } | |
| 747 } | 726 } |
| 748 | 727 |
| 749 void ResumeUploadOperation::OnDataParsed(GDataErrorCode code, | 728 bool OnDataParsedImpl( |
| 750 scoped_ptr<base::Value> value) { | 729 UploadMode upload_mode, |
| 730 const ResumeUploadCallback& callback, |
| 731 GDataErrorCode code, |
| 732 scoped_ptr<base::Value> value) { |
| 751 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 733 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 752 | 734 |
| 753 // For a new file, HTTP_CREATED is returned. | |
| 754 // For an existing file, HTTP_SUCCESS is returned. | |
| 755 if ((params_.upload_mode == UPLOAD_NEW_FILE && code == HTTP_CREATED) || | |
| 756 (params_.upload_mode == UPLOAD_EXISTING_FILE && code == HTTP_SUCCESS)) { | |
| 757 last_chunk_completed_ = true; | |
| 758 } | |
| 759 | |
| 760 scoped_ptr<ResourceEntry> entry; | 735 scoped_ptr<ResourceEntry> entry; |
| 761 if (value.get()) | 736 if (value.get()) |
| 762 entry = ResourceEntry::ExtractAndParse(*(value.get())); | 737 entry = ResourceEntry::ExtractAndParse(*(value.get())); |
| 763 | 738 |
| 764 if (!entry.get()) | 739 if (!entry.get()) |
| 765 LOG(WARNING) << "Invalid entry received on upload."; | 740 LOG(WARNING) << "Invalid entry received on upload."; |
| 766 | 741 |
| 767 callback_.Run(ResumeUploadResponse(code, -1, -1), entry.Pass()); | 742 callback.Run(ResumeUploadResponse(code, -1, -1), entry.Pass()); |
| 743 |
| 744 // For a new file, HTTP_CREATED is returned. |
| 745 // For an existing file, HTTP_SUCCESS is returned. |
| 746 return (upload_mode == UPLOAD_NEW_FILE && code == HTTP_CREATED) || |
| 747 (upload_mode == UPLOAD_EXISTING_FILE && code == HTTP_SUCCESS); |
| 748 } |
| 749 |
| 750 } // namespace |
| 751 |
| 752 //============================ ResumeUploadOperation =========================== |
| 753 |
| 754 ResumeUploadOperation::ResumeUploadOperation( |
| 755 OperationRegistry* registry, |
| 756 net::URLRequestContextGetter* url_request_context_getter, |
| 757 const ResumeUploadCallback& callback, |
| 758 const ResumeUploadParams& params) |
| 759 : UrlFetchOperationBase(registry, |
| 760 url_request_context_getter, |
| 761 OPERATION_UPLOAD, |
| 762 params.drive_file_path), |
| 763 callback_(callback), |
| 764 params_(params), |
| 765 last_chunk_completed_(false), |
| 766 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 767 DCHECK(!callback_.is_null()); |
| 768 } |
| 769 |
| 770 ResumeUploadOperation::~ResumeUploadOperation() {} |
| 771 |
| 772 GURL ResumeUploadOperation::GetURL() const { |
| 773 // This is very tricky to get json from this operation. To do that, &alt=json |
| 774 // has to be appended not here but in InitiateUploadOperation::GetURL(). |
| 775 return params_.upload_location; |
| 776 } |
| 777 |
| 778 void ResumeUploadOperation::ProcessURLFetchResults(const URLFetcher* source) { |
| 779 GDataErrorCode code = GetErrorCode(source); |
| 780 if (ProcessURLFetchResultsImpl( |
| 781 code, source, params_.drive_file_path, callback_, |
| 782 base::Bind(&ResumeUploadOperation::OnDataParsed, |
| 783 weak_ptr_factory_.GetWeakPtr(), |
| 784 code))) { |
| 785 OnProcessURLFetchResultsComplete(true); |
| 786 } |
| 787 } |
| 788 |
| 789 void ResumeUploadOperation::OnDataParsed(GDataErrorCode code, |
| 790 scoped_ptr<base::Value> value) { |
| 791 last_chunk_completed_ = OnDataParsedImpl( |
| 792 params_.upload_mode, callback_, code, value.Pass()); |
| 768 OnProcessURLFetchResultsComplete(last_chunk_completed_); | 793 OnProcessURLFetchResultsComplete(last_chunk_completed_); |
| 769 } | 794 } |
| 770 | 795 |
| 771 void ResumeUploadOperation::NotifyStartToOperationRegistry() { | 796 void ResumeUploadOperation::NotifyStartToOperationRegistry() { |
| 772 NotifyResume(); | 797 NotifyResume(); |
| 773 } | 798 } |
| 774 | 799 |
| 775 void ResumeUploadOperation::NotifySuccessToOperationRegistry() { | 800 void ResumeUploadOperation::NotifySuccessToOperationRegistry() { |
| 776 if (last_chunk_completed_) | 801 if (last_chunk_completed_) |
| 777 NotifyFinish(OPERATION_COMPLETED); | 802 NotifyFinish(OPERATION_COMPLETED); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 base::Int64ToString(params_.start_position) + "-" + | 837 base::Int64ToString(params_.start_position) + "-" + |
| 813 base::Int64ToString(params_.end_position - 1) + "/" + | 838 base::Int64ToString(params_.end_position - 1) + "/" + |
| 814 (params_.content_length == -1 ? "*" : | 839 (params_.content_length == -1 ? "*" : |
| 815 base::Int64ToString(params_.content_length))); | 840 base::Int64ToString(params_.content_length))); |
| 816 return headers; | 841 return headers; |
| 817 } | 842 } |
| 818 | 843 |
| 819 bool ResumeUploadOperation::GetContentData(std::string* upload_content_type, | 844 bool ResumeUploadOperation::GetContentData(std::string* upload_content_type, |
| 820 std::string* upload_content) { | 845 std::string* upload_content) { |
| 821 *upload_content_type = params_.content_type; | 846 *upload_content_type = params_.content_type; |
| 822 *upload_content = std::string(params_.buf->data(), | 847 *upload_content = std::string(params_.buf->data() + params_.buffer_offset, |
| 823 params_.end_position - params_.start_position); | 848 params_.end_position - params_.start_position); |
| 824 return true; | 849 return true; |
| 825 } | 850 } |
| 826 | 851 |
| 827 void ResumeUploadOperation::OnURLFetchUploadProgress( | 852 void ResumeUploadOperation::OnURLFetchUploadProgress( |
| 828 const URLFetcher* source, int64 current, int64 total) { | 853 const URLFetcher* source, int64 current, int64 total) { |
| 829 // Adjust the progress values according to the range currently uploaded. | 854 // Adjust the progress values according to the range currently uploaded. |
| 830 NotifyProgress(params_.start_position + current, params_.content_length); | 855 NotifyProgress(params_.start_position + current, params_.content_length); |
| 831 } | 856 } |
| 832 | 857 |
| 858 //============================ GetUploadStateOperation ========================= |
| 859 |
| 860 GetUploadStateOperation::GetUploadStateOperation( |
| 861 OperationRegistry* registry, |
| 862 net::URLRequestContextGetter* url_request_context_getter, |
| 863 const ResumeUploadCallback& callback, |
| 864 const UploadMode upload_mode, |
| 865 const FilePath& drive_file_path, |
| 866 const GURL& upload_url, |
| 867 int64 content_length) |
| 868 : UrlFetchOperationBase(registry, url_request_context_getter), |
| 869 callback_(callback), |
| 870 upload_mode_(upload_mode), |
| 871 drive_file_path_(drive_file_path), |
| 872 upload_url_(upload_url), |
| 873 content_length_(content_length), |
| 874 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 875 } |
| 876 |
| 877 GetUploadStateOperation::~GetUploadStateOperation() { |
| 878 } |
| 879 |
| 880 GURL GetUploadStateOperation::GetURL() const { |
| 881 return upload_url_; |
| 882 } |
| 883 |
| 884 net::URLFetcher::RequestType GetUploadStateOperation::GetRequestType() const { |
| 885 return net::URLFetcher::PUT_WITHOUT_BODY; |
| 886 } |
| 887 |
| 888 void GetUploadStateOperation::ProcessURLFetchResults( |
| 889 const net::URLFetcher* source) { |
| 890 GDataErrorCode code = GetErrorCode(source); |
| 891 if (ProcessURLFetchResultsImpl( |
| 892 code, source, drive_file_path_, callback_, |
| 893 base::Bind(&GetUploadStateOperation::OnDataParsed, |
| 894 weak_ptr_factory_.GetWeakPtr(), |
| 895 code))) { |
| 896 OnProcessURLFetchResultsComplete(true); |
| 897 } |
| 898 } |
| 899 |
| 900 void GetUploadStateOperation::RunCallbackOnPrematureFailure( |
| 901 GDataErrorCode code) { |
| 902 callback_.Run(ResumeUploadResponse(code, 0, 0), scoped_ptr<ResourceEntry>()); |
| 903 } |
| 904 |
| 905 std::vector<std::string> |
| 906 GetUploadStateOperation::GetExtraRequestHeaders() const { |
| 907 // The header looks like |
| 908 // Content-Range: bytes */<content_length> |
| 909 // for example: |
| 910 // Content-Range: bytes */13851821 |
| 911 // Use * for unknown/streaming content length. |
| 912 // The header takes inclusive range, so we adjust by "end_position - 1". |
| 913 DCHECK_GE(content_length_, -1); |
| 914 |
| 915 std::vector<std::string> headers; |
| 916 headers.push_back( |
| 917 std::string(kUploadContentRange) + "*/" + |
| 918 (content_length_ == -1 ? "*" : base::Int64ToString(content_length_))); |
| 919 return headers; |
| 920 } |
| 921 |
| 922 void GetUploadStateOperation::OnDataParsed( |
| 923 GDataErrorCode code, scoped_ptr<base::Value> value) { |
| 924 OnProcessURLFetchResultsComplete( |
| 925 OnDataParsedImpl( |
| 926 upload_mode_, callback_, code, value.Pass())); |
| 927 } |
| 928 |
| 833 } // namespace google_apis | 929 } // namespace google_apis |
| OLD | NEW |