summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyungwook Tak <k.tak@samsung.com>2017-01-03 14:40:43 +0900
committerKyungwook Tak <k.tak@samsung.com>2017-01-03 14:41:36 +0900
commit5f1d1989e7a06177f92f8b59a77dbe41deb3b281 (patch)
tree24a2fb876e8630fe10592cd5fd5d4fd21c377396
parent6aff7acc014aed787a82e5bb4b4ddf9d8f7a2d9a (diff)
parentf80234bc765938c851be148ad79c27456b91998a (diff)
downloadcsr-framework-5f1d1989e7a06177f92f8b59a77dbe41deb3b281.tar.gz
csr-framework-5f1d1989e7a06177f92f8b59a77dbe41deb3b281.tar.bz2
csr-framework-5f1d1989e7a06177f92f8b59a77dbe41deb3b281.zip
Release 2.3.0
* Mainloop backend layer added * Popup service uses one ecore mainloop Change-Id: Ic6a140928193c64e908c4168ad868798710b0222 Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
-rw-r--r--packaging/csr-framework.spec2
-rw-r--r--src/framework/CMakeLists.txt2
-rw-r--r--src/framework/client/async-logic.cpp20
-rw-r--r--src/framework/client/async-logic.h2
-rw-r--r--src/framework/common/mainloop.h96
-rw-r--r--src/framework/common/native-mainloop.cpp (renamed from src/framework/common/mainloop.cpp)91
-rw-r--r--src/framework/common/native-mainloop.h56
-rw-r--r--src/framework/common/service.cpp65
-rw-r--r--src/framework/common/service.h8
-rw-r--r--src/framework/common/socket.h1
-rw-r--r--src/framework/service/file-system.cpp97
-rw-r--r--src/framework/service/file-system.h2
-rw-r--r--src/framework/service/server-service.cpp8
-rw-r--r--src/framework/ui/popup/CMakeLists.txt1
-rw-r--r--src/framework/ui/popup/ecore-mainloop.cpp161
-rw-r--r--src/framework/ui/popup/ecore-mainloop.h59
-rw-r--r--[-rwxr-xr-x]src/framework/ui/popup/logic.cpp268
-rw-r--r--src/framework/ui/popup/logic.h32
-rw-r--r--src/framework/ui/popup/popup-service.cpp83
-rw-r--r--src/framework/ui/popup/popup.cpp110
-rw-r--r--src/framework/ui/popup/popup.h69
-rw-r--r--test/engine/content-screening/sample-engine.cpp24
22 files changed, 797 insertions, 460 deletions
diff --git a/packaging/csr-framework.spec b/packaging/csr-framework.spec
index 7c2b1b7..5325fdd 100644
--- a/packaging/csr-framework.spec
+++ b/packaging/csr-framework.spec
@@ -22,7 +22,7 @@
Summary: A general purpose content screening and reputation solution
Name: csr-framework
-Version: 2.2.1
+Version: 2.3.0
Release: 0
Source: %{name}-%{version}.tar.gz
License: Apache-2.0 and BSL-1.0
diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt
index 1db36f9..8cad4a3 100644
--- a/src/framework/CMakeLists.txt
+++ b/src/framework/CMakeLists.txt
@@ -48,7 +48,7 @@ SET(${TARGET_CSR_COMMON}_SRCS
common/em-context.cpp
common/kvp-container.cpp
common/dispatcher.cpp
- common/mainloop.cpp
+ common/native-mainloop.cpp
common/service.cpp
common/socket.cpp
common/socket-descriptor.cpp
diff --git a/src/framework/client/async-logic.cpp b/src/framework/client/async-logic.cpp
index 43ca501..ebe97f7 100644
--- a/src/framework/client/async-logic.cpp
+++ b/src/framework/client/async-logic.cpp
@@ -23,19 +23,22 @@
#include <cstdint>
#include <utility>
-#include <sys/epoll.h>
#include "common/exception.h"
#include "common/cs-detected.h"
#include "common/connection.h"
#include "common/async-protocol.h"
+#include "common/native-mainloop.h"
#include "common/audit/logger.h"
namespace Csr {
namespace Client {
AsyncLogic::AsyncLogic(HandleExt *handle, void *userdata) :
- m_handle(handle), m_userdata(userdata), m_dispatcherAsync(new Dispatcher(SockId::CS))
+ m_loop(new NativeMainloop()),
+ m_handle(handle),
+ m_userdata(userdata),
+ m_dispatcherAsync(new Dispatcher(SockId::CS))
{
}
@@ -63,15 +66,15 @@ void AsyncLogic::scanHelper(const CommandId &id, const StrSet &s)
auto fd = this->m_dispatcherAsync->getFd();
auto cancelEventFd = this->m_cancelSignal.getFd();
- this->m_loop.addEventSource(cancelEventFd, EPOLLIN,
- [&](uint32_t) {
+ this->m_loop->addEventSource(cancelEventFd, Mainloop::Event::READ,
+ [&](Mainloop::Event) {
this->m_cancelSignal.receive();
ThrowExcInfo(ASYNC_EVENT_CANCEL, "Async event cancelled on fd: " << fd);
});
- this->m_loop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [&](uint32_t e) {
- if (e & (EPOLLHUP | EPOLLRDHUP))
+ this->m_loop->addEventSource(fd, Mainloop::Event::READ | Mainloop::Event::CLOSE,
+ [&](Mainloop::Event e) {
+ if ((e & Mainloop::Event::CLOSE) != Mainloop::Event::NONE)
ThrowExc(CSR_ERROR_SOCKET, "csr-server might be crashed. Finish async client loop");
// read event
@@ -121,8 +124,7 @@ void AsyncLogic::scanHelper(const CommandId &id, const StrSet &s)
});
try {
- while (true)
- this->m_loop.dispatch(-1);
+ this->m_loop->run(-1);
} catch (const Exception &e) {
switch (e.error()) {
case ASYNC_EVENT_COMPLETE:
diff --git a/src/framework/client/async-logic.h b/src/framework/client/async-logic.h
index 7e82857..6ef4b58 100644
--- a/src/framework/client/async-logic.h
+++ b/src/framework/client/async-logic.h
@@ -46,9 +46,9 @@ public:
private:
void scanHelper(const CommandId &id, const StrSet &s);
+ std::unique_ptr<Mainloop> m_loop;
HandleExt *m_handle; // for registering results for auto-release
void *m_userdata;
- Mainloop m_loop;
EventFd m_cancelSignal;
std::unique_ptr<Dispatcher> m_dispatcherAsync;
};
diff --git a/src/framework/common/mainloop.h b/src/framework/common/mainloop.h
index 18b04d2..3333214 100644
--- a/src/framework/common/mainloop.h
+++ b/src/framework/common/mainloop.h
@@ -1,40 +1,41 @@
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file mainloop.h
- * @author Kyungwook Tak (k.tak@samsung.com)
- * @version 1.0
- * @brief Manageloop of csr-server with epoll
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#pragma once
#include <functional>
-#include <mutex>
-#include <unordered_map>
+#include <utility>
+#include <type_traits>
#include "common/macros.h"
namespace Csr {
-class API Mainloop {
+class Mainloop {
public:
- using Callback = std::function<void(uint32_t event)>;
+ enum class Event : uint32_t {
+ NONE = 0,
+ READ = 1 << 0,
+ WRITE = 1 << 1,
+ CLOSE = 1 << 2
+ };
+
+ using Callback = std::function<void(Event event)>;
- Mainloop();
- virtual ~Mainloop();
+ Mainloop() : m_domainSourceNum(0) {}
+ virtual ~Mainloop() {}
Mainloop(const Mainloop &) = delete;
Mainloop &operator=(const Mainloop &) = delete;
@@ -43,27 +44,48 @@ public:
// timeout unit: seconds
// if timeout is negative value, no timeout on idle.
- void run(int timeout);
+ virtual void run(int timeout) = 0;
- // Moved to public to customize stop condition
- void dispatch(int timeout);
+ virtual void addEventSource(int fd, Event event, Callback &&callback) = 0;
+ virtual void removeEventSource(int fd) = 0;
- void addEventSource(int fd, uint32_t event, Callback &&callback);
- void removeEventSource(int fd);
- size_t countEventSource(void) const;
+ void addDomainEventSource(int fd, Event event, Callback &&callback)
+ {
+ ++this->m_domainSourceNum;
+ this->addEventSource(fd, event, std::move(callback));
+ }
- void setIdleChecker(std::function<bool()> &&idleChecker);
+protected:
+ size_t m_domainSourceNum;
+};
-private:
+template<typename T> using Underlying = typename std::underlying_type<T>::type;
+template<typename T>
+constexpr Underlying<T> underlying(T t) { return Underlying<T>(t); }
- bool m_isTimedOut;
- int m_pollfd;
- mutable std::mutex m_mutex;
- std::unordered_map<int, Callback> m_callbacks;
+inline constexpr Mainloop::Event operator&(Mainloop::Event e1, Mainloop::Event e2)
+{
+ return Mainloop::Event(underlying(e1) & underlying(e2));
+}
- std::function<bool()> m_isIdle;
+inline Mainloop::Event &operator&=(Mainloop::Event &e1, Mainloop::Event e2)
+{
+ return e1 = e1 & e2;
+}
- constexpr static size_t MAX_EPOLL_EVENTS = 32;
-};
+inline constexpr Mainloop::Event operator|(Mainloop::Event e1, Mainloop::Event e2)
+{
+ return Mainloop::Event(underlying(e1) | underlying(e2));
+}
+inline Mainloop::Event &operator|=(Mainloop::Event &e1, Mainloop::Event e2)
+{
+ return e1 = e1 | e2;
}
+
+inline constexpr Mainloop::Event operator~(Mainloop::Event e)
+{
+ return Mainloop::Event(~underlying(e));
+}
+
+} // namespace Csr
diff --git a/src/framework/common/mainloop.cpp b/src/framework/common/native-mainloop.cpp
index 55eb7c8..8e2de51 100644
--- a/src/framework/common/mainloop.cpp
+++ b/src/framework/common/native-mainloop.cpp
@@ -14,12 +14,12 @@
* limitations under the License
*/
/*
- * @file mainloop.cpp
+ * @file native-mainloop.cpp
* @author Kyungwook Tak (k.tak@samsung.com)
* @version 1.0
* @brief Mainloop of csr-server with epoll
*/
-#include "common/mainloop.h"
+#include "common/native-mainloop.h"
#include <system_error>
#include <sys/epoll.h>
@@ -30,7 +30,35 @@
namespace Csr {
-Mainloop::Mainloop() :
+uint32_t NativeMainloop::convertFlags(Mainloop::Event events)
+{
+ uint32_t flags = 0;
+
+ if ((events & Mainloop::Event::READ) != Mainloop::Event::NONE)
+ flags |= EPOLLIN;
+ if ((events & Mainloop::Event::WRITE) != Mainloop::Event::NONE)
+ flags |= EPOLLOUT;
+ if ((events & Mainloop::Event::CLOSE) != Mainloop::Event::NONE)
+ flags |= (EPOLLHUP | EPOLLRDHUP);
+
+ return flags;
+}
+
+Mainloop::Event NativeMainloop::convertFlags(uint32_t events)
+{
+ Mainloop::Event flags = Mainloop::Event::NONE;
+
+ if (events & EPOLLIN)
+ flags |= Mainloop::Event::READ;
+ if (events & EPOLLOUT)
+ flags |= Mainloop::Event::WRITE;
+ if (events & (EPOLLHUP | EPOLLRDHUP))
+ flags |= Mainloop::Event::CLOSE;
+
+ return flags;
+}
+
+NativeMainloop::NativeMainloop() :
m_isTimedOut(false),
m_pollfd(::epoll_create1(EPOLL_CLOEXEC))
{
@@ -40,7 +68,7 @@ Mainloop::Mainloop() :
"Failed to epoll_create1");
}
-Mainloop::~Mainloop()
+NativeMainloop::~NativeMainloop()
{
if (!this->m_isTimedOut && !this->m_callbacks.empty())
ERROR("mainloop registered callbacks should be empty except timed out case");
@@ -48,7 +76,7 @@ Mainloop::~Mainloop()
::close(m_pollfd);
}
-void Mainloop::run(int timeout)
+void NativeMainloop::run(int timeout)
{
this->m_isTimedOut = false;
@@ -56,21 +84,23 @@ void Mainloop::run(int timeout)
this->dispatch(timeout);
}
- DEBUG("Mainloop run stopped");
+ DEBUG("NativeMainloop run stopped");
}
-void Mainloop::addEventSource(int fd, uint32_t event, Callback &&callback)
+void NativeMainloop::addEventSource(
+ int fd, Mainloop::Event event, Mainloop::Callback &&callback)
{
std::lock_guard<std::mutex> l(this->m_mutex);
if (this->m_callbacks.count(fd) != 0)
ThrowExc(CSR_ERROR_SERVER, "event source on fd[" << fd << "] already added!");
- DEBUG("Add event[" << event << "] source on fd[" << fd << "]");
+ DEBUG("Add event[" << static_cast<uint32_t>(event)
+ << "] source on fd[" << fd << "]");
epoll_event e;
- e.events = event;
+ e.events = NativeMainloop::convertFlags(event);
e.data.fd = fd;
if (::epoll_ctl(m_pollfd, EPOLL_CTL_ADD, fd, &e) == -1)
@@ -81,16 +111,17 @@ void Mainloop::addEventSource(int fd, uint32_t event, Callback &&callback)
this->m_callbacks[fd] = std::move(callback);
}
-void Mainloop::removeEventSource(int fd)
+void NativeMainloop::removeEventSource(int fd)
{
std::lock_guard<std::mutex> l(this->m_mutex);
- if (this->m_callbacks.count(fd) == 0)
+ auto it = this->m_callbacks.find(fd);
+ if (it == this->m_callbacks.end())
ThrowExc(CSR_ERROR_SERVER, "event source on fd[" << fd << "] isn't added at all");
DEBUG("Remove event source on fd[" << fd << "]");
- this->m_callbacks.erase(fd);
+ this->m_callbacks.erase(it);
if (::epoll_ctl(m_pollfd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
if (errno == ENOENT)
@@ -102,18 +133,12 @@ void Mainloop::removeEventSource(int fd)
}
}
-size_t Mainloop::countEventSource() const
-{
- std::lock_guard<std::mutex> l(this->m_mutex);
- return this->m_callbacks.size();
-}
-
-void Mainloop::dispatch(int timeout)
+void NativeMainloop::dispatch(int timeout)
{
int nfds = -1;
epoll_event event[MAX_EPOLL_EVENTS];
- DEBUG("Mainloop dispatched with timeout: " << timeout);
+ DEBUG("NativeMainloop dispatched with timeout: " << timeout);
do {
nfds = ::epoll_wait(this->m_pollfd, event, MAX_EPOLL_EVENTS,
@@ -126,13 +151,13 @@ void Mainloop::dispatch(int timeout)
"epoll_wait failed!");
if (nfds == 0) {
- DEBUG("Mainloop timed out!");
- if (this->m_isIdle && !this->m_isIdle()) {
- INFO("Mainloop timed out but there's running task on upper layer. "
+ DEBUG("NativeMainloop timed out!");
+ if (this->m_callbacks.size() > this->m_domainSourceNum) {
+ INFO("NativeMainloop timed out but there's running task on upper layer. "
"Re-dispatch.");
this->m_isTimedOut = false;
} else {
- INFO("Mainloop timed out! stop the loop!");
+ INFO("NativeMainloop timed out! stop the loop!");
this->m_isTimedOut = true;
}
@@ -142,24 +167,22 @@ void Mainloop::dispatch(int timeout)
for (int i = 0; i < nfds; i++) {
int fd = event[i].data.fd;
- if (this->m_callbacks.count(fd) == 0)
+ auto it = this->m_callbacks.find(fd);
+ if (it == this->m_callbacks.end())
ThrowExc(CSR_ERROR_SERVER, "event in on fd[" << fd <<
"] but associated callback isn't exist!");
- if (event[i].events & (EPOLLHUP | EPOLLRDHUP)) {
+ auto events = convertFlags(event[i].events);
+ if ((events & Mainloop::Event::CLOSE) != Mainloop::Event::NONE) {
INFO("peer connection closed on fd[" << fd << "]");
- event[i].events &= ~EPOLLIN;
+ events &= ~Mainloop::Event::READ;
}
- DEBUG("event[" << event[i].events << "] polled on fd[" << fd << "]");
+ DEBUG("event[" << static_cast<uint32_t>(events)
+ << "] polled on fd[" << fd << "]");
- this->m_callbacks[fd](event[i].events);
+ it->second(events);
}
}
-void Mainloop::setIdleChecker(std::function<bool()> &&idleChecker)
-{
- this->m_isIdle = std::move(idleChecker);
-}
-
}
diff --git a/src/framework/common/native-mainloop.h b/src/framework/common/native-mainloop.h
new file mode 100644
index 0000000..04d6fa1
--- /dev/null
+++ b/src/framework/common/native-mainloop.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file native-mainloop.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Manageloop of csr-server with epoll
+ */
+#pragma once
+
+#include <functional>
+#include <mutex>
+#include <unordered_map>
+
+#include "common/mainloop.h"
+#include "common/macros.h"
+
+namespace Csr {
+
+class API NativeMainloop : public Mainloop {
+public:
+ NativeMainloop();
+ virtual ~NativeMainloop();
+
+ virtual void run(int timeout) override;
+ virtual void addEventSource(
+ int fd, Mainloop::Event event, Mainloop::Callback &&callback) override;
+ virtual void removeEventSource(int fd) override;
+
+private:
+ void dispatch(int timeout);
+ static uint32_t convertFlags(Mainloop::Event events);
+ static Mainloop::Event convertFlags(uint32_t events);
+
+ bool m_isTimedOut;
+ int m_pollfd;
+ mutable std::mutex m_mutex;
+ std::unordered_map<int, Mainloop::Callback> m_callbacks;
+
+ constexpr static size_t MAX_EPOLL_EVENTS = 32;
+};
+
+}
diff --git a/src/framework/common/service.cpp b/src/framework/common/service.cpp
index aef65e6..36430d0 100644
--- a/src/framework/common/service.cpp
+++ b/src/framework/common/service.cpp
@@ -30,8 +30,12 @@
namespace Csr {
-Service::Service() noexcept
+Service::Service(Mainloop *mainloop)
{
+ if (mainloop == nullptr)
+ throw std::invalid_argument("mainloop shouldn't be null");
+
+ this->m_loop.reset(mainloop);
}
Service::~Service()
@@ -53,16 +57,18 @@ void Service::start(int timeout)
DEBUG("Get systemd socket[" << socket->getFd() <<
"] for sock id: " << static_cast<int>(id));
- this->m_loop.addEventSource(socket->getFd(), EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [this, socket](uint32_t event) {
- if (event != EPOLLIN)
- return;
+ this->m_loop->addDomainEventSource(
+ socket->getFd(),
+ Mainloop::Event::READ | Mainloop::Event::CLOSE,
+ [this, socket](Mainloop::Event events) {
+ if ((events & Mainloop::Event::READ) == Mainloop::Event::NONE)
+ return;
- this->onNewConnection(std::make_shared<Connection>(socket->accept()));
- });
+ this->onNewConnection(std::make_shared<Connection>(socket->accept()));
+ });
}
- this->m_loop.run(timeout);
+ this->m_loop->run(timeout);
}
void Service::onNewConnection(ConnShPtr &&connection)
@@ -74,28 +80,29 @@ void Service::onNewConnection(ConnShPtr &&connection)
INFO("welcome! accepted client socket fd[" << fd << "]");
- this->m_loop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [&, fd](uint32_t event) {
- std::lock_guard<std::mutex> lock(this->m_crMtx);
+ this->m_loop->addEventSource(fd,
+ Mainloop::Event::READ | Mainloop::Event::CLOSE,
+ [&, fd](Mainloop::Event events) {
+ std::lock_guard<std::mutex> lock(this->m_crMtx);
- DEBUG("read event comes in to fd[" << fd << "]");
+ DEBUG("read event comes in to fd[" << fd << "]");
- if (this->m_connectionRegistry.count(fd) == 0)
- ThrowExc(CSR_ERROR_SERVER, "get event on fd[" << fd <<
- "] but no associated connection exist");
+ auto it = this->m_connectionRegistry.find(fd);
+ if (it == this->m_connectionRegistry.end())
+ ThrowExc(CSR_ERROR_SERVER, "get event on fd[" << fd <<
+ "] but no associated connection exist");
- auto &conn = this->m_connectionRegistry[fd];
-
- if (event & (EPOLLHUP | EPOLLRDHUP)) {
- DEBUG("event of epoll hup. close connection on fd[" << fd << "]");
- this->onCloseConnection(conn);
- return;
- }
+ auto &conn = it->second;
- DEBUG("Start message process on fd[" << fd << "]");
+ if ((events & Mainloop::Event::CLOSE) != Mainloop::Event::NONE) {
+ DEBUG("close event occured. close connection on fd[" << fd << "]");
+ this->onCloseConnection(conn);
+ return;
+ }
- onMessageProcess(conn);
- });
+ this->onMessageProcess(conn);
+ }
+ );
std::lock_guard<std::mutex> lock(this->m_crMtx);
this->m_connectionRegistry[fd] = std::move(connection);
@@ -108,15 +115,15 @@ void Service::onCloseConnection(const ConnShPtr &connection)
auto fd = connection->getFd();
- if (this->m_connectionRegistry.count(fd) == 0)
+ auto it = this->m_connectionRegistry.find(fd);
+ if (it == this->m_connectionRegistry.end())
ThrowExc(CSR_ERROR_SERVER, "no connection in registry to remove "
"associated to fd[" << fd << "]");
INFO("good-bye! close socket fd[" << fd << "]");
- this->m_loop.removeEventSource(fd);
-
- this->m_connectionRegistry.erase(fd);
+ this->m_loop->removeEventSource(fd);
+ this->m_connectionRegistry.erase(it);
}
}
diff --git a/src/framework/common/service.h b/src/framework/common/service.h
index 0e4195c..77ca336 100644
--- a/src/framework/common/service.h
+++ b/src/framework/common/service.h
@@ -21,9 +21,9 @@
*/
#pragma once
-#include <string>
-#include <functional>
#include <set>
+#include <memory>
+#include <unordered_map>
#include <mutex>
#include "common/macros.h"
@@ -35,7 +35,7 @@ namespace Csr {
class API Service {
public:
- Service() noexcept;
+ Service(Mainloop *mainloop);
virtual ~Service();
Service(const Service &) = delete;
@@ -47,7 +47,7 @@ public:
virtual void start(int timeout) final;
protected:
- Mainloop m_loop;
+ std::unique_ptr<Mainloop> m_loop;
private:
virtual void onMessageProcess(const ConnShPtr &) = 0;
diff --git a/src/framework/common/socket.h b/src/framework/common/socket.h
index 52a6a8a..24fd296 100644
--- a/src/framework/common/socket.h
+++ b/src/framework/common/socket.h
@@ -23,7 +23,6 @@
#include <string>
-#include "common/macros.h"
#include "common/types.h"
#include "common/socket-descriptor.h"
diff --git a/src/framework/service/file-system.cpp b/src/framework/service/file-system.cpp
index 2422a4d..8458052 100644
--- a/src/framework/service/file-system.cpp
+++ b/src/framework/service/file-system.cpp
@@ -301,54 +301,73 @@ void FsVisitor::run(const DirPtr &dirptr, const FilePtr &currentdir)
auto fullpath = (parent_dirpath.back() == '/') ?
(parent_dirpath + name) : (parent_dirpath + "/" + name);
- if (result->d_type == DT_DIR) {
+ INFO("start to traverse file: " << fullpath);
+
+ if (result->d_type == DT_LNK) {
+ if (!currentdir->isInApp())
+ continue;
+
+ auto stat = getStat(fullpath);
+ if (S_ISREG(stat->st_mode))
+ this->visitFile(fullpath, currentdir);
+ else if (S_ISDIR(stat->st_mode))
+ this->visitDir(fullpath, currentdir);
+
+ } else if (result->d_type == DT_DIR) {
if ((name_size == 1 && name[0] == '.') ||
(name_size == 2 && name[0] == '.' && name[1] == '.'))
continue;
- FilePtr ncurrentdir;
- try {
- ncurrentdir = File::create(fullpath, currentdir);
- } catch (const Exception &e) {
- if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST) {
- WARN("Perm denied to create file on pkg path: " << fullpath);
- continue;
- } else {
- throw;
- }
- }
-
- if (this->m_isBasedOnName && ncurrentdir->isInApp()) {
- this->m_targetHandler(ncurrentdir);
- } else {
- auto ndirptr = openDir(fullpath);
- if (ndirptr == nullptr) {
- WARN("Failed to open dir: " << fullpath << " with errno: " << errno);
- continue;
- }
-
- DEBUG("recurse dir : " << fullpath);
- this->run(ndirptr, ncurrentdir);
- }
+ this->visitDir(fullpath, currentdir);
} else if (result->d_type == DT_REG) {
- try {
- auto fileptr = File::createIfModified(fullpath, currentdir, this->m_since);
-
- if (fileptr)
- this->m_targetHandler(fileptr);
- } catch (const Exception &e) {
- if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST)
- WARN("file not exist: " << fullpath << " msg: " << e.what());
- else if (e.error() == CSR_ERROR_FILE_SYSTEM)
- WARN("file type is not regular...? can it be happened?"
- " :" << fullpath << " msg: " << e.what());
- else
- throw;
- }
+ this->visitFile(fullpath, currentdir);
}
}
}
+void FsVisitor::visitDir(const std::string &fullpath, const FilePtr &currentdir)
+{
+ FilePtr ncurrentdir;
+
+ try {
+ ncurrentdir = File::create(fullpath, currentdir);
+ } catch (const Exception &e) {
+ if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST) {
+ WARN("Perm denied to create file on pkg path: " << fullpath);
+ return;
+ } else {
+ throw;
+ }
+ }
+
+ if (this->m_isBasedOnName && ncurrentdir->isInApp()) {
+ this->m_targetHandler(ncurrentdir);
+ } else {
+ if (auto ndirptr = openDir(fullpath)) {
+ DEBUG("recurse dir: " << fullpath);
+ this->run(ndirptr, ncurrentdir);
+ } else {
+ WARN("Failed to open dir: " << fullpath << " with errno: " << errno);
+ }
+ }
+}
+
+void FsVisitor::visitFile(const std::string &fullpath, const FilePtr &currentdir)
+{
+ try {
+ if (auto fileptr = File::createIfModified(fullpath, currentdir, this->m_since))
+ this->m_targetHandler(fileptr);
+ } catch (const Exception &e) {
+ if (e.error() == CSR_ERROR_FILE_DO_NOT_EXIST)
+ WARN("file not exist: " << fullpath << " msg: " << e.what());
+ else if (e.error() == CSR_ERROR_FILE_SYSTEM)
+ WARN("file type is not regular...? can it be happened?"
+ " :" << fullpath << " msg: " << e.what());
+ else
+ throw;
+ }
+}
+
void FsVisitor::run()
{
auto currentdir = File::create(this->m_path, nullptr);
diff --git a/src/framework/service/file-system.h b/src/framework/service/file-system.h
index ee73279..7166c47 100644
--- a/src/framework/service/file-system.h
+++ b/src/framework/service/file-system.h
@@ -170,6 +170,8 @@ private:
using DirPtr = std::unique_ptr<Dir>;
void run(const DirPtr &dirptr, const FilePtr &currentdir);
+ void visitDir(const std::string &fullpath, const FilePtr &currentdir);
+ void visitFile(const std::string &fullpath, const FilePtr &currentdir);
static DirPtr openDir(const std::string &);
diff --git a/src/framework/service/server-service.cpp b/src/framework/service/server-service.cpp
index 24bd1bf..b540269 100644
--- a/src/framework/service/server-service.cpp
+++ b/src/framework/service/server-service.cpp
@@ -34,6 +34,7 @@
#include "common/wp-result.h"
#include "common/exception.h"
#include "common/async-protocol.h"
+#include "common/native-mainloop.h"
#include "service/exception.h"
#include "service/access-control.h"
#include "service/core-usage.h"
@@ -84,7 +85,7 @@ inline CommandId extractCommandId(BinaryQueue &q)
} // namespace anonymous
-ServerService::ServerService() : Service(), m_workqueue(5)
+ServerService::ServerService() : Service(new NativeMainloop()), m_workqueue(5)
{
this->m_db = std::make_shared<Db::Manager>(RW_DBSPACE "/.csr.db", RO_DBSPACE);
@@ -111,11 +112,6 @@ ServerService::ServerService() : Service(), m_workqueue(5)
this->add(SockId::CS);
this->add(SockId::WP);
this->add(SockId::ADMIN);
-
- // if task is not running in workqueue, it's idle.
- this->m_loop.setIdleChecker([this]()->bool {
- return (!this->m_workqueue.isTaskRunning() && this->m_loop.countEventSource() == 3);
- });
}
RawBuffer ServerService::processCs(const ConnShPtr &conn, RawBuffer &data)
diff --git a/src/framework/ui/popup/CMakeLists.txt b/src/framework/ui/popup/CMakeLists.txt
index 6f8dd01..ddc667b 100644
--- a/src/framework/ui/popup/CMakeLists.txt
+++ b/src/framework/ui/popup/CMakeLists.txt
@@ -39,6 +39,7 @@ SET(${TARGET_CSR_POPUP}_SRCS
logic.cpp
popup.cpp
popup-service.cpp
+ ecore-mainloop.cpp
package-info.cpp
${PROJECT_SOURCE_DIR}/src/framework/ui/common.cpp
)
diff --git a/src/framework/ui/popup/ecore-mainloop.cpp b/src/framework/ui/popup/ecore-mainloop.cpp
new file mode 100644
index 0000000..4e97e60
--- /dev/null
+++ b/src/framework/ui/popup/ecore-mainloop.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ecore-mainloop.h"
+
+#include <utility>
+#include <exception>
+
+#include "common/audit/logger.h"
+
+namespace Csr {
+namespace Ui {
+
+Ecore_Fd_Handler_Flags EcoreMainloop::convertFlags(Mainloop::Event events)
+{
+ uint32_t flags = 0;
+
+ if ((events & Mainloop::Event::READ) != Mainloop::Event::NONE)
+ flags |= ECORE_FD_READ;
+ if ((events & Mainloop::Event::WRITE) != Mainloop::Event::NONE)
+ flags |= ECORE_FD_WRITE;
+
+ return static_cast<Ecore_Fd_Handler_Flags>(flags);
+}
+
+Mainloop::Event EcoreMainloop::convertFlags(Ecore_Fd_Handler *handler)
+{
+ Mainloop::Event flags = Mainloop::Event::NONE;
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
+ flags |= Mainloop::Event::READ;
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE))
+ flags |= Mainloop::Event::WRITE;
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
+ flags |= Mainloop::Event::CLOSE;
+
+ return flags;
+}
+
+EcoreMainloop::EcoreMainloop() : m_isExitCalled(false), m_timer(nullptr) {}
+
+EcoreMainloop::~EcoreMainloop()
+{
+ if (this->m_timer)
+ ecore_timer_del(this->m_timer);
+
+ if (!this->m_isExitCalled)
+ elm_exit();
+}
+
+void EcoreMainloop::run(int timeout)
+{
+ this->dispatch(timeout);
+}
+
+void EcoreMainloop::dispatch(int timeout)
+{
+ if (timeout >= 0) {
+ this->m_timer = ecore_timer_add(
+ static_cast<double>(timeout), &EcoreMainloop::ecoreTimeoutCb, this);
+
+ if (this->m_timer == nullptr) {
+ ERROR("Failed to ecore_timer_add()...");
+ }
+ }
+
+ elm_run();
+}
+
+void EcoreMainloop::addEventSource(
+ int fd, Mainloop::Event events, Mainloop::Callback &&callback)
+{
+ auto handler = ecore_main_fd_handler_add(
+ fd, convertFlags(events),
+ &EcoreMainloop::ecoreFdCallback, this, nullptr, nullptr);
+
+ if (handler == nullptr) {
+ ERROR("failed to handle fd(" << fd << ") by ecore_main_fd_handler_add()");
+ return;
+ }
+
+ std::unique_ptr<EventSource> source(new EventSource);
+ source->callback = std::move(callback);
+ source->handler = handler;
+
+ this->m_sources[fd] = std::move(source);
+}
+
+void EcoreMainloop::removeEventSource(int fd)
+{
+ auto it = this->m_sources.find(fd);
+
+ if (it == this->m_sources.end()) {
+ ERROR("fd(" << fd << ") associated source is not found");
+ return;
+ }
+
+ ecore_main_fd_handler_del(it->second->handler);
+
+ this->m_sources.erase(it);
+}
+
+Eina_Bool EcoreMainloop::ecoreFdCallback(void *data, Ecore_Fd_Handler *handler)
+{
+ auto mainloop = static_cast<EcoreMainloop *>(data);
+
+ if (mainloop == nullptr)
+ throw std::invalid_argument("userdata for ecore fd callback is invalid");
+
+ int fd = ecore_main_fd_handler_fd_get(handler);
+
+ auto it = mainloop->m_sources.find(fd);
+ if (it == mainloop->m_sources.end() || it->second == nullptr) {
+ ERROR("no associated source found with fd: " << fd);
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ it->second->callback(convertFlags(handler));
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+Eina_Bool EcoreMainloop::ecoreTimeoutCb(void *data)
+{
+ auto mainloop = static_cast<EcoreMainloop *>(data);
+
+ if (mainloop == nullptr)
+ throw std::invalid_argument("userdata for ecore timeout callback is invalid");
+
+ if (mainloop->m_sources.size() == mainloop->m_domainSourceNum) {
+ INFO("There's no alive connection. Only listening socket opened. "
+ "Let's exit the ecore main loop!");
+
+ elm_exit();
+
+ mainloop->m_timer = nullptr;
+ mainloop->m_isExitCalled = true;
+
+ return ECORE_CALLBACK_CANCEL;
+ } else {
+ INFO("Time out expired but there's alive connection "
+ "so go ahead to next tick!");
+ return ECORE_CALLBACK_RENEW;
+ }
+}
+
+} // namespace Ui
+} // namespace Csr
diff --git a/src/framework/ui/popup/ecore-mainloop.h b/src/framework/ui/popup/ecore-mainloop.h
new file mode 100644
index 0000000..271b011
--- /dev/null
+++ b/src/framework/ui/popup/ecore-mainloop.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <unordered_map>
+#include <memory>
+#include <Elementary.h>
+
+#include "common/mainloop.h"
+
+namespace Csr {
+namespace Ui {
+
+class EcoreMainloop : public Mainloop {
+public:
+ EcoreMainloop();
+ virtual ~EcoreMainloop();
+
+ virtual void run(int timeout) override;
+
+ virtual void addEventSource(
+ int fd, Mainloop::Event event, Mainloop::Callback &&callback) override;
+ virtual void removeEventSource(int fd) override;
+
+private:
+ struct EventSource {
+ Mainloop::Callback callback;
+ Ecore_Fd_Handler *handler;
+ };
+
+ void dispatch(int timeout);
+
+ static Ecore_Fd_Handler_Flags convertFlags(Mainloop::Event events);
+ static Mainloop::Event convertFlags(Ecore_Fd_Handler *handler);
+
+ static Eina_Bool ecoreFdCallback(void *data, Ecore_Fd_Handler *handler);
+ static Eina_Bool ecoreTimeoutCb(void *data);
+
+ std::unordered_map<int, std::unique_ptr<EventSource>> m_sources;
+
+ bool m_isExitCalled;
+ Ecore_Timer *m_timer;
+};
+
+} // namespace Ui
+} // namespace Csr
diff --git a/src/framework/ui/popup/logic.cpp b/src/framework/ui/popup/logic.cpp
index ce8c83b..5b1a135 100755..100644
--- a/src/framework/ui/popup/logic.cpp
+++ b/src/framework/ui/popup/logic.cpp
@@ -57,7 +57,7 @@ void split(const std::string &s, std::string &fileName, std::string &extraPath)
extraPath = s.substr(0, idx);
}
-std::string formatToString(const char *form, std::string arg)
+std::string formatToString(const char *form, const std::string &arg)
{
std::vector<char> buf(PATH_MAX, '\0');
snprintf(buf.data(), buf.size(), form, arg.c_str());
@@ -65,254 +65,168 @@ std::string formatToString(const char *form, std::string arg)
}
} // namespace anonymous
-RawBuffer Logic::csPromptData(const std::string &message, const CsDetected &d) const
+void Logic::csPromptData(const std::string &message, const CsDetected &d)
{
std::string risk(d.severity ==
CSR_CS_SEVERITY_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
- Popup p(2);
-
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_PROMPT_DATA_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_PROMPT_DATA_HEADER);
+ m_popup.setBody(FORMAT(
"- " << LABEL_RISK << risk << " (" << d.malwareName << ")"));
- p.setFooter(CS_PROMPT_DATA_FOOTER);
-
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_OPEN);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
+ m_popup.setFooter(CS_PROMPT_DATA_FOOTER);
+ m_popup.setDetailedUrl(d.detailedUrl);
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_CANCEL, CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED),
+ Popup::Button(BTN_OPEN, CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED)});
}
-RawBuffer Logic::csPromptFile(const std::string &message, const CsDetected &d) const
+void Logic::csPromptFile(const std::string &message, const CsDetected &d)
{
std::string risk(d.severity ==
CSR_CS_SEVERITY_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
std::string fileName, extraPath;
split(d.targetName, fileName, extraPath);
- Popup p(3);
-
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_PROMPT_FILE_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_PROMPT_FILE_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_FILE_NAME, fileName) << "<br>" <<
"- " << formatToString(LABEL_FILE_PATH, extraPath) << "<br>" <<
"- " << LABEL_RISK << risk << " (" << d.malwareName << ")"));
std::string prefix(CS_NOTIFY_FILE_FOOTER);
- p.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_FILE_FOOTER));
-
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_OPEN);
- p.setText(p.m_buttons[2], BTN_DELETE);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_REMOVE));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_buttons[2], &p.m_types[2]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
+ m_popup.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_FILE_FOOTER));
+ m_popup.setDetailedUrl(d.detailedUrl);
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_CANCEL, CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED),
+ Popup::Button(BTN_OPEN, CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED),
+ Popup::Button(BTN_DELETE, CSR_CS_USER_RESPONSE_REMOVE)});
}
-RawBuffer Logic::csPromptApp(const std::string &message, const CsDetected &d) const
+void Logic::csPromptApp(const std::string &message, const CsDetected &d)
{
std::string risk(d.severity ==
CSR_CS_SEVERITY_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
PackageInfo info(d.pkgId);
- Popup p(3);
-
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_PROMPT_APP_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_PROMPT_APP_HEADER);
+ m_popup.setBody(FORMAT(
LABEL_APP_NAME << info.getLabel() << "<br>" <<
LABEL_VERSION << info.getVersion() << "<br>" <<
LABEL_RISK << risk << " (" << d.malwareName << ")"));
- p.setIcon(info.getIconPath());
+ m_popup.setIcon(info.getIconPath());
std::string prefix = formatToString(CS_NOTIFY_APP_FOOTER, BTN_UNINSTALL);
- p.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_APP_FOOTER));
-
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_OPEN);
- p.setText(p.m_buttons[2], BTN_UNINSTALL);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_REMOVE));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_buttons[2], &p.m_types[2]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
+ m_popup.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_APP_FOOTER));
+ m_popup.setDetailedUrl(d.detailedUrl);
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_CANCEL, CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED),
+ Popup::Button(BTN_OPEN, CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED),
+ Popup::Button(BTN_UNINSTALL, CSR_CS_USER_RESPONSE_REMOVE)});
}
-RawBuffer Logic::csNotifyData(const std::string &message, const CsDetected &d) const
+void Logic::csNotifyData(const std::string &message, const CsDetected &d)
{
- Popup p(1);
-
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_NOTIFY_DATA_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_NOTIFY_DATA_HEADER);
+ m_popup.setBody(FORMAT(
"- " << LABEL_RISK << LABEL_RISK_LEVEL_HIGH <<
" (" << d.malwareName << ")"));
- p.setFooter(CS_NOTIFY_DATA_FOOTER);
-
- p.setText(p.m_buttons[0], BTN_OK);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
+ m_popup.setFooter(CS_NOTIFY_DATA_FOOTER);
+ m_popup.setDetailedUrl(d.detailedUrl);
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_OK, CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED)});
}
-RawBuffer Logic::csNotifyFile(const std::string &message, const CsDetected &d) const
+void Logic::csNotifyFile(const std::string &message, const CsDetected &d)
{
- Popup p(2);
std::string fileName, extraPath;
split(d.targetName, fileName, extraPath);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_NOTIFY_FILE_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_NOTIFY_FILE_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_FILE_NAME, fileName) << "<br>" <<
"- " << formatToString(LABEL_FILE_PATH, extraPath) << "<br>" <<
"- " << LABEL_RISK << LABEL_RISK_LEVEL_HIGH <<
" (" << d.malwareName << ")"));
- p.setFooter(CS_NOTIFY_FILE_FOOTER);
+ m_popup.setFooter(CS_NOTIFY_FILE_FOOTER);
+ m_popup.setDetailedUrl(d.detailedUrl);
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_DELETE);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_REMOVE));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_CANCEL, CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED),
+ Popup::Button(BTN_DELETE, CSR_CS_USER_RESPONSE_REMOVE)});
}
-RawBuffer Logic::csNotifyApp(const std::string &message, const CsDetected &d) const
+void Logic::csNotifyApp(const std::string &message, const CsDetected &d)
{
PackageInfo info(d.pkgId);
- Popup p(2);
-
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_NOTIFY_APP_HEADER);
- p.setIcon(info.getIconPath());
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_NOTIFY_APP_HEADER);
+ m_popup.setIcon(info.getIconPath());
+ m_popup.setBody(FORMAT(
LABEL_APP_NAME << info.getLabel() << "<br>" <<
LABEL_VERSION << info.getVersion() << "<br>" <<
LABEL_RISK << LABEL_RISK_LEVEL_HIGH << " (" << d.malwareName << ")"));
- p.setFooter(formatToString(CS_NOTIFY_APP_FOOTER, BTN_UNINSTALL));
+ m_popup.setFooter(formatToString(CS_NOTIFY_APP_FOOTER, BTN_UNINSTALL));
+ m_popup.setDetailedUrl(d.detailedUrl);
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_UNINSTALL);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_CANCEL, CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED),
+ Popup::Button(BTN_UNINSTALL, CSR_CS_USER_RESPONSE_REMOVE)});
}
-RawBuffer Logic::wpPrompt(const std::string &message, const UrlItem &item) const
+void Logic::wpPrompt(const std::string &message, const UrlItem &item)
{
std::string risk(item.risk ==
CSR_WP_RISK_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
- Popup p(2);
-
- p.setMessage(message);
- p.setTitle(WP_TITLE);
- p.setHeader(WP_PROMPT_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(WP_TITLE);
+ m_popup.setHeader(WP_PROMPT_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_URL, item.url) << "<br>" <<
"- " << LABEL_RISK << risk));
- p.setFooter(WP_PROMPT_FOOTER);
+ m_popup.setFooter(WP_PROMPT_FOOTER);
+ m_popup.setDetailedUrl(item.url);
- p.setText(p.m_buttons[0], BTN_BLOCK);
- p.setText(p.m_buttons[1], BTN_VIEW);
-
- p.m_types.emplace_back(
- static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
- static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_ALLOWED));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, item.url);
-
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_BLOCK, CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED),
+ Popup::Button(BTN_VIEW, CSR_WP_USER_RESPONSE_PROCESSING_ALLOWED)});
}
-RawBuffer Logic::wpNotify(const std::string &message, const UrlItem &item) const
+void Logic::wpNotify(const std::string &message, const UrlItem &item)
{
- Popup p(1);
-
- p.setMessage(message);
- p.setTitle(WP_TITLE);
- p.setHeader(WP_NOTIFY_HEADER);
- p.setBody(FORMAT(
+ m_popup.reset();
+ m_popup.setMessage(message);
+ m_popup.setTitle(WP_TITLE);
+ m_popup.setHeader(WP_NOTIFY_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_URL, item.url) << "<br>" <<
"- " << LABEL_RISK << LABEL_RISK_LEVEL_HIGH));
- p.setFooter(WP_NOTIFY_FOOTER);
-
- p.setText(p.m_buttons[0], BTN_OK);
-
- p.m_types.emplace_back(static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED));
-
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_hypertext, item.url);
+ m_popup.setFooter(WP_NOTIFY_FOOTER);
+ m_popup.setDetailedUrl(item.url);
- p.run();
- return p.getResult();
+ m_popup.setButtons({
+ Popup::Button(BTN_OK, CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED)});
}
} // namespace Ui
} // namespace Csr
diff --git a/src/framework/ui/popup/logic.h b/src/framework/ui/popup/logic.h
index 50a50dd..bdde6cd 100644
--- a/src/framework/ui/popup/logic.h
+++ b/src/framework/ui/popup/logic.h
@@ -26,24 +26,32 @@
#include "common/types.h"
#include "common/cs-detected.h"
#include "ui/common.h"
+#include "popup.h"
namespace Csr {
namespace Ui {
class Logic {
public:
- Logic() = default;
- virtual ~Logic() = default;
-
- RawBuffer csPromptData(const std::string &, const CsDetected &) const;
- RawBuffer csPromptApp(const std::string &, const CsDetected &) const;
- RawBuffer csPromptFile(const std::string &, const CsDetected &) const;
- RawBuffer csNotifyData(const std::string &, const CsDetected &) const;
- RawBuffer csNotifyApp(const std::string &, const CsDetected &) const;
- RawBuffer csNotifyFile(const std::string &, const CsDetected &) const;
-
- RawBuffer wpPrompt(const std::string &, const UrlItem &) const;
- RawBuffer wpNotify(const std::string &, const UrlItem &) const;
+ Logic() {}
+ virtual ~Logic() {}
+
+ void csPromptData(const std::string &, const CsDetected &);
+ void csPromptApp(const std::string &, const CsDetected &);
+ void csPromptFile(const std::string &, const CsDetected &);
+ void csNotifyData(const std::string &, const CsDetected &);
+ void csNotifyApp(const std::string &, const CsDetected &);
+ void csNotifyFile(const std::string &, const CsDetected &);
+
+ void wpPrompt(const std::string &, const UrlItem &);
+ void wpNotify(const std::string &, const UrlItem &);
+
+ void setSender(Popup::Sender &&sender) {
+ m_popup.setSender(std::move(sender));
+ }
+
+private:
+ Popup m_popup;
};
} // namespace Ui
diff --git a/src/framework/ui/popup/popup-service.cpp b/src/framework/ui/popup/popup-service.cpp
index 186b847..43ed62f 100644
--- a/src/framework/ui/popup/popup-service.cpp
+++ b/src/framework/ui/popup/popup-service.cpp
@@ -1,30 +1,27 @@
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file popup-service.cpp
- * @author Kyungwook Tak (k.tak@samsung.com)
- * @version 1.0
- * @brief
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
+
#include "popup-service.h"
#include "common/binary-queue.h"
#include "common/audit/logger.h"
+#include "common/types.h"
#include "common/exception.h"
-#include "common/cs-detected.h"
+
+#include "ecore-mainloop.h"
namespace Csr {
namespace Ui {
@@ -51,22 +48,30 @@ bool isCsCommand(const CommandId &cid)
}
}
-} // namespace nonymous
+} // namespace anonymous
-PopupService::PopupService() : Service()
+PopupService::PopupService() : Csr::Service(new EcoreMainloop())
{
this->add(SockId::POPUP);
}
-RawBuffer PopupService::process(const ConnShPtr &, RawBuffer &data)
+void PopupService::onMessageProcess(const ConnShPtr &conn)
{
+ auto in = conn->receive();
+
+ // some fd handler from mainloop makes empty read event when client
+ // close connection. returning false from process() means connection
+ // is closed
+ if (in.empty())
+ throw std::invalid_argument("empty read event!");
+
BinaryQueue q;
- q.push(data);
+ q.push(std::move(in));
int intCid;
q.Deserialize(intCid);
- INFO("Request dispatch on popup-service. CommandId: " << static_cast<int>(intCid));
+ INFO("Request dispatch on popup service. CommandId: " << static_cast<int>(intCid));
if (isCsCommand(static_cast<Ui::CommandId>(intCid))) {
std::string message;
@@ -75,22 +80,28 @@ RawBuffer PopupService::process(const ConnShPtr &, RawBuffer &data)
switch (static_cast<Ui::CommandId>(intCid)) {
case CommandId::CS_PROMPT_DATA:
- return m_logic.csPromptData(message, d);
+ m_logic.csPromptData(message, d);
+ break;
case CommandId::CS_PROMPT_APP:
- return m_logic.csPromptApp(message, d);
+ m_logic.csPromptApp(message, d);
+ break;
case CommandId::CS_PROMPT_FILE:
- return m_logic.csPromptFile(message, d);
+ m_logic.csPromptFile(message, d);
+ break;
case CommandId::CS_NOTIFY_DATA:
- return m_logic.csNotifyData(message, d);
+ m_logic.csNotifyData(message, d);
+ break;
case CommandId::CS_NOTIFY_APP:
- return m_logic.csNotifyApp(message, d);
+ m_logic.csNotifyApp(message, d);
+ break;
case CommandId::CS_NOTIFY_FILE:
- return m_logic.csNotifyFile(message, d);
+ m_logic.csNotifyFile(message, d);
+ break;
default:
ThrowExc(CSR_ERROR_SERVER, "protocol error. invalid ui command id.");
@@ -102,25 +113,19 @@ RawBuffer PopupService::process(const ConnShPtr &, RawBuffer &data)
switch (static_cast<Ui::CommandId>(intCid)) {
case CommandId::WP_PROMPT:
- return m_logic.wpPrompt(message, item);
+ m_logic.wpPrompt(message, item);
+ break;
case CommandId::WP_NOTIFY:
- return m_logic.wpNotify(message, item);
+ m_logic.wpNotify(message, item);
+ break;
default:
ThrowExc(CSR_ERROR_SERVER, "protocol error. invalid ui command id.");
}
}
-}
-
-void PopupService::onMessageProcess(const ConnShPtr &connection)
-{
- DEBUG("process message on popup service");
-
- auto in = connection->receive();
- connection->send(this->process(connection, in));
- DEBUG("process done on popup service");
+ m_logic.setSender([conn](const RawBuffer &out) { conn->send(out); });
}
} // namespace Ui
diff --git a/src/framework/ui/popup/popup.cpp b/src/framework/ui/popup/popup.cpp
index 46a0cd3..7c8d3ec 100644
--- a/src/framework/ui/popup/popup.cpp
+++ b/src/framework/ui/popup/popup.cpp
@@ -43,8 +43,20 @@ namespace {
}
-Popup::Popup(int buttonN)
+void Popup::setSender(Sender &&sender)
{
+ m_sender = std::move(sender);
+}
+
+Popup::Popup() : m_win(nullptr)
+{
+ ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keyDownCb, this);
+}
+
+void Popup::reset()
+{
+ clear();
+
// Set win properties.
m_win = elm_win_add(nullptr, "CSR popup", ELM_WIN_NOTIFICATION);
elm_win_indicator_opacity_set(m_win, ELM_WIN_INDICATOR_TRANSLUCENT);
@@ -56,7 +68,6 @@ Popup::Popup(int buttonN)
setRotationToWin(m_win);
eext_win_keygrab_set(m_win, HOME_KEY.c_str());
- ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keyDownCb, NULL);
// Set popup properties.
m_popup = elm_popup_add(m_win);
@@ -105,22 +116,11 @@ Popup::Popup(int buttonN)
elm_box_pack_end(m_box, m_footer);
evas_object_show(m_footer);
- // Add buttons dynamically.
m_btnBox = elm_box_add(m_popup);
setDefaultProperties(m_btnBox);
elm_box_horizontal_set(m_btnBox, EINA_TRUE);
elm_box_padding_set(m_btnBox, 0, 0);
- for(int i=1 ; i <= buttonN; i++) {
- std::string id("button" + std::to_string(i));
- Evas_Object *button = elm_button_add(m_popup);
- elm_object_style_set(button, "bottom");
- setDefaultProperties(button);
- elm_box_pack_end(m_btnBox, button);
- evas_object_show(button);
- m_buttons.emplace_back(button);
- }
-
elm_box_pack_end(m_box, m_btnBox);
evas_object_show(m_btnBox);
@@ -132,7 +132,25 @@ Popup::Popup(int buttonN)
Popup::~Popup()
{
- evas_object_del(m_win);
+ if (m_win != nullptr)
+ evas_object_del(m_win);
+}
+
+void Popup::setButtons(const std::vector<Popup::Button> &buttons)
+{
+ for (auto &button : buttons) {
+ Evas_Object *obj = elm_button_add(m_btnBox);
+
+ elm_object_style_set(obj, "bottom");
+ setDefaultProperties(obj);
+
+ setText(obj, button.text);
+ m_buttonTypeMap[obj] = button.type;
+ evas_object_smart_callback_add(obj, "clicked", btnClickedCb, this);
+
+ elm_box_pack_end(m_btnBox, obj);
+ evas_object_show(obj);
+ }
}
void Popup::setHeader(const std::string &header) noexcept
@@ -163,11 +181,6 @@ void Popup::setIcon(const std::string &path) noexcept
elm_image_file_set(m_icon, path.c_str(), NULL);
}
-void Popup::run(void)
-{
- elm_run();
-}
-
int Popup::response = -1;
RawBuffer Popup::getResult(void)
@@ -209,19 +222,15 @@ void Popup::setText(Evas_Object *obj, const std::string &text) noexcept
elm_object_text_set(obj, text.c_str());
}
-void Popup::callbackRegister(Evas_Object *obj, int *type)
-{
- evas_object_smart_callback_add(obj, "clicked", btnClickedCb, type);
-}
-
-void Popup::callbackRegister(Evas_Object *obj, const std::string &url)
+void Popup::setDetailedUrl(const std::string &url)
{
if (url.empty())
- evas_object_smart_callback_add(
- obj, "anchor,clicked", hypertextClickedCb, &DEFAULT_URL);
+ m_hypertextUrl = DEFAULT_URL;
else
- evas_object_smart_callback_add(
- obj, "anchor,clicked", hypertextClickedCb, &url);
+ m_hypertextUrl = url;
+
+ evas_object_smart_callback_add(
+ m_hypertext, "anchor,clicked", hypertextClickedCb, this);
}
void Popup::rotationChangedCb(void *data, Evas_Object *, void *)
@@ -251,8 +260,12 @@ void Popup::rotationChangedCb(void *data, Evas_Object *, void *)
void Popup::hypertextClickedCb(void *data, Evas_Object *, void *)
{
DEBUG("Launch browser for detailed url.");
+ auto popup = reinterpret_cast<Popup *>(data);
+ if (popup == nullptr)
+ throw std::invalid_argument("Popup instance is null in static callback");
+
+ auto &url = popup->m_hypertextUrl;
- std::string url = *(reinterpret_cast<std::string *>(data));
std::unique_ptr<AppControl> ac(new AppControl);
auto ret = app_control_set_operation(ac->handle, APP_CONTROL_OPERATION_VIEW);
@@ -274,26 +287,49 @@ void Popup::hypertextClickedCb(void *data, Evas_Object *, void *)
}
}
-void Popup::btnClickedCb(void *data, Evas_Object *, void *)
+void Popup::btnClickedCb(void *data, Evas_Object *obj, void *)
{
- response = *(reinterpret_cast<int *>(data));
- elm_exit();
-}
+ auto popup = reinterpret_cast<Popup *>(data);
+ if (popup == nullptr)
+ throw std::invalid_argument("Popup instance is null in static btnClickedCb");
+ response = popup->m_buttonTypeMap.at(obj);
+ popup->terminateWindow();
+}
-Eina_Bool Popup::keyDownCb(void *, int , void *ev)
+Eina_Bool Popup::keyDownCb(void *data, int , void *ev)
{
DEBUG("Key down event caught.");
auto event = reinterpret_cast<Ecore_Event_Key *>(ev);
- if(event->key == HOME_KEY) {
+ if (event->key == HOME_KEY) {
+ auto popup = reinterpret_cast<Popup *>(data);
response = -1;
- elm_exit();
+ popup->terminateWindow();
}
// Let the event continue to other callbacks.
return ECORE_CALLBACK_PASS_ON;
}
+void Popup::terminateWindow()
+{
+ INFO("send result based on response and sender");
+ m_sender(getResult());
+
+ clear();
+}
+
+void Popup::clear()
+{
+ if (m_win != nullptr) {
+ // clear all resources
+ evas_object_del(m_win);
+ m_win = nullptr;
+ }
+
+ m_buttonTypeMap.clear();
+}
+
} // namespace Ui
} // namespace Csr
diff --git a/src/framework/ui/popup/popup.h b/src/framework/ui/popup/popup.h
index 4475d96..b60bfc7 100644
--- a/src/framework/ui/popup/popup.h
+++ b/src/framework/ui/popup/popup.h
@@ -32,60 +32,70 @@
#include "common/audit/logger.h"
#include "common/binary-queue.h"
+#include "common/types.h"
namespace Csr {
namespace Ui {
/*
- * --------------------
- * | title |
- * ========box=========
- * | content(header) |
- * |------subBox------|
- * |icon|content(body)|
- * |------------------|
- * | -hypertext |
- * | |
- * | content(footer) |
- * ====================
- * |------btnBox------|
- * | button(N) |
- * --------------------
+ * ------------------------
+ * | title |
+ * |==========box=========|
+ * || content(header) ||
+ * ||-------subBox-------||
+ * |||icon|content(body)|||
+ * ||--------------------||
+ * || -hypertext ||
+ * || content(footer) ||
+ * ||-------btnBox-------||
+ * ||| button(N) |||
+ * ||--------------------||
+ * |======================|
*/
class Popup {
public:
- Popup(int buttonN);
- virtual ~Popup();
+ struct Button {
+ Button(const char *text, int type) : text(text), type(type) {}
- void run(void);
- RawBuffer getResult(void);
- void setMessage(const std::string &msg) noexcept;
+ const char *text;
+ int type;
+ };
+
+ Popup();
+ virtual ~Popup();
Popup(const Popup &) = delete;
Popup &operator=(const Popup &) = delete;
Popup(Popup &&) = delete;
Popup &operator=(Popup &&) = delete;
+ void reset();
+
+ using Sender = std::function<void(const RawBuffer &)>;
+ void setSender(Sender &&sender);
+
+ void setMessage(const std::string &msg) noexcept;
void setTitle(const std::string &title) noexcept;
void setHeader(const std::string &header) noexcept;
void setBody(const std::string &body) noexcept;
void setFooter(const std::string &footer) noexcept;
void setIcon(const std::string &path) noexcept;
- void setText(Evas_Object *obj, const std::string &text) noexcept;
+ void setDetailedUrl(const std::string &url);
+ void setButtons(const std::vector<Button> &buttons);
- void callbackRegister(Evas_Object *obj, int *type);
- void callbackRegister(Evas_Object *obj, const std::string &url);
+private:
static void btnClickedCb(void *data, Evas_Object *, void *);
static void hypertextClickedCb(void *data, Evas_Object *, void *);
static void rotationChangedCb(void *data, Evas_Object *, void *);
static Eina_Bool keyDownCb(void *, int, void *);
- std::vector<Evas_Object *> m_buttons;
- Evas_Object *m_hypertext;
- std::vector<int> m_types;
+ std::map<Evas_Object *, int> m_buttonTypeMap;
+ void setText(Evas_Object *obj, const std::string &text) noexcept;
+ void terminateWindow();
+ void clear();
-private:
+ RawBuffer getResult(void);
void setDefaultProperties(Evas_Object *obj) noexcept;
void setRotationToWin(Evas_Object *obj) noexcept;
@@ -98,15 +108,18 @@ private:
Evas_Object *m_body;
Evas_Object *m_footer;
Evas_Object *m_icon;
+ Evas_Object *m_hypertext;
std::string m_message;
std::string m_iconPath;
std::string m_hypertextUrl;
- static int response;
-
int m_winW;
int m_winH;
+
+ Sender m_sender;
+
+ static int response;
};
} // namespace Ui
diff --git a/test/engine/content-screening/sample-engine.cpp b/test/engine/content-screening/sample-engine.cpp
index 34afff7..29634e8 100644
--- a/test/engine/content-screening/sample-engine.cpp
+++ b/test/engine/content-screening/sample-engine.cpp
@@ -477,14 +477,28 @@ int csre_cs_scan_app_on_cloud(csre_cs_context_h handle,
int ret = CSRE_ERROR_NONE;
- if (result->d_type & (DT_REG | DT_LNK))
+ if (result->d_type == DT_LNK) {
+ // when the file type is link, check the real file's type(dir or reg file)
+ // and go ahead to traverse
+ struct stat s;
+ if (stat(fullpath.c_str(), &s) != 0)
+ continue; // failed to get stat
+
+ if (S_ISREG(s.st_mode))
+ ret = csre_cs_scan_file(handle, fullpath.c_str(), &detected);
+ else if (S_ISDIR(s.st_mode))
+ ret = csre_cs_scan_app_on_cloud(handle, fullpath.c_str(), &detected);
+ else
+ continue;
+ } else if (result->d_type == DT_REG) {
ret = csre_cs_scan_file(handle, fullpath.c_str(), &detected);
- else if ((result->d_type & DT_DIR)
- && filename.compare("..") != 0
- && filename.compare(".") != 0)
+ } else if ((result->d_type & DT_DIR) &&
+ filename.compare("..") != 0 &&
+ filename.compare(".") != 0) {
ret = csre_cs_scan_app_on_cloud(handle, fullpath.c_str(), &detected);
- else
+ } else {
continue;
+ }
if (ret != CSRE_ERROR_NONE)
return ret;