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 "vendor_ipp_everywhere.h"
17 #include "print_log.h"
18 #include <nlohmann/json.hpp>
19 
20 using namespace OHOS::Print;
21 using json = nlohmann::json;
22 
VendorIppEveryWhere()23 VendorIppEveryWhere::VendorIppEveryWhere() {}
24 
~VendorIppEveryWhere()25 VendorIppEveryWhere::~VendorIppEveryWhere() {}
26 
GetVendorName()27 std::string VendorIppEveryWhere::GetVendorName()
28 {
29     return "driver.ipp.everywhere";
30 }
31 
Init(IPrinterVendorManager *manager)32 bool VendorIppEveryWhere::Init(IPrinterVendorManager *manager)
33 {
34     if (!VendorDriverBase::Init(manager)) {
35         PRINT_HILOGD("VendorDriverBase init fail");
36         return false;
37     }
38     return true;
39 }
UnInit()40 void VendorIppEveryWhere::UnInit()
41 {
42     VendorDriverBase::UnInit();
43 }
OnCreate()44 void VendorIppEveryWhere::OnCreate()
45 {
46     opQueue.Run();
47 }
OnDestroy()48 void VendorIppEveryWhere::OnDestroy()
49 {
50     opQueue.Stop();
51 }
OnStartDiscovery()52 void VendorIppEveryWhere::OnStartDiscovery() {}
OnStopDiscovery()53 void VendorIppEveryWhere::OnStopDiscovery() {}
54 
OnQueryCapability(const std::string &printerId, int timeout)55 bool VendorIppEveryWhere::OnQueryCapability(const std::string &printerId, int timeout)
56 {
57     auto op = std::bind(&VendorIppEveryWhere::QueryCapabilityByUri, this, printerId);
58     return opQueue.Push(op);
59 }
60 
OnQueryCapabilityByIp(const std::string &printerIp, const std::string &protocol)61 bool VendorIppEveryWhere::OnQueryCapabilityByIp(const std::string &printerIp, const std::string &protocol)
62 {
63     if (protocol != "auto" && protocol != "ipp") {
64         PRINT_HILOGW("protocol not support");
65         return false;
66     }
67     PRINT_HILOGI("QueryCapabilityByIp begin");
68     std::string uri = "ipp://" + printerIp + ":631/ipp/print";
69     auto op = std::bind(&VendorIppEveryWhere::ConnectPrinterByUri, this, uri);
70     return opQueue.Push(op);
71 }
72 
OnQueryProperties(const std::string &printerId, const std::vector<std::string> &propertyKeys)73 bool VendorIppEveryWhere::OnQueryProperties(const std::string &printerId, const std::vector<std::string> &propertyKeys)
74 {
75     bool ret = false;
76     for (auto const &key : propertyKeys) {
77         if (key == PRINTER_PROPERTY_KEY_DEVICE_STATE) {
78             auto op = std::bind(&VendorIppEveryWhere::QueryPrinterStatusByUri, this, printerId);
79             if (opQueue.Push(op)) {
80                 ret = true;
81             }
82         }
83     }
84     return ret;
85 }
86 
QueryCapabilityByUri(const std::string &uri)87 void VendorIppEveryWhere::QueryCapabilityByUri(const std::string &uri)
88 {
89     PRINT_HILOGI("QueryCapabilityByUri enter");
90     auto printerInfo = QueryPrinterInfoByUri(uri);
91     if (!UpdateCapability(printerInfo)) {
92         PRINT_HILOGW("update capability fail");
93         return;
94     }
95     PRINT_HILOGI("QueryCapabilityByUri quit");
96 }
97 
ConnectPrinterByUri(const std::string &uri)98 void VendorIppEveryWhere::ConnectPrinterByUri(const std::string &uri)
99 {
100     PRINT_HILOGI("ConnectPrinterByUri enter");
101     auto printerInfo = QueryPrinterInfoByUri(uri);
102     if (!ConnectPrinter(printerInfo)) {
103         PRINT_HILOGW("connect fail");
104         return;
105     }
106     PRINT_HILOGI("ConnectPrinterByUri quit");
107 }
108 
UpdateCapability(std::shared_ptr<PrinterInfo> printerInfo)109 bool VendorIppEveryWhere::UpdateCapability(std::shared_ptr<PrinterInfo> printerInfo)
110 {
111     if (vendorManager == nullptr) {
112         PRINT_HILOGW("vendorManager is null");
113         return false;
114     }
115     if (printerInfo == nullptr) {
116         PRINT_HILOGW("printerInfo fail");
117         return false;
118     }
119     PRINT_HILOGI("get printer info success");
120     if (vendorManager->UpdatePrinterToDiscovery(GetVendorName(), *printerInfo) != EXTENSION_ERROR_NONE) {
121         PRINT_HILOGW("UpdatePrinterToDiscovery fail");
122         return false;
123     }
124     return true;
125 }
126 
ConnectPrinter(std::shared_ptr<PrinterInfo> printerInfo)127 bool VendorIppEveryWhere::ConnectPrinter(std::shared_ptr<PrinterInfo> printerInfo)
128 {
129     if (vendorManager == nullptr) {
130         PRINT_HILOGW("vendorManager is null");
131         return false;
132     }
133     if (printerInfo == nullptr) {
134         PRINT_HILOGW("printer info fail");
135         return false;
136     }
137     PRINT_HILOGI("get printer info success");
138     if (vendorManager->UpdatePrinterToDiscovery(GetVendorName(), *printerInfo) != EXTENSION_ERROR_NONE) {
139         PRINT_HILOGW("UpdatePrinterToDiscovery fail");
140         return false;
141     }
142     PRINT_HILOGI("UpdatePrinterToDiscovery success");
143     if (vendorManager->AddPrinterToCupsWithPpd(GetVendorName(), printerInfo->GetPrinterId(), "") !=
144         EXTENSION_ERROR_NONE) {
145         PRINT_HILOGW("AddPrinterToCupsWithPpd fail");
146         return false;
147     }
148     return true;
149 }
150 
QueryPrinterInfoByUri(const std::string &uri)151 std::shared_ptr<PrinterInfo> VendorIppEveryWhere::QueryPrinterInfoByUri(const std::string &uri)
152 {
153     if (vendorManager == nullptr) {
154         PRINT_HILOGW("vendorManager is null");
155         return nullptr;
156     }
157     PrinterCapability printerCap;
158     if (!vendorManager->QueryPrinterCapabilityByUri(uri, printerCap)) {
159         PRINT_HILOGW("QueryPrinterCapabilityByUri fail");
160         return nullptr;
161     }
162     PRINT_HILOGI("QueryPrinterCapabilityByUri success");
163     return ConvertCapabilityToInfo(printerCap, uri);
164 }
165 
ConvertCapabilityToInfo(const PrinterCapability &printerCap, const std::string &printerUri)166 std::shared_ptr<PrinterInfo> VendorIppEveryWhere::ConvertCapabilityToInfo(const PrinterCapability &printerCap,
167     const std::string &printerUri)
168 {
169     if (!printerCap.HasOption()) {
170         PRINT_HILOGW("empty option");
171         return nullptr;
172     }
173     std::string capOption = printerCap.GetOption();
174     if (!json::accept(capOption)) {
175         PRINT_HILOGW("invalid option");
176         return nullptr;
177     }
178     nlohmann::json capJson = json::parse(capOption, nullptr, false);
179     if (capJson.is_discarded()) {
180         PRINT_HILOGW("json discarded");
181         return nullptr;
182     }
183     if (!capJson.contains("printerName") || !capJson["printerName"].is_string()) {
184         PRINT_HILOGW("printerName invalid");
185         return nullptr;
186     }
187     std::string printerName = capJson["printerName"].get<std::string>();
188     if (!capJson.contains("make") || !capJson["make"].is_string()) {
189         PRINT_HILOGW("make invalid");
190         return nullptr;
191     }
192     std::string printerMaker = capJson["make"].get<std::string>();
193     std::shared_ptr<PrinterInfo> printerInfo = std::make_shared<PrinterInfo>();
194     printerInfo->SetPrinterName(printerName);
195     printerInfo->SetUri(printerUri);
196     printerInfo->SetPrinterMake(printerMaker);
197     printerInfo->SetPrinterId(printerUri);
198     printerInfo->SetPrinterState(PRINTER_UPDATE_CAP);
199     printerInfo->SetCapability(printerCap);
200     nlohmann::json option;
201     option["printerName"] = printerName;
202     option["printerUri"] = printerUri;
203     option["make"] = printerMaker;
204     printerInfo->SetOption(option.dump());
205     return printerInfo;
206 }
207 
QueryPrinterStatusByUri(const std::string &uri)208 void VendorIppEveryWhere::QueryPrinterStatusByUri(const std::string &uri)
209 {
210     if (vendorManager == nullptr) {
211         PRINT_HILOGW("vendorManager is null");
212         return;
213     }
214     PrinterStatus status = PRINTER_STATUS_UNAVAILABLE;
215     if (!vendorManager->QueryPrinterStatusByUri(uri, status)) {
216         return;
217     }
218     OnPrinterStateQueried(uri, static_cast<Print_PrinterState>(status));
219 }
220