OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/chromeos/printing/combining_printer_detector.h" |
| 6 |
| 7 #include <map> |
| 8 #include <utility> |
| 9 #include <vector> |
| 10 |
| 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/observer_list.h" |
| 13 #include "base/scoped_observer.h" |
| 14 #include "chrome/browser/chromeos/printing/printer_detector.h" |
| 15 #include "chromeos/printing/printer_configuration.h" |
| 16 |
| 17 namespace chromeos { |
| 18 namespace { |
| 19 |
| 20 class CombiningPrinterDetectorImpl; |
| 21 |
| 22 // We can't just implement PrinterDetector::Observer in |
| 23 // CombiningPrinterDetectorImpl because we need to be able to determing *which* |
| 24 // underlying detector is giving us new information. Thus we use delegate |
| 25 // instantions to allow for a disambiguation about the source of a |
| 26 // PrinterDetector callback from one of the detectors being combined. |
| 27 class ObserverDelegate : public PrinterDetector::Observer { |
| 28 public: |
| 29 ObserverDelegate(CombiningPrinterDetectorImpl* parent, |
| 30 PrinterDetector* detector) |
| 31 : parent_(parent), observer_(this) { |
| 32 observer_.Add(detector); |
| 33 } |
| 34 void OnPrintersFound(const std::vector<Printer>& printers) override; |
| 35 void OnPrinterScanComplete() override; |
| 36 |
| 37 private: |
| 38 CombiningPrinterDetectorImpl* parent_; |
| 39 ScopedObserver<PrinterDetector, PrinterDetector::Observer> observer_; |
| 40 }; |
| 41 |
| 42 class CombiningPrinterDetectorImpl : public CombiningPrinterDetector { |
| 43 public: |
| 44 ~CombiningPrinterDetectorImpl() override = default; |
| 45 |
| 46 void AddDetector(PrinterDetector* detector) override { |
| 47 detectors_.push_back(detector); |
| 48 delegates_.push_back(base::MakeUnique<ObserverDelegate>(this, detector)); |
| 49 printers_.insert({delegates_.back().get(), detector->GetPrinters()}); |
| 50 scan_done_[delegates_.back().get()] = false; |
| 51 } |
| 52 |
| 53 void AddOwnedDetector(std::unique_ptr<PrinterDetector> detector) override { |
| 54 AddDetector(detector.get()); |
| 55 owned_detectors_.emplace_back(std::move(detector)); |
| 56 } |
| 57 |
| 58 // PrinterDetector implementations. |
| 59 void AddObserver(PrinterDetector::Observer* observer) override { |
| 60 observer_list_.AddObserver(observer); |
| 61 } |
| 62 |
| 63 void RemoveObserver(PrinterDetector::Observer* observer) override { |
| 64 observer_list_.RemoveObserver(observer); |
| 65 } |
| 66 |
| 67 // Note this is *not* the PrinterDetectorObserver interface directly, |
| 68 // it's the entry point for ObserverDelegates to pass along those messages |
| 69 // into this class. |
| 70 void OnPrintersFound(const ObserverDelegate* source, |
| 71 const std::vector<Printer>& printers) { |
| 72 // If this object doesn't know about the delegate trying to update its |
| 73 // printers, we missed delegate registration somehow, which shouldn't |
| 74 // happen. |
| 75 DCHECK(base::ContainsKey(printers_, source)); |
| 76 printers_[source] = printers; |
| 77 std::vector<Printer> all_printers = GetPrinters(); |
| 78 for (PrinterDetector::Observer& observer : observer_list_) { |
| 79 observer.OnPrintersFound(all_printers); |
| 80 } |
| 81 } |
| 82 |
| 83 void OnPrinterScanComplete(const ObserverDelegate* source) { |
| 84 DCHECK(base::ContainsKey(printers_, source)); |
| 85 bool& scan_done = scan_done_[source]; |
| 86 if (!scan_done) { |
| 87 scan_done = true; |
| 88 for (const auto& entry : scan_done_) { |
| 89 if (!entry.second) { |
| 90 // Not all done yet. |
| 91 return; |
| 92 } |
| 93 } |
| 94 // Final outstanding scan just finished, notify observers. |
| 95 for (PrinterDetector::Observer& observer : observer_list_) { |
| 96 observer.OnPrinterScanComplete(); |
| 97 } |
| 98 } |
| 99 } |
| 100 |
| 101 // Aggregate the printers from all underlying sources and return them. |
| 102 std::vector<Printer> GetPrinters() override { |
| 103 std::vector<Printer> ret; |
| 104 for (const auto& entry : printers_) { |
| 105 ret.insert(ret.end(), entry.second.begin(), entry.second.end()); |
| 106 } |
| 107 return ret; |
| 108 } |
| 109 |
| 110 void Start() override { |
| 111 for (PrinterDetector* detector : detectors_) { |
| 112 detector->Start(); |
| 113 } |
| 114 } |
| 115 |
| 116 private: |
| 117 // Map from observer delegate to the most recent list of printers from that |
| 118 // observer. |
| 119 std::map<const ObserverDelegate*, std::vector<Printer>> printers_; |
| 120 |
| 121 // Map from observer delegate to whether or not that observer has completed |
| 122 // its scan. |
| 123 std::map<const ObserverDelegate*, bool> scan_done_; |
| 124 |
| 125 // Observers of this object. |
| 126 base::ObserverList<PrinterDetector::Observer> observer_list_; |
| 127 |
| 128 std::vector<std::unique_ptr<PrinterDetector>> owned_detectors_; |
| 129 |
| 130 // Memory management -- this just exists to ensure that the held |
| 131 // elements get cleaned up. |
| 132 std::vector<std::unique_ptr<ObserverDelegate>> delegates_; |
| 133 |
| 134 // All detectors used by the combining detector, owned or unowned. |
| 135 std::vector<PrinterDetector*> detectors_; |
| 136 }; |
| 137 |
| 138 void ObserverDelegate::OnPrintersFound(const std::vector<Printer>& printers) { |
| 139 parent_->OnPrintersFound(this, printers); |
| 140 } |
| 141 |
| 142 void ObserverDelegate::OnPrinterScanComplete() { |
| 143 parent_->OnPrinterScanComplete(this); |
| 144 } |
| 145 |
| 146 } // namespace |
| 147 |
| 148 // static |
| 149 std::unique_ptr<CombiningPrinterDetector> CombiningPrinterDetector::Create() { |
| 150 return base::MakeUnique<CombiningPrinterDetectorImpl>(); |
| 151 } |
| 152 |
| 153 } // namespace chromeos |
OLD | NEW |