lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / desktop / source / lib / lokinteractionhandler.cxx
blobb41d17737b1653383b379b4157acc51295351c90
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "lokinteractionhandler.hxx"
22 #include <boost/property_tree/json_parser.hpp>
24 #include <rtl/ref.hxx>
25 #include <cppuhelper/supportsservice.hxx>
27 #include <com/sun/star/task/XInteractionAbort.hpp>
28 #include <com/sun/star/task/XInteractionApprove.hpp>
29 #include <com/sun/star/task/XInteractionPassword2.hpp>
30 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
31 #include <com/sun/star/ucb/InteractiveNetworkOffLineException.hpp>
33 #include <com/sun/star/ucb/InteractiveIOException.hpp>
34 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
35 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
36 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
38 #include <com/sun/star/task/DocumentPasswordRequest2.hpp>
39 #include <com/sun/star/task/DocumentMSPasswordRequest2.hpp>
41 #include "../../inc/lib/init.hxx"
43 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
44 #include <sfx2/lokhelper.hxx>
45 #include <sfx2/viewsh.hxx>
47 using namespace com::sun::star;
49 LOKInteractionHandler::LOKInteractionHandler(
50 const OString& rCommand,
51 desktop::LibLibreOffice_Impl *const pLOKit,
52 desktop::LibLODocument_Impl *const pLOKDocument)
53 : m_pLOKit(pLOKit)
54 , m_pLOKDocument(pLOKDocument)
55 , m_command(rCommand)
56 , m_usePassword(false)
58 assert(m_pLOKit);
61 LOKInteractionHandler::~LOKInteractionHandler()
65 OUString SAL_CALL LOKInteractionHandler::getImplementationName()
67 return "com.sun.star.comp.uui.LOKInteractionHandler";
70 sal_Bool SAL_CALL LOKInteractionHandler::supportsService(OUString const & rServiceName)
72 return cppu::supportsService(this, rServiceName);
75 uno::Sequence< OUString > SAL_CALL LOKInteractionHandler::getSupportedServiceNames()
77 uno::Sequence< OUString > aNames(3);
78 aNames[0] = "com.sun.star.task.InteractionHandler";
79 // added to indicate support for configuration.backend.MergeRecoveryRequest
80 aNames[1] = "com.sun.star.configuration.backend.InteractionHandler";
81 aNames[2] = "com.sun.star.uui.InteractionHandler";
82 // for backwards compatibility
83 return aNames;
86 void SAL_CALL LOKInteractionHandler::initialize(uno::Sequence<uno::Any> const & /*rArguments*/)
90 void SAL_CALL LOKInteractionHandler::handle(
91 uno::Reference<task::XInteractionRequest> const & xRequest)
93 // just do the same thing in both cases
94 handleInteractionRequest(xRequest);
97 void LOKInteractionHandler::postError(css::task::InteractionClassification classif, const char* kind, ErrCode code, const OUString &message)
99 const char *classification = "error";
100 switch (classif)
102 case task::InteractionClassification_ERROR: break;
103 case task::InteractionClassification_WARNING: classification = "warning"; break;
104 case task::InteractionClassification_INFO: classification = "info"; break;
105 case task::InteractionClassification_QUERY: classification = "query"; break;
106 default: assert(false); break;
109 // create the JSON representation
110 boost::property_tree::ptree aTree;
111 aTree.put("classification", classification);
112 aTree.put("cmd", m_command.getStr());
113 aTree.put("kind", kind);
114 aTree.put("code", code);
115 aTree.put("message", message.toUtf8());
117 std::stringstream aStream;
118 boost::property_tree::write_json(aStream, aTree);
120 std::size_t nView = SfxViewShell::Current() ? SfxLokHelper::getView() : 0;
121 if (m_pLOKDocument && m_pLOKDocument->mpCallbackFlushHandlers.count(nView))
122 m_pLOKDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_ERROR, aStream.str().c_str());
123 else if (m_pLOKit->mpCallback)
124 m_pLOKit->mpCallback(LOK_CALLBACK_ERROR, aStream.str().c_str(), m_pLOKit->mpCallbackData);
127 namespace {
129 /// Just approve the interaction.
130 void selectApproved(uno::Sequence<uno::Reference<task::XInteractionContinuation>> const &rContinuations)
132 for (sal_Int32 i = 0; i < rContinuations.getLength(); ++i)
134 uno::Reference<task::XInteractionApprove> xApprove(rContinuations[i], uno::UNO_QUERY);
135 if (xApprove.is())
136 xApprove->select();
142 bool LOKInteractionHandler::handleIOException(const css::uno::Sequence<css::uno::Reference<css::task::XInteractionContinuation>> &rContinuations, const css::uno::Any& rRequest)
144 ucb::InteractiveIOException aIoException;
145 if (!(rRequest >>= aIoException))
146 return false;
148 static ErrCode const aErrorCode[int(ucb::IOErrorCode_WRONG_VERSION) + 1] =
150 ERRCODE_IO_ABORT,
151 ERRCODE_IO_ACCESSDENIED,
152 ERRCODE_IO_ALREADYEXISTS,
153 ERRCODE_IO_BADCRC,
154 ERRCODE_IO_CANTCREATE,
155 ERRCODE_IO_CANTREAD,
156 ERRCODE_IO_CANTSEEK,
157 ERRCODE_IO_CANTTELL,
158 ERRCODE_IO_CANTWRITE,
159 ERRCODE_IO_CURRENTDIR,
160 ERRCODE_IO_DEVICENOTREADY,
161 ERRCODE_IO_NOTSAMEDEVICE,
162 ERRCODE_IO_GENERAL,
163 ERRCODE_IO_INVALIDACCESS,
164 ERRCODE_IO_INVALIDCHAR,
165 ERRCODE_IO_INVALIDDEVICE,
166 ERRCODE_IO_INVALIDLENGTH,
167 ERRCODE_IO_INVALIDPARAMETER,
168 ERRCODE_IO_ISWILDCARD,
169 ERRCODE_IO_LOCKVIOLATION,
170 ERRCODE_IO_MISPLACEDCHAR,
171 ERRCODE_IO_NAMETOOLONG,
172 ERRCODE_IO_NOTEXISTS,
173 ERRCODE_IO_NOTEXISTSPATH,
174 ERRCODE_IO_NOTSUPPORTED,
175 ERRCODE_IO_NOTADIRECTORY,
176 ERRCODE_IO_NOTAFILE,
177 ERRCODE_IO_OUTOFSPACE,
178 ERRCODE_IO_TOOMANYOPENFILES,
179 ERRCODE_IO_OUTOFMEMORY,
180 ERRCODE_IO_PENDING,
181 ERRCODE_IO_RECURSIVE,
182 ERRCODE_IO_UNKNOWN,
183 ERRCODE_IO_WRITEPROTECTED,
184 ERRCODE_IO_WRONGFORMAT,
185 ERRCODE_IO_WRONGVERSION,
188 postError(aIoException.Classification, "io", aErrorCode[static_cast<int>(aIoException.Code)], "");
189 selectApproved(rContinuations);
191 return true;
194 bool LOKInteractionHandler::handleNetworkException(const uno::Sequence<uno::Reference<task::XInteractionContinuation>> &rContinuations, const uno::Any &rRequest)
196 ucb::InteractiveNetworkException aNetworkException;
197 if (!(rRequest >>= aNetworkException))
198 return false;
200 ErrCode nErrorCode;
201 OUString aMessage;
203 ucb::InteractiveNetworkOffLineException aOffLineException;
204 ucb::InteractiveNetworkResolveNameException aResolveNameException;
205 ucb::InteractiveNetworkConnectException aConnectException;
206 ucb::InteractiveNetworkReadException aReadException;
207 ucb::InteractiveNetworkWriteException aWriteException;
208 if (rRequest >>= aOffLineException)
210 nErrorCode = ERRCODE_INET_OFFLINE;
212 else if (rRequest >>= aResolveNameException)
214 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
215 aMessage = aResolveNameException.Server;
217 else if (rRequest >>= aConnectException)
219 nErrorCode = ERRCODE_INET_CONNECT;
220 aMessage = aConnectException.Server;
222 else if (rRequest >>= aReadException)
224 nErrorCode = ERRCODE_INET_READ;
225 aMessage = aReadException.Diagnostic;
227 else if (rRequest >>= aWriteException)
229 nErrorCode = ERRCODE_INET_WRITE;
230 aMessage = aWriteException.Diagnostic;
232 else
234 nErrorCode = ERRCODE_INET_GENERAL;
237 postError(aNetworkException.Classification, "network", nErrorCode, aMessage);
238 selectApproved(rContinuations);
240 return true;
243 bool LOKInteractionHandler::handlePasswordRequest(const uno::Sequence<uno::Reference<task::XInteractionContinuation>> &rContinuations, const uno::Any &rRequest)
245 bool bPasswordRequestFound = false;
246 bool bIsRequestPasswordToModify = false;
248 OString sUrl;
250 task::DocumentPasswordRequest passwordRequest;
251 if (rRequest >>= passwordRequest)
253 bIsRequestPasswordToModify = false;
254 sUrl = passwordRequest.Name.toUtf8();
255 bPasswordRequestFound = true;
258 task::DocumentPasswordRequest2 passwordRequest2;
259 if (rRequest >>= passwordRequest2)
261 bIsRequestPasswordToModify = passwordRequest2.IsRequestPasswordToModify;
262 sUrl = passwordRequest2.Name.toUtf8();
263 bPasswordRequestFound = true;
266 task::DocumentMSPasswordRequest2 passwordMSRequest;
267 if (rRequest >>= passwordMSRequest)
269 bIsRequestPasswordToModify = passwordMSRequest.IsRequestPasswordToModify;
270 sUrl = passwordMSRequest.Name.toUtf8();
271 bPasswordRequestFound = true;
274 if (!bPasswordRequestFound)
275 return false;
277 if (m_pLOKit->mpCallback &&
278 m_pLOKit->hasOptionalFeature(bIsRequestPasswordToModify ? LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY
279 : LOK_FEATURE_DOCUMENT_PASSWORD))
281 m_pLOKit->mpCallback(bIsRequestPasswordToModify ? LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY
282 : LOK_CALLBACK_DOCUMENT_PASSWORD,
283 sUrl.getStr(),
284 m_pLOKit->mpCallbackData);
286 // block until SetPassword is called
287 m_havePassword.wait();
288 m_havePassword.reset();
291 for (sal_Int32 i = 0; i < rContinuations.getLength(); ++i)
293 if (m_usePassword)
295 if (bIsRequestPasswordToModify)
297 uno::Reference<task::XInteractionPassword2> const xIPW2(rContinuations[i], uno::UNO_QUERY);
298 xIPW2->setPasswordToModify(m_Password);
299 xIPW2->select();
301 else
303 uno::Reference<task::XInteractionPassword> const xIPW(rContinuations[i], uno::UNO_QUERY);
304 if (xIPW.is())
306 xIPW->setPassword(m_Password);
307 xIPW->select();
311 else
313 if (bIsRequestPasswordToModify)
315 uno::Reference<task::XInteractionPassword2> const xIPW2(rContinuations[i], uno::UNO_QUERY);
316 xIPW2->setRecommendReadOnly(true);
317 xIPW2->select();
319 else
321 uno::Reference<task::XInteractionAbort> const xAbort(rContinuations[i], uno::UNO_QUERY);
322 if (xAbort.is())
324 xAbort->select();
329 return true;
332 sal_Bool SAL_CALL LOKInteractionHandler::handleInteractionRequest(
333 const uno::Reference<task::XInteractionRequest>& xRequest)
335 uno::Sequence<uno::Reference<task::XInteractionContinuation>> const &rContinuations = xRequest->getContinuations();
336 uno::Any const request(xRequest->getRequest());
338 if (handleIOException(rContinuations, request))
339 return true;
341 if (handleNetworkException(rContinuations, request))
342 return true;
344 if (handlePasswordRequest(rContinuations, request))
345 return true;
347 // TODO: perform more interactions 'for real' like the above
348 selectApproved(rContinuations);
350 return true;
353 void LOKInteractionHandler::SetPassword(char const*const pPassword)
355 if (pPassword)
357 m_Password = OUString(pPassword, strlen(pPassword), RTL_TEXTENCODING_UTF8);
358 m_usePassword = true;
360 else
362 m_usePassword = false;
364 m_havePassword.set();
367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */