1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <chrono>
17 #include "vendor_manager.h"
18 #include "vendor_helper.h"
19 #include "vendor_bsuni_driver.h"
20 #include "vendor_ipp_everywhere.h"
21 #include "print_log.h"
22 
23 using namespace OHOS::Print;
24 namespace {
25 const std::string VENDOR_MANAGER_PREFIX = "fwk.";
26 const std::string GLOBAL_ID_DELIMITER = ":";
27 const int MONITOR_CHECK_INTERVAL_MS = 1000;
28 const size_t IP_LENGTH_MIN = 10;
29 }
30 
VendorManager()31 VendorManager::VendorManager() {}
32 
~VendorManager()33 VendorManager::~VendorManager()
34 {
35     UnInit();
36 }
37 
GetGlobalVendorName(const std::string &vendorName)38 std::string VendorManager::GetGlobalVendorName(const std::string &vendorName)
39 {
40     return VENDOR_MANAGER_PREFIX + vendorName;
41 }
GetGlobalPrinterId(const std::string &globalVendorName, const std::string &printerId)42 std::string VendorManager::GetGlobalPrinterId(const std::string &globalVendorName, const std::string &printerId)
43 {
44     return globalVendorName + GLOBAL_ID_DELIMITER + printerId;
45 }
ExtractVendorName(const std::string &globalVendorName)46 std::string VendorManager::ExtractVendorName(const std::string &globalVendorName)
47 {
48     auto pos = globalVendorName.find(VENDOR_MANAGER_PREFIX);
49     if (pos != 0 || globalVendorName.length() <= VENDOR_MANAGER_PREFIX.length()) {
50         return "";
51     }
52     return globalVendorName.substr(VENDOR_MANAGER_PREFIX.length());
53 }
54 
ExtractGlobalVendorName(const std::string &globalPrinterId)55 std::string VendorManager::ExtractGlobalVendorName(const std::string &globalPrinterId)
56 {
57     auto pos = globalPrinterId.find(GLOBAL_ID_DELIMITER);
58     if (pos == std::string::npos) {
59         return "";
60     }
61     return globalPrinterId.substr(0, pos);
62 }
63 
ExtractPrinterId(const std::string &globalPrinterId)64 std::string VendorManager::ExtractPrinterId(const std::string &globalPrinterId)
65 {
66     auto pos = globalPrinterId.find(GLOBAL_ID_DELIMITER);
67     if (pos == std::string::npos || globalPrinterId.length() <= pos + 1) {
68         return "";
69     }
70     return globalPrinterId.substr(pos + 1);
71 }
72 
Init(IPrintServiceAbility *sa, bool loadDefault)73 bool VendorManager::Init(IPrintServiceAbility *sa, bool loadDefault)
74 {
75     PRINT_HILOGI("Init enter");
76     printServiceAbility = sa;
77     if (!loadDefault) {
78         return true;
79     }
80     bool expectLoaded = false;
81     if (!defaultLoaded.compare_exchange_strong(expectLoaded, true)) {
82         PRINT_HILOGI("load already");
83         return true;
84     }
85     PRINT_HILOGI("load default vendor...");
86     auto vendorBsUni = std::make_shared<VendorBsuniDriver>();
87     if (!LoadVendorDriver(vendorBsUni)) {
88         PRINT_HILOGW("BsUni driver load fail");
89         auto vendorIppEverywhere = std::make_shared<VendorIppEveryWhere>();
90         if (!LoadVendorDriver(vendorIppEverywhere)) {
91             PRINT_HILOGW("IppEverywhere driver load fail");
92             return false;
93         }
94     }
95     PRINT_HILOGI("Init quit");
96     return true;
97 }
98 
UnInit()99 void VendorManager::UnInit()
100 {
101     PRINT_HILOGI("UnInit enter");
102     StopStatusMonitor();
103     std::lock_guard<std::mutex> lock(vendorMapMutex);
104     for (auto const &pair : vendorMap) {
105         PRINT_HILOGD("UnInit %{public}s", pair.first.c_str());
106         if (pair.second == nullptr) {
107             PRINT_HILOGW("vendor extension is null");
108             continue;
109         }
110         pair.second->OnDestroy();
111         pair.second->UnInit();
112     }
113     vendorMap.clear();
114     printServiceAbility = nullptr;
115     defaultLoaded = false;
116     PRINT_HILOGI("UnInit quit");
117 }
118 
LoadVendorDriver(std::shared_ptr<VendorDriverBase> vendorDriver)119 bool VendorManager::LoadVendorDriver(std::shared_ptr<VendorDriverBase> vendorDriver)
120 {
121     if (vendorDriver == nullptr) {
122         PRINT_HILOGW("vendorDriver is null");
123         return false;
124     }
125     if (!vendorDriver->Init(this)) {
126         PRINT_HILOGW("vendorDriver init fail");
127         return false;
128     }
129     std::lock_guard<std::mutex> lock(vendorMapMutex);
130     vendorMap.insert(std::make_pair(vendorDriver->GetVendorName(), vendorDriver));
131     vendorDriver->OnCreate();
132     return true;
133 }
UnloadVendorDriver(const std::string &vendorName)134 bool VendorManager::UnloadVendorDriver(const std::string &vendorName)
135 {
136     std::lock_guard<std::mutex> lock(vendorMapMutex);
137     auto iter = vendorMap.find(vendorName);
138     if (iter == vendorMap.end()) {
139         return false;
140     }
141     auto vendorDriver = iter->second;
142     vendorMap.erase(iter);
143     if (vendorDriver != nullptr) {
144         vendorDriver->OnDestroy();
145         vendorDriver->UnInit();
146     }
147     return true;
148 }
149 
ConnectPrinter(const std::string &globalPrinterId)150 bool VendorManager::ConnectPrinter(const std::string &globalPrinterId)
151 {
152     PRINT_HILOGI("ConnectPrinter enter");
153     std::string printerId = ExtractPrinterId(globalPrinterId);
154     if (printerId.empty()) {
155         PRINT_HILOGW("empty printer id");
156         return false;
157     }
158     auto vendorDriver = FindDriverByPrinterId(globalPrinterId);
159     if (vendorDriver == nullptr) {
160         PRINT_HILOGW("vendorDriver is null");
161         return false;
162     }
163     PRINT_HILOGD("OnQueryCapability: %{public}s", printerId.c_str());
164     return vendorDriver->OnQueryCapability(printerId, 0);
165 }
166 
ConnectPrinterByIp(const std::string &printerIp, const std::string &protocol)167 bool VendorManager::ConnectPrinterByIp(const std::string &printerIp, const std::string &protocol)
168 {
169     PRINT_HILOGI("ConnectPrinterByIp enter");
170     bool ret = false;
171     if (printerIp.size() < IP_LENGTH_MIN) {
172         PRINT_HILOGW("ip length incorrect");
173         return ret;
174     }
175     for (auto const &pair : vendorMap) {
176         PRINT_HILOGD("ConnectPrinterByIp %{public}s", pair.first.c_str());
177         if (pair.second == nullptr) {
178             PRINT_HILOGW("vendor extension is null");
179             continue;
180         }
181         if (pair.second->OnQueryCapabilityByIp(printerIp, protocol)) {
182             ret = true;
183         }
184     }
185     PRINT_HILOGI("ConnectPrinterByIp quit");
186     return ret;
187 }
188 
QueryPrinterInfo(const std::string &globalPrinterId, int timeout)189 bool VendorManager::QueryPrinterInfo(const std::string &globalPrinterId, int timeout)
190 {
191     PRINT_HILOGI("QueryPrinterInfo enter");
192     std::string printerId = ExtractPrinterId(globalPrinterId);
193     if (printerId.empty()) {
194         PRINT_HILOGW("empty printer id");
195         return false;
196     }
197     auto vendorDriver = FindDriverByPrinterId(globalPrinterId);
198     if (vendorDriver == nullptr) {
199         PRINT_HILOGW("vendorDriver is null");
200         return false;
201     }
202     PRINT_HILOGD("OnQueryCapability: %{public}s", printerId.c_str());
203     vendorDriver->OnQueryCapability(printerId, timeout);
204     PRINT_HILOGI("QueryPrinterInfo quit");
205     return true;
206 }
207 
StartDiscovery()208 void VendorManager::StartDiscovery()
209 {
210     PRINT_HILOGI("StartDiscovery enter");
211     std::lock_guard<std::mutex> lock(vendorMapMutex);
212     for (auto const &pair : vendorMap) {
213         PRINT_HILOGD("StartDiscovery %{public}s", pair.first.c_str());
214         if (pair.second == nullptr) {
215             PRINT_HILOGW("vendor extension is null");
216             continue;
217         }
218         pair.second->OnStartDiscovery();
219     }
220     PRINT_HILOGI("StartDiscovery quit");
221 }
StopDiscovery()222 void VendorManager::StopDiscovery()
223 {
224     PRINT_HILOGI("StopDiscovery enter");
225     std::lock_guard<std::mutex> lock(vendorMapMutex);
226     for (auto const &pair : vendorMap) {
227         if (pair.second == nullptr) {
228             PRINT_HILOGW("vendor extension is null");
229             continue;
230         }
231         pair.second->OnStopDiscovery();
232     }
233     PRINT_HILOGI("StopDiscovery quit");
234 }
235 
AddPrinterToDiscovery(const std::string &vendorName, const PrinterInfo &printerInfo)236 int32_t VendorManager::AddPrinterToDiscovery(const std::string &vendorName, const PrinterInfo &printerInfo)
237 {
238     PRINT_HILOGI("AddPrinterToDiscovery enter");
239     if (printServiceAbility == nullptr) {
240         PRINT_HILOGW("printServiceAbility is null");
241         return EXTENSION_ERROR_CALLBACK_FAIL;
242     }
243     if (!printServiceAbility->AddVendorPrinterToDiscovery(GetGlobalVendorName(vendorName), printerInfo)) {
244         PRINT_HILOGW("AddPrinterToDiscovery fail");
245         return EXTENSION_ERROR_CALLBACK_FAIL;
246     }
247     PRINT_HILOGI("AddPrinterToDiscovery quit");
248     return EXTENSION_ERROR_NONE;
249 }
250 
UpdatePrinterToDiscovery(const std::string &vendorName, const PrinterInfo &printerInfo)251 int32_t VendorManager::UpdatePrinterToDiscovery(const std::string &vendorName, const PrinterInfo &printerInfo)
252 {
253     PRINT_HILOGI("UpdatePrinterToDiscovery enter");
254     if (printServiceAbility == nullptr) {
255         PRINT_HILOGW("printServiceAbility is null");
256         return EXTENSION_ERROR_CALLBACK_FAIL;
257     }
258     std::string globalVendorName = GetGlobalVendorName(vendorName);
259     if (!printServiceAbility->UpdateVendorPrinterToDiscovery(globalVendorName, printerInfo)) {
260         PRINT_HILOGW("UpdatePrinterToDiscovery fail");
261         return EXTENSION_ERROR_CALLBACK_FAIL;
262     }
263     PRINT_HILOGI("UpdatePrinterToDiscovery quit");
264     return EXTENSION_ERROR_NONE;
265 }
RemovePrinterFromDiscovery(const std::string &vendorName, const std::string &printerId)266 int32_t VendorManager::RemovePrinterFromDiscovery(const std::string &vendorName, const std::string &printerId)
267 {
268     PRINT_HILOGI("RemovePrinterFromDiscovery enter");
269     if (printServiceAbility == nullptr) {
270         PRINT_HILOGW("printServiceAbility is null");
271         return EXTENSION_ERROR_CALLBACK_FAIL;
272     }
273     if (!printServiceAbility->RemoveVendorPrinterFromDiscovery(GetGlobalVendorName(vendorName), printerId)) {
274         PRINT_HILOGW("RemovePrinterFromDiscovery fail");
275         return EXTENSION_ERROR_CALLBACK_FAIL;
276     }
277     PRINT_HILOGI("RemovePrinterFromDiscovery quit");
278     return EXTENSION_ERROR_NONE;
279 }
280 
AddPrinterToCupsWithPpd(const std::string &vendorName, const std::string &printerId, const std::string &ppdData)281 int32_t VendorManager::AddPrinterToCupsWithPpd(const std::string &vendorName, const std::string &printerId,
282                                                const std::string &ppdData)
283 {
284     PRINT_HILOGI("AddPrinterToCupsWithPpd enter");
285     if (printServiceAbility == nullptr) {
286         PRINT_HILOGW("printServiceAbility is null");
287         return EXTENSION_ERROR_CALLBACK_FAIL;
288     }
289     std::string globalVendorName = GetGlobalVendorName(vendorName);
290     if (!printServiceAbility->AddVendorPrinterToCupsWithPpd(globalVendorName, printerId, ppdData)) {
291         PRINT_HILOGW("AddPrinterToCupsWithPpd fail");
292         return EXTENSION_ERROR_CALLBACK_FAIL;
293     }
294     PRINT_HILOGI("AddPrinterToCupsWithPpd quit");
295     return EXTENSION_ERROR_NONE;
296 }
297 
RemovePrinterFromCups(const std::string &vendorName, const std::string &printerId)298 int32_t VendorManager::RemovePrinterFromCups(const std::string &vendorName, const std::string &printerId)
299 {
300     PRINT_HILOGI("RemovePrinterFromCups enter");
301     if (printServiceAbility == nullptr) {
302         PRINT_HILOGW("printServiceAbility is null");
303         return EXTENSION_ERROR_CALLBACK_FAIL;
304     }
305     std::string globalVendorName = GetGlobalVendorName(vendorName);
306     if (!printServiceAbility->RemoveVendorPrinterFromCups(globalVendorName, printerId)) {
307         PRINT_HILOGW("RemovePrinterFromCups fail");
308         return EXTENSION_ERROR_CALLBACK_FAIL;
309     }
310     PRINT_HILOGI("RemovePrinterFromCups quit");
311     return EXTENSION_ERROR_NONE;
312 }
313 
OnPrinterPpdQueried(const std::string &vendorName, const std::string &printerId, const std::string &ppdData)314 bool VendorManager::OnPrinterPpdQueried(const std::string &vendorName, const std::string &printerId,
315                                         const std::string &ppdData)
316 {
317     PRINT_HILOGI("OnPrinterPpdQueried enter");
318     if (printServiceAbility == nullptr) {
319         PRINT_HILOGW("printServiceAbility is null");
320         return false;
321     }
322     std::string globalVendorName = GetGlobalVendorName(vendorName);
323     std::string globalPrinterId = GetGlobalPrinterId(globalVendorName, printerId);
324     PRINT_HILOGD("global printer id %{public}s", globalPrinterId.c_str());
325     if (!IsConnectingPrinter(globalPrinterId, "")) {
326         PRINT_HILOGW("not connecting");
327         return false;
328     }
329     if (!printServiceAbility->AddVendorPrinterToCupsWithPpd(globalVendorName, printerId, ppdData)) {
330         PRINT_HILOGW("AddPrinterToCupsWithPpd fail");
331         return false;
332     }
333     PRINT_HILOGI("OnPrinterPpdQueried quit");
334     return true;
335 }
336 
OnPrinterStatusChanged(const std::string &vendorName, const std::string &printerId, const PrinterVendorStatus &status)337 bool VendorManager::OnPrinterStatusChanged(const std::string &vendorName, const std::string &printerId,
338                                            const PrinterVendorStatus &status)
339 {
340     std::string globalVendorName = GetGlobalVendorName(vendorName);
341     if (printServiceAbility != nullptr) {
342         return printServiceAbility->OnVendorStatusUpdate(globalVendorName, printerId, status);
343     }
344     return true;
345 }
346 
FindDriverByPrinterId(const std::string &globalPrinterId)347 std::shared_ptr<VendorDriverBase> VendorManager::FindDriverByPrinterId(const std::string &globalPrinterId)
348 {
349     std::string globalVendorName = ExtractGlobalVendorName(globalPrinterId);
350     std::string vendorName = ExtractVendorName(globalVendorName);
351     if (vendorName.empty()) {
352         PRINT_HILOGW("Invalid printer id");
353         return nullptr;
354     }
355     return FindDriverByVendorName(vendorName);
356 }
357 
FindDriverByVendorName(const std::string &vendorName)358 std::shared_ptr<VendorDriverBase> VendorManager::FindDriverByVendorName(const std::string &vendorName)
359 {
360     std::lock_guard<std::mutex> lock(vendorMapMutex);
361     auto iter = vendorMap.find(vendorName);
362     if (iter == vendorMap.end()) {
363         PRINT_HILOGW("cannot find vendor extension: %{public}s", vendorName.c_str());
364         return nullptr;
365     }
366     return iter->second;
367 }
368 
StartStatusMonitor()369 void VendorManager::StartStatusMonitor()
370 {
371     PRINT_HILOGI("StartStatusMonitor Enter");
372     {
373         std::unique_lock<std::mutex> lock(statusMonitorMutex);
374         if (statusMonitorOn) {
375             PRINT_HILOGW("already on");
376             return;
377         }
378         statusMonitorOn = true;
379     }
380     PRINT_HILOGI("StartStatusMonitor Now");
381     statusMonitorThread = std::thread(&VendorManager::StatusMonitorProcess, this);
382     PRINT_HILOGI("StartStatusMonitor Quit");
383 }
384 
StopStatusMonitor()385 void VendorManager::StopStatusMonitor()
386 {
387     PRINT_HILOGI("StopStatusMonitor Enter");
388     {
389         std::unique_lock<std::mutex> lock(statusMonitorMutex);
390         statusMonitorOn = false;
391     }
392     statusMonitorCondition.notify_one();
393     if (statusMonitorThread.joinable()) {
394         statusMonitorThread.join();
395     }
396     PRINT_HILOGI("StopStatusMonitor Quit");
397 }
398 
StatusMonitorProcess()399 void VendorManager::StatusMonitorProcess()
400 {
401     PRINT_HILOGI("StatusMonitorProcess Enter");
402     while (WaitNext()) {
403         UpdateAllPrinterStatus();
404     }
405     PRINT_HILOGI("StatusMonitorProcess Quit");
406 }
407 
UpdateAllPrinterStatus()408 void VendorManager::UpdateAllPrinterStatus()
409 {
410     std::lock_guard<std::mutex> lock(vendorMapMutex);
411     for (auto const &pair : vendorMap) {
412         if (pair.second == nullptr) {
413             PRINT_HILOGW("vendor extension is null");
414             continue;
415         }
416         pair.second->UpdateAllPrinterStatus();
417     }
418 }
419 
WaitNext()420 bool VendorManager::WaitNext()
421 {
422     std::unique_lock<std::mutex> lock(statusMonitorMutex);
423     if (!statusMonitorOn) {
424         return false;
425     }
426     statusMonitorCondition.wait_for(lock, std::chrono::milliseconds(MONITOR_CHECK_INTERVAL_MS));
427     if (!statusMonitorOn) {
428         return false;
429     }
430     return true;
431 }
432 
MonitorPrinterStatus(const std::string &globalPrinterId, bool on)433 bool VendorManager::MonitorPrinterStatus(const std::string &globalPrinterId, bool on)
434 {
435     std::string globalVendorName = ExtractGlobalVendorName(globalPrinterId);
436     std::string printerId = ExtractPrinterId(globalPrinterId);
437     if (globalVendorName.empty() || printerId.empty()) {
438         PRINT_HILOGW("invalid printer id: %{private}s", globalPrinterId.c_str());
439         return false;
440     }
441     std::string vendorName = ExtractVendorName(globalVendorName);
442     if (vendorName.empty()) {
443         PRINT_HILOGW("vendor name empty");
444         return false;
445     }
446     auto vendorDriver = FindDriverByVendorName(vendorName);
447     if (vendorDriver == nullptr) {
448         PRINT_HILOGW("vendor driver is null");
449         return false;
450     }
451     return vendorDriver->MonitorPrinterStatus(printerId, on);
452 }
453 
IsConnectingPrinter(const std::string &id, const std::string &uri)454 bool VendorManager::IsConnectingPrinter(const std::string &id, const std::string &uri)
455 {
456     std::lock_guard<std::mutex> lock(simpleObjectMutex);
457     if (isConnecting && !connectingPrinter.empty()) {
458         if (connectingMethod == ID_AUTO) {
459             return id == connectingPrinter;
460         } else {
461             return uri.find(connectingPrinter) != std::string::npos;
462         }
463     }
464     return false;
465 }
466 
SetConnectingPrinter(ConnectMethod method, const std::string &printer)467 void VendorManager::SetConnectingPrinter(ConnectMethod method, const std::string &printer)
468 {
469     std::lock_guard<std::mutex> lock(simpleObjectMutex);
470     connectingMethod = method;
471     connectingPrinter = printer;
472     isConnecting = true;
473 }
474 
ClearConnectingPrinter()475 void VendorManager::ClearConnectingPrinter()
476 {
477     PRINT_HILOGD("ClearConnectingPrinter");
478     std::lock_guard<std::mutex> lock(simpleObjectMutex);
479     isConnecting = false;
480 }
481 
QueryPrinterCapabilityByUri(const std::string &uri, PrinterCapability &printerCap)482 bool VendorManager::QueryPrinterCapabilityByUri(const std::string &uri, PrinterCapability &printerCap)
483 {
484     if (printServiceAbility == nullptr) {
485         PRINT_HILOGW("printServiceAbility is null");
486         return false;
487     }
488     return printServiceAbility->QueryPrinterCapabilityByUri(uri, printerCap);
489 }
490 
QueryPrinterStatusByUri(const std::string &uri, PrinterStatus &status)491 bool VendorManager::QueryPrinterStatusByUri(const std::string &uri, PrinterStatus &status)
492 {
493     if (printServiceAbility == nullptr) {
494         PRINT_HILOGW("printServiceAbility is null");
495         return false;
496     }
497     return printServiceAbility->QueryPrinterStatusByUri(uri, status);
498 }
499