17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// found in the LICENSE file. 47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/local_discovery/privet_url_fetcher.h" 67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <algorithm> 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/bind.h" 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/json/json_reader.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/singleton.h" 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/message_loop/message_loop.h" 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/rand_util.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/browser_process.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/local_discovery/privet_constants.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/http/http_status_code.h" 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/url_request/url_request_status.h" 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace local_discovery { 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)typedef std::map<std::string, std::string> TokenMap; 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct TokenMapHolder { 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public: 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static TokenMapHolder* GetInstance() { 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return Singleton<TokenMapHolder>::get(); 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TokenMap map; 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; 376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kXPrivetAuthTokenHeaderPrefix[] = "X-Privet-Auth: "; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kRangeHeaderFormat[] = "Range: bytes=%d-%d"; 398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char kXPrivetEmptyToken[] = "\"\""; 406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kPrivetAuthTokenUnknown[] = "Unknown"; 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kPrivetMaxRetries = 20; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int kPrivetTimeoutOnError = 5; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kHTTPErrorCodeInvalidXPrivetToken = 418; 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string MakeRangeHeader(int start, int end) { 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GE(start, 0); 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GT(end, 0); 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GT(end, start); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::StringPrintf(kRangeHeaderFormat, start, end); 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void PrivetURLFetcher::Delegate::OnNeedPrivetToken( 550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) PrivetURLFetcher* fetcher, 560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const TokenCallback& callback) { 570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) OnError(fetcher, TOKEN_ERROR); 580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)std::string PrivetURLFetcher::Delegate::GetAuthToken() { 616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return kPrivetAuthTokenUnknown; 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PrivetURLFetcher::Delegate::OnRawData(PrivetURLFetcher* fetcher, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool response_is_file, 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& data_string, 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& data_file) { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPrivetURLFetcher::PrivetURLFetcher( 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const GURL& url, 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch net::URLFetcher::RequestType request_type, 747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch net::URLRequestContextGetter* request_context, 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PrivetURLFetcher::Delegate* delegate) 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : url_(url), 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_type_(request_type), 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_context_(request_context), 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_(delegate), 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) do_not_retry_on_transient_error_(false), 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch send_empty_privet_token_(false), 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) has_byte_range_(false), 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) make_response_file_(false), 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) v3_mode_(false), 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) byte_range_start_(0), 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) byte_range_end_(0), 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tries_(0), 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) weak_factory_(this) { 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPrivetURLFetcher::~PrivetURLFetcher() { 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PrivetURLFetcher::SetTokenForHost(const std::string& host, 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& token) { 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TokenMapHolder::GetInstance()->map[host] = token; 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PrivetURLFetcher::ResetTokenMapForTests() { 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TokenMapHolder::GetInstance()->map.clear(); 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void PrivetURLFetcher::DoNotRetryOnTransientError() { 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(tries_ == 0); 1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) do_not_retry_on_transient_error_ = true; 1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid PrivetURLFetcher::SendEmptyPrivetToken() { 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(tries_ == 0); 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch send_empty_privet_token_ = true; 1130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string PrivetURLFetcher::GetPrivetAccessToken() { 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (send_empty_privet_token_) { 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return std::string(); 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TokenMapHolder* token_map_holder = TokenMapHolder::GetInstance(); 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TokenMap::iterator found = token_map_holder->map.find(GetHostString()); 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return found != token_map_holder->map.end() ? found->second : std::string(); 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string PrivetURLFetcher::GetHostString() { 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return url_.GetOrigin().spec(); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrivetURLFetcher::SaveResponseToFile() { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(tries_ == 0); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) make_response_file_ = true; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void PrivetURLFetcher::V3Mode() { 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) v3_mode_ = true; 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrivetURLFetcher::SetByteRange(int start, int end) { 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(tries_ == 0); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) byte_range_start_ = start; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) byte_range_end_ = end; 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) has_byte_range_ = true; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void PrivetURLFetcher::Try() { 1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) tries_++; 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (tries_ < kPrivetMaxRetries) { 1480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_fetcher_->SetRequestContext(request_context_.get()); 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (v3_mode_) { 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string auth_token = delegate_->GetAuthToken(); 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url_fetcher_->AddExtraRequestHeader( 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string(kXPrivetAuthTokenHeaderPrefix) + auth_token); 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string token = GetPrivetAccessToken(); 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (token.empty()) 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) token = kXPrivetEmptyToken; 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) url_fetcher_->AddExtraRequestHeader( 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string(kXPrivetTokenHeaderPrefix) + token); 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (has_byte_range_) { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_->AddExtraRequestHeader( 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MakeRangeHeader(byte_range_start_, byte_range_end_)); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (make_response_file_) { 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_fetcher_->SaveResponseToTemporaryFile( 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::GetMessageLoopProxyForThread( 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::FILE)); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // URLFetcher requires us to set upload data for POST requests. 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (request_type_ == net::URLFetcher::POST) { 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!upload_file_path_.empty()) { 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) url_fetcher_->SetUploadFilePath( 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) upload_content_type_, 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) upload_file_path_, 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 0 /*offset*/, 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) kuint64max /*length*/, 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserThread::GetMessageLoopProxyForThread( 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserThread::FILE)); 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) url_fetcher_->SetUploadData(upload_content_type_, upload_data_); 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) url_fetcher_->Start(); 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) delegate_->OnError(this, RETRY_ERROR); 1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetURLFetcher::Start() { 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. 2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!send_empty_privet_token_ && !v3_mode_) { 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string privet_access_token; 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch privet_access_token = GetPrivetAccessToken(); 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (privet_access_token.empty()) { 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RequestTokenRefresh(); 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Try(); 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, 2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& upload_data) { 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(upload_file_path_.empty()); 2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) upload_content_type_ = upload_content_type; 2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) upload_data_ = upload_data; 2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PrivetURLFetcher::SetUploadFilePath( 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& upload_content_type, 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::FilePath& upload_file_path) { 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(upload_data_.empty()); 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) upload_content_type_ = upload_content_type; 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) upload_file_path_ = upload_file_path; 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (source->GetResponseCode() == net::HTTP_SERVICE_UNAVAILABLE) { 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScheduleRetry(kPrivetTimeoutOnError); 2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!OnURLFetchCompleteDoNotParseData(source)) { 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Byte ranges should only be used when we're not parsing the data 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // as JSON. 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!has_byte_range_); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We should only be saving raw data to a file. 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!make_response_file_); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnURLFetchCompleteParseData(source); 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Note that this function returns "true" in error cases to indicate 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// that it has fully handled the responses. 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PrivetURLFetcher::OnURLFetchCompleteDoNotParseData( 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const net::URLFetcher* source) { 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (source->GetResponseCode() == kHTTPErrorCodeInvalidXPrivetToken) { 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RequestTokenRefresh(); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (source->GetResponseCode() != net::HTTP_OK && 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source->GetResponseCode() != net::HTTP_PARTIAL_CONTENT) { 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->OnError(this, RESPONSE_CODE_ERROR); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (make_response_file_) { 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath response_file_path; 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!source->GetResponseAsFilePath(true, &response_file_path)) { 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->OnError(this, URL_FETCH_ERROR); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return delegate_->OnRawData(this, true, std::string(), response_file_path); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string response_str; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!source->GetResponseAsString(&response_str)) { 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->OnError(this, URL_FETCH_ERROR); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return delegate_->OnRawData(this, false, response_str, base::FilePath()); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrivetURLFetcher::OnURLFetchCompleteParseData( 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const net::URLFetcher* source) { 2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (source->GetResponseCode() != net::HTTP_OK) { 2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->OnError(this, RESPONSE_CODE_ERROR); 2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string response_str; 2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!source->GetResponseAsString(&response_str)) { 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->OnError(this, URL_FETCH_ERROR); 2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::JSONReader json_reader(base::JSON_ALLOW_TRAILING_COMMAS); 2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<base::Value> value; 3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch value.reset(json_reader.ReadToValue(response_str)); 3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!value) { 3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->OnError(this, JSON_PARSE_ERROR); 3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::DictionaryValue* dictionary_value = NULL; 3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!value->GetAsDictionary(&dictionary_value)) { 3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->OnError(this, JSON_PARSE_ERROR); 3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::string error; 3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (dictionary_value->GetString(kPrivetKeyError, &error)) { 3170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (error == kPrivetErrorInvalidXPrivetToken) { 3180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) RequestTokenRefresh(); 3190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (PrivetErrorTransient(error)) { 3210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!do_not_retry_on_transient_error_) { 3220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int timeout_seconds; 3230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!dictionary_value->GetInteger(kPrivetKeyTimeout, 3240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) &timeout_seconds)) { 3250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) timeout_seconds = kPrivetDefaultTimeout; 3260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScheduleRetry(timeout_seconds); 3290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch delegate_->OnParsedJson( 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this, *dictionary_value, dictionary_value->HasKey(kPrivetKeyError)); 3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void PrivetURLFetcher::ScheduleRetry(int timeout_seconds) { 3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) double random_scaling_factor = 3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition; 3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int timeout_seconds_randomized = 3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static_cast<int>(timeout_seconds * random_scaling_factor); 3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) timeout_seconds_randomized = 346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::max(timeout_seconds_randomized, kPrivetMinimumTimeout); 347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&PrivetURLFetcher::Try, weak_factory_.GetWeakPtr()), 3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::TimeDelta::FromSeconds(timeout_seconds_randomized)); 3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void PrivetURLFetcher::RequestTokenRefresh() { 3550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) delegate_->OnNeedPrivetToken( 3560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) this, 3570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); 3580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 3590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void PrivetURLFetcher::RefreshToken(const std::string& token) { 3610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (token.empty()) { 3620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) delegate_->OnError(this, TOKEN_ERROR); 3630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else { 364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetTokenForHost(GetHostString(), token); 3650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Try(); 3660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 3680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { 3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return (error == kPrivetErrorDeviceBusy) || 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (error == kPrivetV3ErrorDeviceBusy) || 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (error == kPrivetErrorPendingUserAction) || 373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (error == kPrivetErrorPrinterBusy); 3741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 3751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace local_discovery 377