| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chromeos/printing/ppd_provider.h" | 5 #include "chromeos/printing/ppd_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <unordered_map> | 10 #include <unordered_map> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/base64.h" | 14 #include "base/base64.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/files/file.h" | 16 #include "base/files/file.h" |
| 17 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 18 #include "base/json/json_parser.h" | 18 #include "base/json/json_parser.h" |
| 19 #include "base/memory/ptr_util.h" | 19 #include "base/memory/ptr_util.h" |
| 20 #include "base/sequenced_task_runner.h" |
| 20 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
| 21 #include "base/strings/string_split.h" | 22 #include "base/strings/string_split.h" |
| 22 #include "base/strings/string_tokenizer.h" | 23 #include "base/strings/string_tokenizer.h" |
| 23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 24 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
| 25 #include "base/synchronization/lock.h" | 26 #include "base/synchronization/lock.h" |
| 26 #include "base/task_runner_util.h" | 27 #include "base/task_runner_util.h" |
| 28 #include "base/task_scheduler/post_task.h" |
| 27 #include "base/threading/sequenced_task_runner_handle.h" | 29 #include "base/threading/sequenced_task_runner_handle.h" |
| 28 #include "base/threading/thread_restrictions.h" | 30 #include "base/threading/thread_restrictions.h" |
| 29 #include "base/time/time.h" | 31 #include "base/time/time.h" |
| 30 #include "base/values.h" | 32 #include "base/values.h" |
| 31 #include "chromeos/printing/ppd_cache.h" | 33 #include "chromeos/printing/ppd_cache.h" |
| 32 #include "chromeos/printing/printing_constants.h" | 34 #include "chromeos/printing/printing_constants.h" |
| 33 #include "net/base/load_flags.h" | 35 #include "net/base/load_flags.h" |
| 34 #include "net/http/http_status_code.h" | 36 #include "net/http/http_status_code.h" |
| 35 #include "net/url_request/url_fetcher.h" | 37 #include "net/url_request/url_fetcher.h" |
| 36 #include "net/url_request/url_fetcher_delegate.h" | 38 #include "net/url_request/url_fetcher_delegate.h" |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 DCHECK(PpdReferenceIsWellFormed(reference)); | 151 DCHECK(PpdReferenceIsWellFormed(reference)); |
| 150 // The key prefixes here are arbitrary, but ensure we can't have an (unhashed) | 152 // The key prefixes here are arbitrary, but ensure we can't have an (unhashed) |
| 151 // collision between keys generated from different PpdReference fields. | 153 // collision between keys generated from different PpdReference fields. |
| 152 if (!reference.effective_make_and_model.empty()) { | 154 if (!reference.effective_make_and_model.empty()) { |
| 153 return std::string("em:") + reference.effective_make_and_model; | 155 return std::string("em:") + reference.effective_make_and_model; |
| 154 } else { | 156 } else { |
| 155 return std::string("up:") + reference.user_supplied_ppd_url; | 157 return std::string("up:") + reference.user_supplied_ppd_url; |
| 156 } | 158 } |
| 157 } | 159 } |
| 158 | 160 |
| 161 // Handles the result after PPD storage. |
| 162 void OnPpdStored() {} |
| 163 |
| 164 // Fetch the file pointed at by |url| and store it in |file_contents|. |
| 165 // Returns true if the fetch was successful. |
| 166 bool FetchFile(const GURL& url, std::string* file_contents) { |
| 167 CHECK(url.is_valid()); |
| 168 CHECK(url.SchemeIs("file")); |
| 169 base::ThreadRestrictions::AssertIOAllowed(); |
| 170 |
| 171 return base::ReadFileToString(base::FilePath(url.path()), file_contents); |
| 172 } |
| 173 |
| 159 struct ManufacturerMetadata { | 174 struct ManufacturerMetadata { |
| 160 // Key used to look up the printer list on the server. This is initially | 175 // Key used to look up the printer list on the server. This is initially |
| 161 // populated. | 176 // populated. |
| 162 std::string reference; | 177 std::string reference; |
| 163 | 178 |
| 164 // Map from localized printer name to canonical-make-and-model string for | 179 // Map from localized printer name to canonical-make-and-model string for |
| 165 // the given printer. Populated on demand. | 180 // the given printer. Populated on demand. |
| 166 std::unique_ptr<std::unordered_map<std::string, std::string>> printers; | 181 std::unique_ptr<std::unordered_map<std::string, std::string>> printers; |
| 167 }; | 182 }; |
| 168 | 183 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 194 FT_PRINTERS, // List of printers from a manufacturer. | 209 FT_PRINTERS, // List of printers from a manufacturer. |
| 195 FT_PPD_INDEX, // Master ppd index. | 210 FT_PPD_INDEX, // Master ppd index. |
| 196 FT_PPD, // A Ppd file. | 211 FT_PPD, // A Ppd file. |
| 197 FT_USB_DEVICES // USB device id to canonical name map. | 212 FT_USB_DEVICES // USB device id to canonical name map. |
| 198 }; | 213 }; |
| 199 | 214 |
| 200 PpdProviderImpl( | 215 PpdProviderImpl( |
| 201 const std::string& browser_locale, | 216 const std::string& browser_locale, |
| 202 scoped_refptr<net::URLRequestContextGetter> url_context_getter, | 217 scoped_refptr<net::URLRequestContextGetter> url_context_getter, |
| 203 scoped_refptr<PpdCache> ppd_cache, | 218 scoped_refptr<PpdCache> ppd_cache, |
| 204 scoped_refptr<base::SequencedTaskRunner> disk_task_runner, | |
| 205 const PpdProvider::Options& options) | 219 const PpdProvider::Options& options) |
| 206 : browser_locale_(browser_locale), | 220 : browser_locale_(browser_locale), |
| 207 url_context_getter_(url_context_getter), | 221 url_context_getter_(url_context_getter), |
| 208 ppd_cache_(ppd_cache), | 222 ppd_cache_(ppd_cache), |
| 209 disk_task_runner_(disk_task_runner), | 223 disk_task_runner_(base::CreateSequencedTaskRunnerWithTraits( |
| 224 {base::TaskPriority::USER_VISIBLE, base::MayBlock(), |
| 225 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), |
| 210 options_(options), | 226 options_(options), |
| 211 weak_factory_(this) {} | 227 weak_factory_(this) {} |
| 212 | 228 |
| 213 // Resolving manufacturers requires a couple of steps, because of | 229 // Resolving manufacturers requires a couple of steps, because of |
| 214 // localization. First we have to figure out what locale to use, which | 230 // localization. First we have to figure out what locale to use, which |
| 215 // involves grabbing a list of available locales from the server. Once we | 231 // involves grabbing a list of available locales from the server. Once we |
| 216 // have decided on a locale, we go out and fetch the manufacturers map in that | 232 // have decided on a locale, we go out and fetch the manufacturers map in that |
| 217 // localization. | 233 // localization. |
| 218 // | 234 // |
| 219 // This means when a request comes in, we either queue it and start background | 235 // This means when a request comes in, we either queue it and start background |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 FinishPpdResolution(cb, PpdProvider::INTERNAL_ERROR, std::string()); | 376 FinishPpdResolution(cb, PpdProvider::INTERNAL_ERROR, std::string()); |
| 361 return; | 377 return; |
| 362 } | 378 } |
| 363 // First step, check the cache. If the cache lookup fails, we'll (try to) | 379 // First step, check the cache. If the cache lookup fails, we'll (try to) |
| 364 // consult the server. | 380 // consult the server. |
| 365 ppd_cache_->Find(PpdReferenceToCacheKey(reference), | 381 ppd_cache_->Find(PpdReferenceToCacheKey(reference), |
| 366 base::Bind(&PpdProviderImpl::ResolvePpdCacheLookupDone, | 382 base::Bind(&PpdProviderImpl::ResolvePpdCacheLookupDone, |
| 367 weak_factory_.GetWeakPtr(), reference, cb)); | 383 weak_factory_.GetWeakPtr(), reference, cb)); |
| 368 } | 384 } |
| 369 | 385 |
| 370 // Our only sources of long running ops are cache fetches and network fetches. | |
| 371 bool Idle() const override { return ppd_cache_->Idle() && !fetch_inflight_; } | |
| 372 | |
| 373 // Common handler that gets called whenever a fetch completes. Note this | 386 // Common handler that gets called whenever a fetch completes. Note this |
| 374 // is used both for |fetcher_| fetches (i.e. http[s]) and file-based fetches; | 387 // is used both for |fetcher_| fetches (i.e. http[s]) and file-based fetches; |
| 375 // |source| may be null in the latter case. | 388 // |source| may be null in the latter case. |
| 376 void OnURLFetchComplete(const net::URLFetcher* source) override { | 389 void OnURLFetchComplete(const net::URLFetcher* source) override { |
| 377 switch (fetcher_target_) { | 390 switch (fetcher_target_) { |
| 378 case FT_LOCALES: | 391 case FT_LOCALES: |
| 379 OnLocalesFetchComplete(); | 392 OnLocalesFetchComplete(); |
| 380 break; | 393 break; |
| 381 case FT_MANUFACTURERS: | 394 case FT_MANUFACTURERS: |
| 382 OnManufacturersFetchComplete(); | 395 OnManufacturersFetchComplete(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 | 462 |
| 450 if (url.SchemeIs("http") || url.SchemeIs("https")) { | 463 if (url.SchemeIs("http") || url.SchemeIs("https")) { |
| 451 fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this); | 464 fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this); |
| 452 fetcher_->SetRequestContext(url_context_getter_.get()); | 465 fetcher_->SetRequestContext(url_context_getter_.get()); |
| 453 fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | | 466 fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | |
| 454 net::LOAD_DO_NOT_SAVE_COOKIES | | 467 net::LOAD_DO_NOT_SAVE_COOKIES | |
| 455 net::LOAD_DO_NOT_SEND_COOKIES | | 468 net::LOAD_DO_NOT_SEND_COOKIES | |
| 456 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 469 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
| 457 fetcher_->Start(); | 470 fetcher_->Start(); |
| 458 } else if (url.SchemeIs("file")) { | 471 } else if (url.SchemeIs("file")) { |
| 459 disk_task_runner_->PostTaskAndReply( | 472 auto file_contents = base::MakeUnique<std::string>(); |
| 460 FROM_HERE, base::Bind(&PpdProviderImpl::FetchFile, this, url), | 473 std::string* content_ptr = file_contents.get(); |
| 461 base::Bind(&PpdProviderImpl::OnURLFetchComplete, this, nullptr)); | 474 base::PostTaskAndReplyWithResult( |
| 475 disk_task_runner_.get(), FROM_HERE, |
| 476 base::Bind(&FetchFile, url, content_ptr), |
| 477 base::Bind(&PpdProviderImpl::OnFileFetchComplete, this, |
| 478 base::Passed(&file_contents))); |
| 462 } | 479 } |
| 463 } | 480 } |
| 464 | 481 |
| 465 // Fetch the file pointed at by url and store it in |file_fetch_contents_|. | 482 // Handle the result of a file fetch. |
| 466 // Use |file_fetch_success_| to indicate success or failure. | 483 void OnFileFetchComplete(std::unique_ptr<std::string> file_contents, |
| 467 void FetchFile(const GURL& url) { | 484 bool success) { |
| 468 CHECK(url.is_valid()); | 485 file_fetch_success_ = success; |
| 469 CHECK(url.SchemeIs("file")); | 486 file_fetch_contents_ = success ? *file_contents : ""; |
| 470 base::ThreadRestrictions::AssertIOAllowed(); | 487 OnURLFetchComplete(nullptr); |
| 471 file_fetch_success_ = base::ReadFileToString(base::FilePath(url.path()), | |
| 472 &file_fetch_contents_); | |
| 473 } | 488 } |
| 474 | 489 |
| 475 void FinishPpdResolution(const ResolvePpdCallback& cb, | 490 void FinishPpdResolution(const ResolvePpdCallback& cb, |
| 476 PpdProvider::CallbackResultCode result_code, | 491 PpdProvider::CallbackResultCode result_code, |
| 477 const std::string& ppd_contents) { | 492 const std::string& ppd_contents) { |
| 478 if (result_code == PpdProvider::SUCCESS) { | 493 if (result_code == PpdProvider::SUCCESS) { |
| 479 base::SequencedTaskRunnerHandle::Get()->PostTask( | 494 base::SequencedTaskRunnerHandle::Get()->PostTask( |
| 480 FROM_HERE, base::Bind(cb, PpdProvider::SUCCESS, ppd_contents, | 495 FROM_HERE, base::Bind(cb, PpdProvider::SUCCESS, ppd_contents, |
| 481 ExtractFiltersFromPpd(ppd_contents))); | 496 ExtractFiltersFromPpd(ppd_contents))); |
| 482 } else { | 497 } else { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 DCHECK(!ppd_resolution_queue_.empty()); | 672 DCHECK(!ppd_resolution_queue_.empty()); |
| 658 std::string contents; | 673 std::string contents; |
| 659 | 674 |
| 660 if ((ValidateAndGetResponseAsString(&contents) != PpdProvider::SUCCESS) || | 675 if ((ValidateAndGetResponseAsString(&contents) != PpdProvider::SUCCESS) || |
| 661 contents.size() > kMaxPpdSizeBytes) { | 676 contents.size() > kMaxPpdSizeBytes) { |
| 662 FinishPpdResolution(ppd_resolution_queue_.front().second, | 677 FinishPpdResolution(ppd_resolution_queue_.front().second, |
| 663 PpdProvider::SERVER_ERROR, std::string()); | 678 PpdProvider::SERVER_ERROR, std::string()); |
| 664 } else { | 679 } else { |
| 665 ppd_cache_->Store( | 680 ppd_cache_->Store( |
| 666 PpdReferenceToCacheKey(ppd_resolution_queue_.front().first), contents, | 681 PpdReferenceToCacheKey(ppd_resolution_queue_.front().first), contents, |
| 667 base::Callback<void()>()); | 682 base::Bind(&OnPpdStored)); |
| 668 FinishPpdResolution(ppd_resolution_queue_.front().second, | 683 FinishPpdResolution(ppd_resolution_queue_.front().second, |
| 669 PpdProvider::SUCCESS, contents); | 684 PpdProvider::SUCCESS, contents); |
| 670 } | 685 } |
| 671 ppd_resolution_queue_.pop_front(); | 686 ppd_resolution_queue_.pop_front(); |
| 672 } | 687 } |
| 673 | 688 |
| 674 // Called when |fetcher_| should have just downloaded a usb device map | 689 // Called when |fetcher_| should have just downloaded a usb device map |
| 675 // for the vendor at the head of the |usb_resolution_queue_|. | 690 // for the vendor at the head of the |usb_resolution_queue_|. |
| 676 void OnUsbFetchComplete() { | 691 void OnUsbFetchComplete() { |
| 677 DCHECK(!usb_resolution_queue_.empty()); | 692 DCHECK(!usb_resolution_queue_.empty()); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 ~PpdProviderImpl() override {} | 1009 ~PpdProviderImpl() override {} |
| 995 }; | 1010 }; |
| 996 | 1011 |
| 997 } // namespace | 1012 } // namespace |
| 998 | 1013 |
| 999 // static | 1014 // static |
| 1000 scoped_refptr<PpdProvider> PpdProvider::Create( | 1015 scoped_refptr<PpdProvider> PpdProvider::Create( |
| 1001 const std::string& browser_locale, | 1016 const std::string& browser_locale, |
| 1002 scoped_refptr<net::URLRequestContextGetter> url_context_getter, | 1017 scoped_refptr<net::URLRequestContextGetter> url_context_getter, |
| 1003 scoped_refptr<PpdCache> ppd_cache, | 1018 scoped_refptr<PpdCache> ppd_cache, |
| 1004 scoped_refptr<base::SequencedTaskRunner> disk_task_runner, | |
| 1005 const PpdProvider::Options& options) { | 1019 const PpdProvider::Options& options) { |
| 1006 return scoped_refptr<PpdProvider>( | 1020 return scoped_refptr<PpdProvider>(new PpdProviderImpl( |
| 1007 new PpdProviderImpl(browser_locale, url_context_getter, ppd_cache, | 1021 browser_locale, url_context_getter, ppd_cache, options)); |
| 1008 disk_task_runner, options)); | |
| 1009 } | 1022 } |
| 1010 } // namespace printing | 1023 } // namespace printing |
| 1011 } // namespace chromeos | 1024 } // namespace chromeos |
| OLD | NEW |