$(extension_src_dir)/web-engine-chromium/tizen-web-engine-load-error.cpp \
$(extension_src_dir)/web-engine-chromium/tizen-web-engine-policy-decision.cpp \
$(extension_src_dir)/web-engine-chromium/tizen-web-engine-request-interceptor.cpp \
+ $(extension_src_dir)/web-engine-chromium/tizen-web-engine-request-interceptor-task-queue.cpp \
$(extension_src_dir)/web-engine-chromium/tizen-web-engine-security-origin.cpp \
$(extension_src_dir)/web-engine-chromium/tizen-web-engine-settings.cpp
#include "tizen-web-engine-http-auth-handler.h"
#include "tizen-web-engine-load-error.h"
#include "tizen-web-engine-policy-decision.h"
+#include "tizen-web-engine-request-interceptor.h"
#include "tizen-web-engine-settings.h"
#include <Ecore_Evas.h>
ewk_view_geolocation_permission_callback_set(mWebView, &WebViewContainerForDali::OnGeolocationPermission, &mClient);
}
+ void RegisterRequestInterceptorCallback(bool isRegistered)
+ {
+ Ewk_Context* context = ewk_view_context_get(mWebView);
+ if (isRegistered)
+ {
+ ewk_context_intercept_request_callback_set(context, &WebViewContainerForDali::OnRequestIntercepted, &mClient);
+ }
+ else
+ {
+ ewk_context_intercept_request_callback_set(context, nullptr, nullptr);
+ }
+ }
+
void UpdateDisplayArea(Dali::Rect<int32_t> displayArea)
{
evas_object_move(mWebView, displayArea.x, displayArea.y);
client->LoadError(std::move(loadError));
}
+ static void OnRequestIntercepted(Ewk_Context*, Ewk_Intercept_Request* request, void* data)
+ {
+ auto client = static_cast<WebViewContainerClient*>(data);
+ std::unique_ptr<Dali::WebEngineRequestInterceptor> webInterceptor(new TizenWebEngineRequestInterceptor(request));
+ client->RequestIntercepted(std::move(webInterceptor));
+ }
+
static void OnUrlChanged(void* data, Evas_Object*, void* newUrl)
{
auto client = static_cast<WebViewContainerClient*>(data);
: mWebViewContainer(0)
, mJavaScriptEvaluationCount(0)
{
+ EventThreadCallback* callback = new Dali::EventThreadCallback(Dali::MakeCallback(this, &TizenWebEngineChromium::OnRequestInterceptedEventCallback));
+ mRequestInterceptorEventTrigger = std::unique_ptr<Dali::EventThreadCallback>(callback);
}
TizenWebEngineChromium::~TizenWebEngineChromium()
void TizenWebEngineChromium::RegisterRequestInterceptorCallback(WebEngineRequestInterceptorCallback callback)
{
mRequestInterceptedCallback = callback;
+ if (mWebViewContainer)
+ {
+ bool isRegistered = mRequestInterceptedCallback ? true : false;
+ mWebViewContainer->RegisterRequestInterceptorCallback(isRegistered);
+ }
}
void TizenWebEngineChromium::RegisterConsoleMessageReceivedCallback(WebEngineConsoleMessageReceivedCallback callback)
ExecuteCallback(mScrollEdgeReachedCallback, edge);
}
+void TizenWebEngineChromium::RequestIntercepted(std::unique_ptr<Dali::WebEngineRequestInterceptor> interceptor)
+{
+ {
+ Mutex::ScopedLock lock(mMutex);
+ mRequestInterceptorQueue.push(std::move(interceptor));
+ // Trigger an event on main thread.
+ mRequestInterceptorEventTrigger->Trigger();
+ }
+
+ // Wait for tasks on main thread and execute tasks.
+ TizenWebEngineRequestInterceptor* requestInterceptor = static_cast<TizenWebEngineRequestInterceptor*>(interceptor.get());
+ requestInterceptor->WaitAndRunTasks();
+}
+
+void TizenWebEngineChromium::OnRequestInterceptedEventCallback()
+{
+ std::unique_ptr<Dali::WebEngineRequestInterceptor> interceptor;
+ {
+ Mutex::ScopedLock lock(mMutex);
+ interceptor = std::move(mRequestInterceptorQueue.front());
+ mRequestInterceptorQueue.pop();
+ }
+
+ ExecuteCallback(mRequestInterceptedCallback, std::move(interceptor));
+
+ // Notify ui-thread tasks ready on main thread.
+ TizenWebEngineRequestInterceptor* requestInterceptor = static_cast<TizenWebEngineRequestInterceptor*>(interceptor.get());
+ requestInterceptor->NotifyTaskReady();
+}
+
void TizenWebEngineChromium::UrlChanged(const std::string& url)
{
DALI_LOG_RELEASE_INFO("#UrlChanged : %s\n", url.c_str());
// EXTERNAL INCLUDES
#include <dali-toolkit/dali-toolkit.h>
+#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
#include <dali/devel-api/adaptor-framework/web-engine-plugin.h>
+#include <dali/devel-api/threading/mutex.h>
#include <dali/public-api/images/native-image-interface.h>
-#include <functional>
+#include <functional>
#include <memory>
-#include <tbm_surface.h>
+#include <queue>
#include <unordered_map>
+#include <tbm_surface.h>
+
namespace Dali
{
class PixelData;
*/
virtual void RequestFormRepostDecided(std::unique_ptr<Dali::WebEngineFormRepostDecision> decision) = 0;
+ /**
+ * @brief Callback function to be called by WebViewContainer when http request
+ * need be intercepted.
+ * @param [in] request The http request interceptor.
+ */
+ virtual void RequestIntercepted(std::unique_ptr<Dali::WebEngineRequestInterceptor> interceptor) = 0;
+
/**
* @brief Callback function to be called by WebViewContainer when url is
* changed.
*/
void ResponsePolicyDecided(std::unique_ptr<Dali::WebEnginePolicyDecision> policy) override;
+ /**
+ * @copydoc Dali::Plugin::WebViewContainerClient::RequestIntercepted()
+ */
+ void RequestIntercepted(std::unique_ptr<Dali::WebEngineRequestInterceptor> interceptor) override;
+
/**
* @copydoc Dali::Plugin::WebViewContainerClient::UrlChanged()
*/
*/
void PlainTextRecieved(const std::string& plainText) override;
+private:
+ /**
+ * @brief Event callback for request interceptor is called on main thread.
+ */
+ void OnRequestInterceptedEventCallback();
+
private:
WebViewContainerForDali* mWebViewContainer;
Dali::NativeImageSourcePtr mDaliImageSrc;
std::unordered_map<size_t, JavaScriptMessageHandlerCallback> mJavaScriptEvaluationResultHandlers;
std::unordered_map<std::string, JavaScriptMessageHandlerCallback> mJavaScriptMessageHandlers;
+
+ Dali::Mutex mMutex;
+ std::unique_ptr<Dali::EventThreadCallback> mRequestInterceptorEventTrigger;
+ std::queue<std::unique_ptr<Dali::WebEngineRequestInterceptor>> mRequestInterceptorQueue;
};
} // namespace Plugin
} // namespace Dali
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 "tizen-web-engine-request-interceptor-task-queue.h"
+
+namespace Dali
+{
+namespace Plugin
+{
+
+std::atomic<TaskQueue*> TaskQueue::mInstance { nullptr };
+std::mutex TaskQueue::mInstanceMutex;
+
+TaskQueue* TaskQueue::GetInstance()
+{
+ if(mInstance == nullptr)
+ {
+ std::lock_guard<std::mutex> lock(mInstanceMutex);
+ if(mInstance == nullptr)
+ {
+ mInstance = new TaskQueue();
+ }
+ }
+ return mInstance;
+}
+
+TaskQueue::TaskQueue()
+ : mIsThreadWaiting(true)
+{
+}
+
+void TaskQueue::AddTask(TaskCallback task)
+{
+ std::unique_lock<std::mutex> lock(mMutex);
+ mTaskQueue.push_back(task);
+}
+
+void TaskQueue::NotifyTaskReady()
+{
+ std::unique_lock<std::mutex> lock(mMutex);
+ mIsThreadWaiting = false;
+
+ // wake up the request interceptor thread
+ mCondition.notify_all();
+}
+
+void TaskQueue::WaitAndRunTasks()
+{
+ // wait for tasks.
+ std::unique_lock<std::mutex> lock(mMutex);
+ while(mIsThreadWaiting)
+ {
+ mCondition.wait(lock);
+ }
+ mIsThreadWaiting = true;
+
+ // execute tasks.
+ for(std::vector<TaskCallback>::iterator iter = mTaskQueue.begin(); iter != mTaskQueue.end(); iter++)
+ {
+ (*iter)();
+ }
+ mTaskQueue.clear();
+}
+
+} // namespace Plugin
+} // namespace Dali
--- /dev/null
+#ifndef DALI_PLUGIN_TIZEN_WEB_ENGINE_REQUEST_INTERCEPTOR_TASK_QUEUE_H
+#define DALI_PLUGIN_TIZEN_WEB_ENGINE_REQUEST_INTERCEPTOR_TASK_QUEUE_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <atomic>
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <vector>
+
+namespace Dali
+{
+namespace Plugin
+{
+
+/**
+ * @brief A class TaskQueue for running tasks. It is thread-safe.
+ */
+class TaskQueue
+{
+public:
+ static TaskQueue* GetInstance();
+
+ /**
+ * @brief Task callback.
+ */
+ using TaskCallback = std::function<bool(void)>;
+
+ /**
+ * @brief Add task.
+ */
+ void AddTask(TaskCallback taskQueue);
+
+ /**
+ * @brief Notify that tasks are ready.
+ */
+ void NotifyTaskReady();
+
+ /**
+ * @brief Wait for and run tasks.
+ */
+ void WaitAndRunTasks();
+
+private:
+ TaskQueue();
+
+ static std::atomic<TaskQueue*> mInstance;
+ static std::mutex mInstanceMutex;
+
+ bool mIsThreadWaiting;
+ std::vector<TaskCallback> mTaskQueue;
+ std::mutex mMutex;
+ std::condition_variable mCondition;\r
+};
+
+} // namespace Plugin
+} // namespace Dali
+
+#endif // DALI_PLUGIN_TIZEN_WEB_ENGINE_REQUEST_INTERCEPTOR_TASK_QUEUE_H
*/
#include "tizen-web-engine-request-interceptor.h"
+#include "tizen-web-engine-request-interceptor-task-queue.h"
namespace Dali
{
TizenWebEngineRequestInterceptor::TizenWebEngineRequestInterceptor(Ewk_Intercept_Request* interceptor)
: ewkRequestInterceptor(interceptor)
{
+ const char* url = ewk_intercept_request_url_get(ewkRequestInterceptor);
+ if (url)
+ {
+ requestUrl = std::string(url);
+ }
}
TizenWebEngineRequestInterceptor::~TizenWebEngineRequestInterceptor()
std::string TizenWebEngineRequestInterceptor::GetUrl() const
{
- const char* url = ewk_intercept_request_url_get(ewkRequestInterceptor);
- return url ? std::string(url) : std::string();
+ return requestUrl;
}
bool TizenWebEngineRequestInterceptor::Ignore()
{
- return ewk_intercept_request_ignore(ewkRequestInterceptor);
+ TaskQueue::GetInstance()->AddTask(std::bind(&TizenWebEngineRequestInterceptor::IgnoreUi, this));
+ return true;
}
bool TizenWebEngineRequestInterceptor::SetResponseStatus(int statusCode, const std::string& customStatusText)
{
- return ewk_intercept_request_response_status_set(ewkRequestInterceptor, statusCode, customStatusText.c_str());
+ TaskQueue::GetInstance()->AddTask(std::bind(&TizenWebEngineRequestInterceptor::SetResponseStatusUi, this, statusCode, customStatusText));
+ return true;
}
bool TizenWebEngineRequestInterceptor::AddResponseHeader(const std::string& fieldName, const std::string& fieldValue)
{
- return ewk_intercept_request_response_header_add(ewkRequestInterceptor, fieldName.c_str(), fieldValue.c_str());
+ TaskQueue::GetInstance()->AddTask(std::bind(&TizenWebEngineRequestInterceptor::AddResponseHeaderUi, this, fieldName, fieldValue));
+ return true;
}
bool TizenWebEngineRequestInterceptor::AddResponseBody(const std::string& body, uint32_t length)
+{
+ TaskQueue::GetInstance()->AddTask(std::bind(&TizenWebEngineRequestInterceptor::AddResponseBodyUi, this, body, length));
+ return true;
+}
+
+void TizenWebEngineRequestInterceptor::WaitAndRunTasks()
+{
+ TaskQueue::GetInstance()->WaitAndRunTasks();
+}
+
+void TizenWebEngineRequestInterceptor::NotifyTaskReady()
+{
+ TaskQueue::GetInstance()->NotifyTaskReady();
+}
+
+bool TizenWebEngineRequestInterceptor::IgnoreUi()
+{
+ return ewk_intercept_request_ignore(ewkRequestInterceptor);
+}
+
+bool TizenWebEngineRequestInterceptor::SetResponseStatusUi(int statusCode, const std::string& customStatusText)
+{
+ return ewk_intercept_request_response_status_set(ewkRequestInterceptor, statusCode, customStatusText.c_str());
+}
+
+bool TizenWebEngineRequestInterceptor::AddResponseHeaderUi(const std::string& fieldName, const std::string& fieldValue)
+{
+ return ewk_intercept_request_response_header_add(ewkRequestInterceptor, fieldName.c_str(), fieldValue.c_str());
+}
+
+bool TizenWebEngineRequestInterceptor::AddResponseBodyUi(const std::string& body, uint32_t length)
{
return ewk_intercept_request_response_body_set(ewkRequestInterceptor, body.c_str(), length);
}
// EXTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/web-engine-request-interceptor.h>
-#include <ewk_intercept_request.h>
+
+#include <functional>
#include <string>
+#include <vector>
+
+#include <ewk_intercept_request.h>
namespace Dali
{
*/
bool AddResponseBody(const std::string& body, uint32_t length) override;
+ /**
+ * @brief Wait for and run tasks on ui-thread.
+ */
+ void WaitAndRunTasks();
+
+ /**
+ * @brief Notify task ready on main thread.
+ */
+ void NotifyTaskReady();
+
+private:
+ /**
+ * @copydoc Dali::WebEngineRequestInterceptor::Ignore()
+ * @note It is run on ui thread
+ */
+ bool IgnoreUi();
+
+ /**
+ * @copydoc Dali::WebEngineRequestInterceptor::SetResponseStatus()
+ * @note It is run on ui thread
+ */
+ bool SetResponseStatusUi(int statusCode, const std::string& customStatusText);
+
+ /**
+ * @copydoc Dali::WebEngineRequestInterceptor::AddResponseHeader()
+ * @note It is run on ui thread
+ */
+ bool AddResponseHeaderUi(const std::string& fieldName, const std::string& fieldValue);
+
+ /**
+ * @copydoc Dali::WebEngineRequestInterceptor::AddResponseBody()
+ * @note It is run on ui thread
+ */
+ bool AddResponseBodyUi(const std::string& body, uint32_t length);
+
private:
Ewk_Intercept_Request* ewkRequestInterceptor;
+ std::string requestUrl;
};
} // namespace Plugin