From 9ba7d8591de26c447c98deef3f0e778c902e0e3c Mon Sep 17 00:00:00 2001 From: Aron Kim Date: Mon, 1 Apr 2019 01:41:10 +0000 Subject: [PATCH 01/16] [M94 Migration] Remove gstreamer and related packages for desktop. Gstreamer was used by multimedia on desktop. But multimedia support for desktop is removed long back. So there is no need to build the packages. Reference: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/176672/ Change-Id: I1e88fa9967d58d294594cf5aeb0b72d5af337d69 Signed-off-by: Aron Kim Signed-off-by: uzair (cherry picked from commit 4d06eb3bbf064c8318039674776eb3cb03c5a13e) --- tizen_src/build/jhbuild/jhbuild.modules | 84 --------------------------------- 1 file changed, 84 deletions(-) diff --git a/tizen_src/build/jhbuild/jhbuild.modules b/tizen_src/build/jhbuild/jhbuild.modules index e7526c4..a4f163e 100755 --- a/tizen_src/build/jhbuild/jhbuild.modules +++ b/tizen_src/build/jhbuild/jhbuild.modules @@ -9,12 +9,6 @@ - - - - - - @@ -26,8 +20,6 @@ href="http://ftp.gnome.org"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date: Wed, 17 Nov 2021 12:34:45 +0530 Subject: [PATCH 02/16] Fix for crash when new window is opened from ubrowser UI Currently, |create_new_window_web_contents_cb_| is static and therefore can be run multiple times during new window launch. However, it being of type OnceCallback results in crash when run more than once. This commit changes this callback to type RepeatingCallback to fix the crash issue. Change-Id: Ifa4e07a1df5a974de98bf81d18944c00ee7227e1 Signed-off-by: Chandan Padhi --- .../content/browser/web_contents/web_contents_impl_efl.cc | 7 ++++--- .../content/public/browser/web_contents_efl_delegate.h | 3 ++- tizen_src/ewk/efl_integration/eweb_view.cc | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc index 2399fff..2a4e06f 100644 --- a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc @@ -218,9 +218,10 @@ void WebContentsImplEfl::HandleNewWindowRequest( bool create) { if (create) { scoped_refptr ssn = session_storage_namespace; - WebContentsEflDelegate::WebContentsCreateCallback callback = base::BindOnce( - &WebContentsImplEfl::HandleNewWebContentsCreate, base::Unretained(this), - render_process_id, route_id, main_frame_route_id, params, ssn); + WebContentsEflDelegate::WebContentsCreateCallback callback = + base::BindRepeating(&WebContentsImplEfl::HandleNewWebContentsCreate, + base::Unretained(this), render_process_id, route_id, + main_frame_route_id, params, ssn); if (efl_delegate_ && efl_delegate_->WebContentsCreateAsync(callback)) return; diff --git a/tizen_src/chromium_impl/content/public/browser/web_contents_efl_delegate.h b/tizen_src/chromium_impl/content/public/browser/web_contents_efl_delegate.h index fb0a4cf..148b056 100644 --- a/tizen_src/chromium_impl/content/public/browser/web_contents_efl_delegate.h +++ b/tizen_src/chromium_impl/content/public/browser/web_contents_efl_delegate.h @@ -23,7 +23,8 @@ class CONTENT_EXPORT WebContentsEflDelegate { // intended to pass platform specific data to WebContents constructor. It // returns a pointer to new WebContents created by the function. The caller // is expected to take ownership of the returned object. - typedef base::OnceCallback WebContentsCreateCallback; + typedef base::RepeatingCallback + WebContentsCreateCallback; // Callback allowing the embedder to resume or block new window request. The // argument specifies if the request should be allowed (true) or blocked diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index e0c1037..d19ceba 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -141,7 +141,7 @@ class WebViewAsyncRequestHitTestDataUserCallback int EWebView::find_request_id_counter_ = 0; content::WebContentsEflDelegate::WebContentsCreateCallback EWebView::create_new_window_web_contents_cb_ = - base::BindOnce(&NullCreateWebContents); + base::BindRepeating(&NullCreateWebContents); EWebView* EWebView::FromEvasObject(Evas_Object* eo) { return WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(eo); @@ -306,10 +306,11 @@ void EWebView::SetFocus(Eina_Bool focus) { void EWebView::CreateNewWindow( content::WebContentsEflDelegate::WebContentsCreateCallback cb) { - create_new_window_web_contents_cb_ = std::move(cb); + create_new_window_web_contents_cb_ = cb; Evas_Object* new_object = NULL; SmartCallback().call(&new_object); - create_new_window_web_contents_cb_ = base::BindOnce(&NullCreateWebContents); + create_new_window_web_contents_cb_ = + base::BindRepeating(&NullCreateWebContents); DCHECK(new_object); } @@ -2182,8 +2183,7 @@ void EWebView::HandleRendererProcessCrash() { } void EWebView::InitializeContent() { - WebContents* new_contents = - std::move(create_new_window_web_contents_cb_).Run(this); + WebContents* new_contents = create_new_window_web_contents_cb_.Run(this); if (!new_contents) { WebContents::CreateParams params(context_->browser_context()); web_contents_.reset( -- 2.7.4 From 300fa1d1c981af712a9503469985d765f8bad846 Mon Sep 17 00:00:00 2001 From: Chandan Padhi Date: Mon, 22 Nov 2021 12:00:52 +0530 Subject: [PATCH 03/16] fixup! Create AggregatedRenderPassList from CompositorRenderPassList CSS filters were not getting applied due to missing AggregatedRenderPassDrawQuad in AggregatedRenderPass. Change-Id: I94327fe7a01c25e4f349b3e23a76ff9b359118ef Signed-off-by: Chandan Padhi --- .../browser/compositor/evasgl_delegated_frame_host.cc | 12 +++++++++--- .../content/browser/compositor/evasgl_delegated_frame_host.h | 1 - 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.cc b/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.cc index cd34f2d..3960b7f 100644 --- a/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.cc +++ b/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.cc @@ -61,7 +61,7 @@ void EvasGLDelegatedFrameHost::CreateAggregatedRenderPassList( auto copy_pass = std::make_unique(sqs_size, dq_size); copy_pass->SetAll( - render_pass_id_generator_.GenerateNextId(), source->output_rect, + viz::AggregatedRenderPassId(uint64_t{source->id}), source->output_rect, source->damage_rect, source->transform_to_root_target, source->filters, source->backdrop_filters, source->backdrop_filter_bounds, gfx::ContentColorUsage::kSRGB, source->has_transparent_background, @@ -87,8 +87,14 @@ void EvasGLDelegatedFrameHost::CreateAggregatedRenderPassList( *copy_shared_quad_state = **sqs_iter; } DCHECK(quad->shared_quad_state == *sqs_iter); - - copy_pass->CopyFromAndAppendDrawQuad(quad); + if (quad->material == viz::DrawQuad::Material::kCompositorRenderPass) { + const auto* pass_quad = + viz::CompositorRenderPassDrawQuad::MaterialCast(quad); + copy_pass->CopyFromAndAppendRenderPassDrawQuad( + pass_quad, + viz::AggregatedRenderPassId(uint64_t{pass_quad->render_pass_id})); + } else + copy_pass->CopyFromAndAppendDrawQuad(quad); } render_pass_list_.push_back(std::move(copy_pass)); } diff --git a/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.h b/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.h index 0cdd16d..a25430c 100644 --- a/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.h +++ b/tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.h @@ -67,7 +67,6 @@ class CONTENT_EXPORT EvasGLDelegatedFrameHost viz::DebugRendererSettings debug_settings_; std::unique_ptr resource_provider_; int child_id_; - viz::AggregatedRenderPassId::Generator render_pass_id_generator_; viz::AggregatedRenderPassList render_pass_list_; viz::ResourceIdSet resources_in_frame_; std::vector returned_resources_; -- 2.7.4 From ea1f1ac6505b6ee6ef84cf61434791449f2b7c2e Mon Sep 17 00:00:00 2001 From: "fr.fang" Date: Wed, 2 Dec 2020 13:58:43 +0800 Subject: [PATCH 04/16] [M94 Migration] Add event handler for EVAS_CALLBACK_MOUSE_OUT Currently, webview can not detect whether the mouse is moved out of webview. The problem is when moving mouse to the edge of webview, the node under the cursor will stay in hover state event when the mouse moved out. The hover state will not be invalidated until the mouse move into webview. Reference: https://review.tizen.org/gerrit/248765 Change-Id: Iea67174faf8c3f5dcc0706bd05fad2ec2025e741 Signed-off-by: fr.fang Signed-off-by: Gajendra N --- .../renderer_host/render_widget_host_view_efl.cc | 14 ++++++++ .../renderer_host/render_widget_host_view_efl.h | 1 + .../browser/renderer_host/web_event_factory_efl.cc | 42 ++++++++++++++++++++++ .../browser/renderer_host/web_event_factory_efl.h | 2 ++ 4 files changed, 59 insertions(+) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc index b5e9076..3ff61a0 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc @@ -212,6 +212,8 @@ void RenderWidgetHostViewEfl::InitAsChild(gfx::NativeView /* parent_view */) { OnMouseUp, this); evas_object_event_callback_add(content_image_, EVAS_CALLBACK_MOUSE_MOVE, OnMouseMove, this); + evas_object_event_callback_add(content_image_, EVAS_CALLBACK_MOUSE_OUT, + OnMouseOut, this); evas_object_event_callback_add(content_image_, EVAS_CALLBACK_MOUSE_WHEEL, OnMouseWheel, this); evas_object_event_callback_add(content_image_, EVAS_CALLBACK_KEY_DOWN, @@ -277,6 +279,8 @@ RenderWidgetHostViewEfl::~RenderWidgetHostViewEfl() { OnMouseUp); evas_object_event_callback_del(content_image_, EVAS_CALLBACK_MOUSE_MOVE, OnMouseMove); + evas_object_event_callback_del(content_image_, EVAS_CALLBACK_MOUSE_OUT, + OnMouseOut); evas_object_event_callback_del(content_image_, EVAS_CALLBACK_MOUSE_WHEEL, OnMouseWheel); evas_object_event_callback_del(content_image_, EVAS_CALLBACK_KEY_DOWN, @@ -1137,6 +1141,16 @@ void RenderWidgetHostViewEfl::OnMouseMove(void* data, } } +void RenderWidgetHostViewEfl::OnMouseOut(void* data, + Evas* evas, + Evas_Object* obj, + void* event_info) { + RenderWidgetHostViewEfl* rwhv = static_cast(data); + blink::WebMouseEvent event = + MakeWebMouseEvent(obj, static_cast(event_info)); + rwhv->host_->ForwardMouseEvent(event); +} + void RenderWidgetHostViewEfl::OnMultiTouchDownEvent(void* data, Evas* evas, Evas_Object* obj, diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h index ecefb02..71d8fd1 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h @@ -278,6 +278,7 @@ class CONTENT_EXPORT RenderWidgetHostViewEfl static void OnMouseDown(void* data, Evas*, Evas_Object*, void*); static void OnMouseUp(void* data, Evas*, Evas_Object*, void*); static void OnMouseMove(void* data, Evas*, Evas_Object*, void*); + static void OnMouseOut(void* data, Evas*, Evas_Object*, void*); static void OnMouseWheel(void* data, Evas*, Evas_Object*, void*); static void OnKeyDown(void*, Evas*, Evas_Object*, void*); static void OnKeyUp(void*, Evas*, Evas_Object*, void*); diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.cc index 83ba6b9..859d27d 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.cc @@ -361,6 +361,21 @@ static WebMouseEvent::Button EvasToWebMouseButton(int button) { return WebMouseEvent::Button::kNoButton; } +enum { LeftButtonPressed = 1, MiddleButtonPressed = 2, RightButtonPressed = 4 }; + +static WebInputEvent::Modifiers EvasToWebMouseButtonsPressed(int buttons) { + unsigned result = 0; + + if (buttons & LeftButtonPressed) + result |= WebInputEvent::kLeftButtonDown; + if (buttons & MiddleButtonPressed) + result |= WebInputEvent::kMiddleButtonDown; + if (buttons & RightButtonPressed) + result |= WebInputEvent::kRightButtonDown; + + return static_cast(result); +} + static WebInputEvent::Modifiers EvasToWebModifiers( const Evas_Modifier* modifiers) { unsigned result = 0; @@ -407,11 +422,38 @@ template blink::WebMouseEvent MakeWebMouseEvent( const Evas_Event_Mouse_Up*); blink::WebMouseEvent MakeWebMouseEvent(Evas_Object* view, + const Evas_Event_Mouse_Out* ev) { + WebMouseEvent event(WebInputEvent::Type::kMouseLeave, + EvasToWebModifiers(ev->modifiers), + ui::EventTimeStampFromSeconds(ev->timestamp / 1000)); + + event.button = EvasToWebMouseButton(ev->buttons); + event.SetModifiers(event.GetModifiers() | + EvasToWebMouseButtonsPressed(ev->buttons)); + + const float sf = GetDeviceScaleFactor(); + gfx::PointF point(ev->canvas.x / sf, ev->canvas.y / sf); + TranslateEvasCoordToWebKitCoord(view, &point); + + Evas* evas = evas_object_evas_get(view); + event.SetPositionInScreen( + evas_coord_world_x_to_screen(evas, ev->canvas.x) / sf, + evas_coord_world_y_to_screen(evas, ev->canvas.y) / sf); + event.SetPositionInWidget(point); + + return event; +} + +blink::WebMouseEvent MakeWebMouseEvent(Evas_Object* view, const Evas_Event_Mouse_Move* ev) { WebMouseEvent event(WebInputEvent::Type::kMouseMove, EvasToWebModifiers(ev->modifiers), ui::EventTimeStampFromSeconds(ev->timestamp / 1000)); + event.button = EvasToWebMouseButton(ev->buttons); + event.SetModifiers(event.GetModifiers() | + EvasToWebMouseButtonsPressed(ev->buttons)); + const float sf = GetDeviceScaleFactor(); gfx::PointF point(ev->cur.canvas.x / sf, ev->cur.canvas.y / sf); TranslateEvasCoordToWebKitCoord(view, &point); diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.h index 0de1187..1d43037 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/web_event_factory_efl.h @@ -20,6 +20,8 @@ template blink::WebMouseEvent MakeWebMouseEvent( blink::WebInputEvent::Type type, Evas_Object* view, const EVT*); blink::WebMouseEvent MakeWebMouseEvent(Evas_Object* view, + const Evas_Event_Mouse_Out* ev); +blink::WebMouseEvent MakeWebMouseEvent(Evas_Object* view, const Evas_Event_Mouse_Move* ev); blink::WebMouseWheelEvent MakeWebMouseEvent(Evas_Object*, const Evas_Event_Mouse_Wheel* ev); -- 2.7.4 From 8abb81f1e2e06f7095220b0bd873b2a3d6ab759a Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Fri, 6 Nov 2020 16:26:42 +0530 Subject: [PATCH 05/16] [M94 Migration] Fix AssertNoURLRequests crash issue This patch fixes the crash by AssertNoURLRequests(). Reference: https://review.tizen.org/gerrit/247190 Change-Id: Ibe1ab1c7b2360dd795211fe991cd6be2dd9f1409 Signed-off-by: Gajendra N --- tizen_src/ewk/efl_integration/browser_context_efl.cc | 15 ++++++++++----- .../ewk/efl_integration/url_request_context_getter_efl.cc | 15 ++++++++++++++- .../ewk/efl_integration/url_request_context_getter_efl.h | 3 +++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/tizen_src/ewk/efl_integration/browser_context_efl.cc b/tizen_src/ewk/efl_integration/browser_context_efl.cc index cb767e5..ed97268 100644 --- a/tizen_src/ewk/efl_integration/browser_context_efl.cc +++ b/tizen_src/ewk/efl_integration/browser_context_efl.cc @@ -59,14 +59,19 @@ BrowserContextEfl::~BrowserContextEfl() { autofill::PersonalDataManagerFactory::GetInstance() ->PersonalDataManagerRemove(this); #endif - - if (resource_context_) { - resource_context_->set_url_request_context_getter(NULL); + ShutdownStoragePartitions(); + if (resource_context_) BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, resource_context_); - } } -BrowserContextEfl::ResourceContextEfl::~ResourceContextEfl() {} +BrowserContextEfl::ResourceContextEfl::~ResourceContextEfl() { + // |cookie_manager_| has access to + // |URLRequestContextGetterEfl::GetURLRequestContext()|. So it should be + // released before NotifyContextShuttingDown() + cookie_manager_ = nullptr; + if (getter_.get()) + getter_->NotifyContextShuttingDown(); +} bool BrowserContextEfl::ResourceContextEfl::HTTPCustomHeaderAdd( const std::string& name, diff --git a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc index e769f59..437244b 100644 --- a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc +++ b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc @@ -62,11 +62,24 @@ URLRequestContextGetterEfl::URLRequestContextGetterEfl( io_task_runner); } -URLRequestContextGetterEfl::~URLRequestContextGetterEfl() {} +URLRequestContextGetterEfl::~URLRequestContextGetterEfl() { + // NotifyContextShuttingDown() must have been called. + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(shut_down_); +} + +void URLRequestContextGetterEfl::NotifyContextShuttingDown() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + shut_down_ = true; + URLRequestContextGetter::NotifyContextShuttingDown(); +} net::URLRequestContext* URLRequestContextGetterEfl::GetURLRequestContext() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (shut_down_) + return nullptr; + if (!url_request_context_) { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); diff --git a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h index 86c2a27..97464f4 100644 --- a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h +++ b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h @@ -53,6 +53,8 @@ class URLRequestContextGetterEfl : public net::URLRequestContextGetter { return weak_ptr_factory_.GetWeakPtr(); } + void NotifyContextShuttingDown(); + protected: virtual ~URLRequestContextGetterEfl(); @@ -66,6 +68,7 @@ class URLRequestContextGetterEfl : public net::URLRequestContextGetter { bool ignore_certificate_errors_; base::FilePath base_path_; + bool shut_down_ = false; const scoped_refptr& io_task_runner_; const scoped_refptr& file_task_runner_; net::NetLog* net_log_; -- 2.7.4 From 83c8f9a2db63d6b8da8410a5d34d4dd0e17ced01 Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Fri, 28 May 2021 13:03:28 +0530 Subject: [PATCH 06/16] [M94 Migration] Load ErrorPage for HTTP Error 404 When an URL fails to load with HTTP Error 404, no error page was displayed; only blank page was seen. This patch overrides necessary functions to display the required error page. Reference: https://review.tizen.org/gerrit/258954 Change-Id: I24f42ebd37e33e48a3998afdc891d329d34db831 Signed-off-by: Gajendra N (cherry picked from commit 5877ed199a4a3e3185b935f5ced45581c2313781) --- tizen_src/ewk/efl_integration/content_browser_client_efl.cc | 8 ++++++++ tizen_src/ewk/efl_integration/content_browser_client_efl.h | 1 + .../ewk/efl_integration/renderer/content_renderer_client_efl.cc | 9 +++++++++ .../ewk/efl_integration/renderer/content_renderer_client_efl.h | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc index a9f8e6d..418cbd1 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -18,6 +18,8 @@ #include "browser/render_message_filter_efl.h" #include "browser/web_view_browser_message_filter.h" #include "common/content_switches_efl.h" +#include "components/error_page/common/error.h" +#include "components/error_page/common/localized_error.h" #include "content/browser/web_contents/web_contents_view_efl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_widget_host.h" @@ -220,6 +222,12 @@ void ContentBrowserClientEfl::DispatchPopupBlockedOnUIThread( target_url.spec().c_str()); } +bool ContentBrowserClientEfl::HasErrorPage(int http_status_code) { + // Use an internal error page, if we have one for the status code. + return error_page::LocalizedError::HasStrings( + error_page::Error::kHttpErrorDomain, http_status_code); +} + void ContentBrowserClientEfl::AllowCertificateError( WebContents* web_contents, int cert_error, diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.h b/tizen_src/ewk/efl_integration/content_browser_client_efl.h index 7832490..cc11fb1 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.h +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.h @@ -60,6 +60,7 @@ class ContentBrowserClientEfl : public ContentBrowserClient { scoped_refptr CreateQuotaPermissionContext() override; + bool HasErrorPage(int http_status_code) override; void AllowCertificateError( WebContents* web_contents, int cert_error, diff --git a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc index 9b5d558..e4067f7 100644 --- a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc +++ b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc @@ -265,6 +265,15 @@ void ContentRendererClientEfl::PrepareErrorPage( content::CommonRendererClient::PrepareErrorPage(error, error_html); } +void ContentRendererClientEfl::PrepareErrorPageForHttpStatusError( + content::RenderFrame* render_frame, + const blink::WebURLError& error, + const std::string& http_method, + int http_status, + std::string* error_html) { + content::CommonRendererClient::PrepareErrorPage(error, error_html); +} + void ContentRendererClientEfl::ApplyCustomMobileSettings(blink::WebView* webview) { // blink::WebViewImpl prevents auto zoom after tap if maximum legible scale is // too small. Blink by default sets it to 1 and needs to be enlarged to make diff --git a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h index fe18655..660f495 100644 --- a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h +++ b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h @@ -76,6 +76,12 @@ class ContentRendererClientEfl : public content::ContentRendererClient { const blink::WebURLError& error, const std::string& http_method, std::string* error_html) override; + void PrepareErrorPageForHttpStatusError( + content::RenderFrame* render_frame, + const blink::WebURLError& error, + const std::string& http_method, + int http_status, + std::string* error_html) override; uint64_t VisitedLinkHash(const char* canonical_url, size_t length) override; -- 2.7.4 From e84c83b5eb26ec49d901d958ea1be8535c81ff3d Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Wed, 1 Dec 2021 13:50:02 +0530 Subject: [PATCH 07/16] [M94 Migration] Add internalization of login_popup(Authentication) In current implementation, we just call signal of authentication. But we need to offer default popup about authentication. If application developer wants to customize authentication, use "ewk_view_authentication_callback_set". Reference: https://review.tizen.org/gerrit/245896 Change-Id: Ie637aaf65a49c24a126167fed4fc98a74fff7acd Signed-off-by: Surya Kumar --- tizen_src/ewk/efl_integration/BUILD.gn | 2 + .../authentication_challenge_popup.cc | 252 +++++++++++++++++++++ .../authentication_challenge_popup.h | 46 ++++ tizen_src/ewk/efl_integration/eweb_view.cc | 7 +- tizen_src/ewk/efl_integration/eweb_view.h | 5 + .../ewk/efl_integration/eweb_view_callbacks.h | 2 - tizen_src/ewk/efl_integration/public/ewk_view.cc | 23 ++ .../resource/AuthenticationPopup.edc | 115 ++++++++++ tizen_src/ewk/efl_integration/resource/BUILD.gn | 1 + tizen_src/ewk/efl_webview_app/app.c | 11 +- ...k_ewk_auth_challenge_credential_cancel_func.cpp | 13 +- ...link_ewk_auth_challenge_credential_use_func.cpp | 10 +- ...utc_blink_ewk_auth_challenge_realm_get_func.cpp | 17 +- .../utc_blink_ewk_auth_challenge_suspend_func.cpp | 12 +- 14 files changed, 481 insertions(+), 35 deletions(-) create mode 100644 tizen_src/ewk/efl_integration/authentication_challenge_popup.cc create mode 100644 tizen_src/ewk/efl_integration/authentication_challenge_popup.h create mode 100644 tizen_src/ewk/efl_integration/resource/AuthenticationPopup.edc diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index 125203a..e956ddf 100644 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -180,6 +180,8 @@ shared_library("chromium-ewk") { } sources += [ + "authentication_challenge_popup.cc", + "authentication_challenge_popup.h", "autofill_popup_view_efl.cc", "autofill_popup_view_efl.h", "browser/background_sync_controller_efl.cc", diff --git a/tizen_src/ewk/efl_integration/authentication_challenge_popup.cc b/tizen_src/ewk/efl_integration/authentication_challenge_popup.cc new file mode 100644 index 0000000..d0a3803 --- /dev/null +++ b/tizen_src/ewk/efl_integration/authentication_challenge_popup.cc @@ -0,0 +1,252 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ewk/efl_integration/authentication_challenge_popup.h" + +#if defined(OS_TIZEN) +#include +#endif + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" +#include "content/common/paths_efl.h" +#include "ewk/efl_integration/eweb_view.h" +#include "public/ewk_view.h" + +// Color of text_box border +static const int kBorderColorRed = 10; +static const int kBorderColorGreen = 10; +static const int kBorderColorBlue = 10; + +// Length of text_box border +static const int kBorderWidth = 200; +static const int kBorderHeight = 30; +static const int kBorderThickness = 3; + +AuthenticationChallengePopup::AuthenticationChallengePopup( + Ewk_Auth_Challenge* auth_challenge, + Evas_Object* ewk_view) + : conformant_(nullptr), + ewk_view_(ewk_view), + login_button_(nullptr), + layout_(nullptr), + password_entry_(nullptr), + popup_(nullptr), + user_name_entry_(nullptr), + auth_challenge_(auth_challenge) {} + +AuthenticationChallengePopup::~AuthenticationChallengePopup() { + if (login_button_) + evas_object_smart_callback_del(login_button_, "clicked", + AuthenticationLoginCallback); +#if defined(OS_TIZEN) + if (popup_) { + eext_object_event_callback_del(popup_, EEXT_CALLBACK_BACK, + HwBackKeyCallback); + } +#endif + if (conformant_) { + evas_object_del(conformant_); + conformant_ = nullptr; + } +} + +void AuthenticationChallengePopup::AuthenticationLoginCallback( + void* data, + Evas_Object* obj, + void* event_info) { + auto auth_challenge_popup = static_cast(data); + if (!auth_challenge_popup) { + LOG(ERROR) << "Showing authentication popup failed"; + return; + } + + const char* username = + elm_entry_entry_get(auth_challenge_popup->user_name_entry_); + const char* password = + elm_entry_entry_get(auth_challenge_popup->password_entry_); + ewk_auth_challenge_credential_use(auth_challenge_popup->auth_challenge_, + username, password); + delete auth_challenge_popup; +} + +#if defined(OS_TIZEN) +void AuthenticationChallengePopup::HwBackKeyCallback(void* data, + Evas_Object* obj, + void* event_info) { + auto* auth_challenge_popup = static_cast(data); + if (!auth_challenge_popup) { + LOG(ERROR) << "Showing authentication popup failed"; + return; + } + ewk_auth_challenge_credential_cancel(auth_challenge_popup->auth_challenge_); + delete auth_challenge_popup; +} +#endif + +Evas_Object* AuthenticationChallengePopup::CreateBorder( + const std::string& text, + Evas_Object* entry_box) { + Evas_Object* border = elm_bg_add(popup_); + if (!border) + return nullptr; + + elm_bg_color_set(border, kBorderColorRed, kBorderColorGreen, + kBorderColorBlue); + if (!text.compare("border_up") || !text.compare("border_down")) + evas_object_size_hint_min_set(border, kBorderWidth, kBorderThickness); + else + evas_object_size_hint_min_set(border, kBorderThickness, kBorderHeight); + + evas_object_show(border); + elm_object_part_content_set(entry_box, text.c_str(), border); + + return border; +} + +Evas_Object* AuthenticationChallengePopup::CreateTextBox( + const char* edj_path, + Evas_Object* container_box) { + Evas_Object* entry_box = elm_layout_add(popup_); + if (!entry_box) + return nullptr; + elm_layout_file_set(entry_box, edj_path, "authentication_challenge"); + + Evas_Object* text_box = elm_entry_add(entry_box); + if (!text_box) + return nullptr; + elm_entry_single_line_set(text_box, EINA_TRUE); + elm_object_focus_set(text_box, EINA_TRUE); + elm_entry_scrollable_set(text_box, true); + evas_object_show(text_box); + + elm_object_part_content_set(entry_box, "elm.swallow.entry", text_box); + + CreateBorder("border_up", entry_box); + CreateBorder("border_down", entry_box); + CreateBorder("border_left", entry_box); + CreateBorder("border_right", entry_box); + + elm_box_pack_end(container_box, entry_box); + evas_object_show(entry_box); + + return text_box; +} + +bool AuthenticationChallengePopup::CreateTextLabel(const char* text, + Evas_Object* container_box) { + Evas_Object* text_label = elm_label_add(popup_); + if (!text_label) + return false; + elm_object_text_set(text_label, text); + elm_box_pack_end(container_box, text_label); + evas_object_show(text_label); + return true; +} + +Evas_Object* AuthenticationChallengePopup::CreateContainerBox() { + Evas_Object* box = elm_box_add(popup_); + if (!box) + return nullptr; + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(box); + + if (!CreateTextLabel(dgettext("WebKit", "IDS_WEBVIEW_BODY_USERNAME"), box)) + return nullptr; + base::FilePath edj_dir, authentication_edj; + base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); + authentication_edj = + edj_dir.Append(FILE_PATH_LITERAL("AuthenticationPopup.edj")); + + user_name_entry_ = + CreateTextBox(authentication_edj.AsUTF8Unsafe().c_str(), box); + if (!user_name_entry_) + return nullptr; + + if (!CreateTextLabel(dgettext("WebKit", "IDS_WEBVIEW_BODY_PASSWORD"), box)) + return nullptr; + + password_entry_ = + CreateTextBox(authentication_edj.AsUTF8Unsafe().c_str(), box); + if (!password_entry_) + return nullptr; + elm_entry_password_set(password_entry_, EINA_TRUE); + elm_entry_input_panel_layout_set(password_entry_, + ELM_INPUT_PANEL_LAYOUT_PASSWORD); + + return box; +} + +bool AuthenticationChallengePopup::ShowAuthenticationPopup(const char* url) { + Evas_Object* parent = + elm_object_top_widget_get(elm_object_parent_widget_get(ewk_view_)); + if (!parent) + parent = ewk_view_; + + conformant_ = elm_conformant_add(parent); + if (!conformant_) + return false; + + evas_object_size_hint_weight_set(conformant_, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(parent, conformant_); + + layout_ = elm_layout_add(conformant_); + if (!layout_) + return false; + elm_layout_theme_set(layout_, "layout", "application", "default"); + evas_object_size_hint_weight_set(layout_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_content_set(conformant_, layout_); + evas_object_show(layout_); + + popup_ = elm_popup_add(layout_); + if (!popup_) + return false; + elm_object_part_text_set(popup_, "title,text", url); + + Evas_Object* box = CreateContainerBox(); + if (!box) + return false; + elm_object_content_set(popup_, box); + login_button_ = elm_button_add(popup_); + if (!login_button_) + return false; + elm_object_style_set(login_button_, "popup"); + evas_object_size_hint_weight_set(login_button_, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(login_button_, EVAS_HINT_FILL, + EVAS_HINT_FILL); + elm_object_text_set(login_button_, dgettext("WebKit", "IDS_BR_BODY_LOG_IN")); + elm_box_pack_end(box, login_button_); + elm_object_part_content_set(popup_, "button1", login_button_); + evas_object_show(login_button_); + + evas_object_smart_callback_add(login_button_, "clicked", + AuthenticationLoginCallback, this); +#if defined(OS_TIZEN) + eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, HwBackKeyCallback, + this); +#endif + evas_object_show(popup_); + + return true; +} + +void AuthenticationChallengePopup::CreateAndShow( + Ewk_Auth_Challenge* auth_challenge, + Evas_Object* ewk_view) { + if (!auth_challenge) + return; + auto popup = new AuthenticationChallengePopup(auth_challenge, ewk_view); + + const char* url = ewk_auth_challenge_url_get(auth_challenge); + + ewk_auth_challenge_suspend(auth_challenge); + if (!popup->ShowAuthenticationPopup(url)) { + LOG(ERROR) << "Showing authentication popup is failed"; + ewk_auth_challenge_credential_cancel(auth_challenge); + delete popup; + } +} diff --git a/tizen_src/ewk/efl_integration/authentication_challenge_popup.h b/tizen_src/ewk/efl_integration/authentication_challenge_popup.h new file mode 100644 index 0000000..5d2766f --- /dev/null +++ b/tizen_src/ewk/efl_integration/authentication_challenge_popup.h @@ -0,0 +1,46 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_AUTHENTICATION_CHALLENGE_POPUP_H_ +#define EWK_EFL_INTEGRATION_AUTHENTICATION_CHALLENGE_POPUP_H_ + +#include +#include + +#include "public/ewk_auth_challenge_internal.h" + +class AuthenticationChallengePopup { + public: + ~AuthenticationChallengePopup(); + + static void CreateAndShow(Ewk_Auth_Challenge* auth_challenge, + Evas_Object* ewk_view); + + private: + explicit AuthenticationChallengePopup(Ewk_Auth_Challenge* auth_challenge, + Evas_Object* ewk_view); + + bool ShowAuthenticationPopup(const char* url); + static void AuthenticationLoginCallback(void* data, + Evas_Object* obj, + void* event_info); +#if defined(OS_TIZEN) + static void HwBackKeyCallback(void* data, Evas_Object* obj, void* event_info); +#endif + Evas_Object* CreateBorder(const std::string& text, Evas_Object* entry_box); + Evas_Object* CreateContainerBox(); + Evas_Object* CreateTextBox(const char* edj_path, Evas_Object* container_box); + bool CreateTextLabel(const char* edj_path, Evas_Object* container_box); + + Evas_Object* conformant_; + Evas_Object* ewk_view_; + Evas_Object* login_button_; + Evas_Object* layout_; + Evas_Object* password_entry_; + Evas_Object* popup_; + Evas_Object* user_name_entry_; + Ewk_Auth_Challenge* auth_challenge_; +}; + +#endif // EWK_EFL_INTEGRATION_AUTHENTICATION_CHALLENGE_POPUP_H_ \ No newline at end of file diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index d19ceba..52b66e3 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -533,13 +533,18 @@ void EWebView::Hide() { web_contents_->WasHidden(); } +void EWebView::SetViewAuthCallback(Ewk_View_Authentication_Callback callback, + void* user_data) { + authentication_cb_.Set(callback, user_data); +} + void EWebView::InvokeAuthCallback(LoginDelegateEfl* login_delegate, const GURL& url, const std::string& realm) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); auth_challenge_.reset(new _Ewk_Auth_Challenge(login_delegate, url, realm)); - SmartCallback().call(auth_challenge_.get()); + authentication_cb_.Run(evas_object_, auth_challenge_.get()); if (!auth_challenge_->is_decided && !auth_challenge_->is_suspended) { auth_challenge_->is_decided = true; diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 124652a..b4abe90 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -253,6 +253,9 @@ class EWebView { int error_code, const std::string& error_description, bool is_main_frame); + + void SetViewAuthCallback(Ewk_View_Authentication_Callback callback, + void* user_data); void InvokeAuthCallback(LoginDelegateEfl* login_delegate, const GURL& url, const std::string& realm); @@ -580,6 +583,8 @@ class EWebView { WebViewCallback quota_request_callback_; + WebViewCallback + authentication_cb_; std::unique_ptr inputPicker_; base::IDMap diff --git a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h index e23a4bd..95aac0b 100644 --- a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h +++ b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h @@ -99,7 +99,6 @@ enum CallbackType { GeoLocationPermissionRequest, GeoLocationValid, RequestCertificateConfirm, - AuthChallenge, SetCertificatePem, PolicyResponseDecide, ContextMenuCustomize, @@ -237,7 +236,6 @@ DECLARE_EWK_VIEW_CALLBACK(LoadCommitted, "load,committed", void); DECLARE_EWK_VIEW_CALLBACK(GeoLocationPermissionRequest, "geolocation,permission,request", _Ewk_Geolocation_Permission_Request*); DECLARE_EWK_VIEW_CALLBACK(GeoLocationValid, "geolocation,valid", Eina_Bool*); DECLARE_EWK_VIEW_CALLBACK(RequestCertificateConfirm, "request,certificate,confirm", _Ewk_Certificate_Policy_Decision*); -DECLARE_EWK_VIEW_CALLBACK(AuthChallenge, "authentication,challenge", _Ewk_Auth_Challenge*); DECLARE_EWK_VIEW_CALLBACK(SetCertificatePem, "certificate,pem,set", const char*); DECLARE_EWK_VIEW_CALLBACK(PolicyResponseDecide, "policy,response,decide", _Ewk_Policy_Decision*); DECLARE_EWK_VIEW_CALLBACK(ContextMenuCustomize, "contextmenu,customize", _Ewk_Context_Menu*); diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 67696bb..a95082e5 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -22,6 +22,7 @@ #include +#include "authentication_challenge_popup.h" #include "content/public/browser/navigation_controller.h" #include "cookie_manager.h" #include "eweb_view.h" @@ -56,6 +57,9 @@ static Eina_Bool _ewk_view_default_geolocation_permission( static Eina_Bool _ewk_view_default_notification_permission( Evas_Object*, Ewk_Notification_Permission_Request*, void*); +static void _ewk_view_default_authentication( + Evas_Object*, Ewk_Auth_Challenge*, void*); + Eina_Bool ewk_view_smart_class_set(Ewk_View_Smart_Class* api) { EINA_SAFETY_ON_NULL_RETURN_VAL(api, false); @@ -95,6 +99,8 @@ Evas_Object* ewk_view_add_with_context(Evas* e, Ewk_Context* context) _ewk_view_default_geolocation_permission, 0); ewk_view_notification_permission_callback_set(ewk_view, _ewk_view_default_notification_permission, 0); + ewk_view_authentication_callback_set(ewk_view, + _ewk_view_default_authentication, nullptr); } return ewk_view; @@ -1333,6 +1339,23 @@ void ewk_view_request_manifest_from_url(Evas_Object* o, Ewk_View_Request_Manifes LOG_EWK_API_MOCKUP(); } +void ewk_view_authentication_callback_set( + Evas_Object* ewk_view, + Ewk_View_Authentication_Callback callback, + void* user_data) +{ + EWK_VIEW_IMPL_GET_OR_RETURN(ewk_view, impl); + impl->SetViewAuthCallback(callback, user_data); + +} + +static void _ewk_view_default_authentication(Evas_Object* ewk_view, + Ewk_Auth_Challenge* auth_challenge, + void* user_data) +{ + AuthenticationChallengePopup::CreateAndShow(auth_challenge, ewk_view); +} + void ewk_view_app_installation_request_callback_set(Evas_Object* o, Ewk_App_Installation_Request_Callback callback, void* user_data) { LOG_EWK_API_MOCKUP(); diff --git a/tizen_src/ewk/efl_integration/resource/AuthenticationPopup.edc b/tizen_src/ewk/efl_integration/resource/AuthenticationPopup.edc new file mode 100644 index 0000000..8df1cca --- /dev/null +++ b/tizen_src/ewk/efl_integration/resource/AuthenticationPopup.edc @@ -0,0 +1,115 @@ +collections { + group { + name: "authentication_challenge"; + parts { + part { + name: "background"; + type: RECT; + scale : 1; + description { + state: "default" 0.0; + min: 200 30; + max: 200 30; + visible: 1; + } + } + part { + name: "elm.swallow.entry"; + type: SWALLOW; + scale : 1; + description { + state: "default" 0.0; + align: 0.0 0.0; + min: 200 30; + max: 200 30; + color: 0 217 217 255; + visible: 1; + rel1{ + relative: 0 0; + to: "background"; + } + rel2{ + relative: 1 1; + to: "background"; + } + } + } + part { + name: "border_up"; + type: SWALLOW; + scale : 1; + description { + state: "default" 0.0; + align: 0 0; + visible: 1; + fixed: 1 1; + rel1{ + relative: 0 0; + to: "background"; + } + rel2{ + relative: 1 0; + to: "background"; + } + } + } + part { + name: "border_down"; + type: SWALLOW; + scale : 1; + description { + state: "default" 0.0; + align: 1 1; + visible: 1; + fixed: 1 1; + rel1{ + relative: 0 1; + to: "background"; + } + rel2{ + relative: 1 1; + to: "background"; + } + } + } + part { + name: "border_left"; + type: SWALLOW; + scale : 1; + description { + state: "default" 0.0; + align: 0 0; + visible: 1; + fixed: 1 1; + rel1{ + relative: 0 0; + to: "background"; + } + rel2{ + relative: 0 1; + to: "background"; + } + } + } + part { + name: "border_right"; + type: SWALLOW; + scale : 1; + description { + state: "default" 0.0; + align: 0 0; + visible: 1; + fixed: 1 1; + rel1{ + relative: 1 0; + to: "background"; + } + rel2{ + relative: 1 1; + to: "background"; + } + } + } + } + } +} \ No newline at end of file diff --git a/tizen_src/ewk/efl_integration/resource/BUILD.gn b/tizen_src/ewk/efl_integration/resource/BUILD.gn index ed22cfe..274481b 100644 --- a/tizen_src/ewk/efl_integration/resource/BUILD.gn +++ b/tizen_src/ewk/efl_integration/resource/BUILD.gn @@ -30,6 +30,7 @@ template("edje_res_ewk") { edje_res_ewk("edje_resources_ewk") { sources = [ + "AuthenticationPopup.edc", "AutofillPopup.edc", "JavaScriptPopup.edc", "control.edc", diff --git a/tizen_src/ewk/efl_webview_app/app.c b/tizen_src/ewk/efl_webview_app/app.c index 98b1f4f..f98652c 100644 --- a/tizen_src/ewk/efl_webview_app/app.c +++ b/tizen_src/ewk/efl_webview_app/app.c @@ -88,7 +88,7 @@ static void __did_start_provisional_load_for_frame_cb(void *data, Evas_Object *o static void __did_commit_load_for_frame(void *data, Evas_Object *obj, void *event_info); static void __geoLocation_popup_display_cb(void *data, Evas_Object *obj, void *event_info); void __script_executed_cb(Evas_Object *obj, const char *javascript_result, void *data); -static void __auth_challenge_cb(void* data, Evas_Object *obj, void *event_info); +static void __auth_challenge_cb(Evas_Object* ewk_view, Ewk_Auth_Challenge* auth_challenge, void* user_data); static void __policy_response_decide_cb(void *data, Evas_Object *obj, void *event_info); static void __customize_context_menu_cb(void* data, Evas_Object *obj, void *event_info); static void __customize_context_menu_item_selected_cb(void* data, Evas_Object *obj, void *event_info); @@ -538,7 +538,6 @@ int main(int argc, char** argv) evas_object_smart_callback_add(view, "load,committed", __did_commit_load_for_frame, 0); evas_object_smart_callback_add(view, "load,provisional,started", __did_start_provisional_load_for_frame_cb, 0); evas_object_smart_callback_add(view, "geolocation,permission,request", __geoLocation_popup_display_cb,0); - evas_object_smart_callback_add(view, "authentication,challenge", __auth_challenge_cb, 0); evas_object_smart_callback_add(view, "policy,response,decide", __policy_response_decide_cb, 0); evas_object_smart_callback_add(view, "contextmenu,customize", __customize_context_menu_cb, 0); evas_object_smart_callback_add(view, "contextmenu,selected", __customize_context_menu_item_selected_cb, 0); @@ -565,6 +564,7 @@ int main(int argc, char** argv) ewk_view_custom_header_add(view, "X-Test-header", "X-Value-1"); ewk_view_notification_permission_callback_set(view, __notification_permission_cb, 0); + ewk_view_authentication_callback_set(view, __auth_challenge_cb, NULL); #if defined(OS_TIZEN) if (IsMobileProfile() || IsWearableProfile()) { @@ -850,13 +850,14 @@ void __navigation_policy_decide_cb(void *data, Evas_Object *obj, void *event_inf ewk_policy_decision_use(decision); } -void __auth_challenge_cb(void* data, Evas_Object *obj, void *event_info) +void __auth_challenge_cb(Evas_Object* ewk_view, Ewk_Auth_Challenge* auth_challenge, void* user_data) { printf("APP.C callback called __auth_challenge_cb \n"); - Ewk_Auth_Challenge* auth_challenge = (Ewk_Auth_Challenge*)event_info; auth_challenge_holder = auth_challenge; - if (!auth_challenge) + if (!auth_challenge) { fprintf(stderr, "auth_challenge NULL\n"); + return; + } const char* realm = ewk_auth_challenge_realm_get(auth_challenge); const char* url = ewk_auth_challenge_url_get(auth_challenge); diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_cancel_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_cancel_func.cpp index a834487..b577874 100755 --- a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_cancel_func.cpp +++ b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_cancel_func.cpp @@ -10,12 +10,14 @@ static Eina_Bool is_Authenticated; class utc_blink_ewk_auth_challenge_credential_cancel : public utc_blink_ewk_base { protected: - void PostSetUp() { - evas_object_smart_callback_add(GetEwkWebView(), "authentication,challenge", authentication_challenge, this); + void PostSetUp() override + { + ewk_view_authentication_callback_set(GetEwkWebView(), AuthenticationChallenge, this); } - void PreTearDown() { - evas_object_smart_callback_del(GetEwkWebView(), "authentication,challenge", authentication_challenge); + void PreTearDown() override + { + ewk_view_authentication_callback_set(GetEwkWebView(), nullptr, nullptr); } void LoadFinished(Evas_Object* webview) @@ -23,12 +25,11 @@ protected: EventLoopStop(utc_blink_ewk_base::Failure); // will noop if EventLoopStop was alraedy called } - static void authentication_challenge(void* data, Evas_Object* webview, void* event_info) + static void AuthenticationChallenge(Evas_Object* o, Ewk_Auth_Challenge* auth_challenge, void* data) { utc_blink_ewk_auth_challenge_credential_cancel *owner = static_cast(data); utc_message("[authentication_challenge] :: "); - Ewk_Auth_Challenge* auth_challenge = (Ewk_Auth_Challenge*)event_info; if (!auth_challenge) { owner->EventLoopStop(utc_blink_ewk_base::Failure); return; diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_use_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_use_func.cpp index 1895cad..8b5467c 100755 --- a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_use_func.cpp +++ b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_credential_use_func.cpp @@ -9,14 +9,15 @@ class utc_blink_ewk_auth_challenge_credential_use : public utc_blink_ewk_base { protected: - void PostSetUp() + void PostSetUp() override { - evas_object_smart_callback_add( GetEwkWebView(), "authentication,challenge", authentication_challenge, this); + ewk_view_authentication_callback_set(GetEwkWebView(), AuthenticationChallenge, this); } - void PreTearDown() + void PreTearDown() override { evas_object_smart_callback_del( GetEwkWebView(), "authentication,challenge", authentication_challenge); + ewk_view_authentication_callback_set(GetEwkWebView(), nullptr, nullptr); } void LoadFinished(Evas_Object* webview) @@ -24,12 +25,11 @@ protected: EventLoopStop( utc_blink_ewk_base::Failure ); // will noop if EventLoopStop was alraedy called } - static void authentication_challenge(void* data, Evas_Object* webview, void* event_info) + static void AuthenticationChallenge(Evas_Object* o, Ewk_Auth_Challenge* auth_challenge, void* data) { utc_message("[authentication_challenge] :: "); utc_blink_ewk_auth_challenge_credential_use *owner = static_cast(data); - Ewk_Auth_Challenge* auth_challenge = (Ewk_Auth_Challenge*)event_info; if (!auth_challenge) { owner->EventLoopStop( utc_blink_ewk_base::Failure ); // will noop if EventLoopStop was alraedy called utc_fail(); diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_realm_get_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_realm_get_func.cpp index 2ab69da..35db7b4 100755 --- a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_realm_get_func.cpp +++ b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_realm_get_func.cpp @@ -8,14 +8,14 @@ class utc_blink_ewk_auth_challenge_realm_get : public utc_blink_ewk_base { protected: - void PostSetUp() + void PostSetUp() override { - evas_object_smart_callback_add(GetEwkWebView(), "authentication,challenge", authentication_challenge, this); + ewk_view_authentication_callback_set(GetEwkWebView(), AuthenticationChallenge, this); } - void PreTearDown() + void PreTearDown() override { - evas_object_smart_callback_del(GetEwkWebView(), "authentication,challenge", authentication_challenge); + ewk_view_authentication_callback_set(GetEwkWebView(), nullptr, nullptr); } void LoadFinished(Evas_Object* webview) @@ -23,19 +23,16 @@ protected: EventLoopStop( utc_blink_ewk_base::Failure ); // will noop if EventLoopStop was alraedy called } - static void authentication_challenge(void* data, Evas_Object* webview, void* event_info) + static void AuthenticationChallenge(Evas_Object* o, Ewk_Auth_Challenge* auth_challenge, void* data) { ASSERT_TRUE(data != NULL); utc_blink_ewk_auth_challenge_realm_get *owner = static_cast(data); - Ewk_Auth_Challenge* auth_challenge = static_cast(event_info); - - if(auth_challenge) + if (auth_challenge) { std::string realm = ewk_auth_challenge_realm_get(auth_challenge); - if( realm == "Widget TestCases EARLY ACCESS" ) { - + if (realm == "Widget TestCases EARLY ACCESS") { owner->EventLoopStop(utc_blink_ewk_base::Success); return; } diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_suspend_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_suspend_func.cpp index 7e6baa4..b721c5a 100755 --- a/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_suspend_func.cpp +++ b/tizen_src/ewk/unittest/utc_blink_ewk_auth_challenge_suspend_func.cpp @@ -8,14 +8,14 @@ class utc_blink_ewk_auth_challenge_suspend : public utc_blink_ewk_base { protected: - void PostSetUp() + void PostSetUp() override { - evas_object_smart_callback_add(GetEwkWebView(), "authentication,challenge", authentication_challenge, this); + ewk_view_authentication_callback_set(GetEwkWebView(), AuthenticationChallenge, this); } - void PreTearDown() + void PreTearDown() override { - evas_object_smart_callback_del(GetEwkWebView(), "authentication,challenge", authentication_challenge); + ewk_view_authentication_callback_set(GetEwkWebView(), nullptr, nullptr); } void LoadFinished(Evas_Object* webview) @@ -23,7 +23,7 @@ protected: EventLoopStop( utc_blink_ewk_base::Failure ); // will noop if EventLoopStop was alraedy called } - static void authentication_challenge(void* data, Evas_Object* webview, void* event_info) + static void AuthenticationChallenge(Evas_Object* o, Ewk_Auth_Challenge* auth_challenge, void* data) { ASSERT_TRUE(data != NULL); @@ -31,7 +31,7 @@ protected: Ewk_Auth_Challenge* auth_challenge = static_cast(event_info); - if(auth_challenge) + if (auth_challenge) { ewk_auth_challenge_suspend(auth_challenge); -- 2.7.4 From b8a33c8bb6bc62342c04d9908ce09bd98d0b866c Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Mon, 6 Dec 2021 18:21:05 +0530 Subject: [PATCH 08/16] [M94 Migration] Bringup Authentication popup Migrated Authentication popup code from M85 Cherry-picked from: https://review.tizen.org/gerrit/267205 Test site: https://the-internet.herokuapp.com/basic_auth Change-Id: I9d130b6962f44905fd5c0acf731c830846059c59 Signed-off-by: Surya Kumar --- .../efl_integration/browser/login_delegate_efl.cc | 90 ++++++++-------------- .../efl_integration/browser/login_delegate_efl.h | 40 ++++++---- .../efl_integration/content_browser_client_efl.cc | 17 ++++ .../efl_integration/content_browser_client_efl.h | 10 +++ tizen_src/ewk/efl_integration/eweb_context.cc | 6 ++ tizen_src/ewk/efl_integration/eweb_context.h | 5 ++ .../private/ewk_auth_challenge_private.h | 2 +- .../efl_integration/private/ewk_context_private.cc | 5 ++ .../efl_integration/private/ewk_context_private.h | 1 + .../ewk/efl_integration/public/ewk_context.cc | 10 ++- .../efl_integration/web_contents_delegate_efl.cc | 6 +- .../efl_integration/web_contents_delegate_efl.h | 4 +- 12 files changed, 113 insertions(+), 83 deletions(-) diff --git a/tizen_src/ewk/efl_integration/browser/login_delegate_efl.cc b/tizen_src/ewk/efl_integration/browser/login_delegate_efl.cc index cd392b9..708a1de 100644 --- a/tizen_src/ewk/efl_integration/browser/login_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/login_delegate_efl.cc @@ -2,95 +2,69 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "browser/login_delegate_efl.h" - -#include +#include "login_delegate_efl.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "net/base/auth.h" -#include "net/url_request/url_request.h" - +#include "private/ewk_context_private.h" #include "web_contents_delegate_efl.h" -#include "common/web_contents_utils.h" using content::BrowserThread; -using content::RenderViewHost; -using content::RenderFrameHost; using content::WebContents; -LoginDelegateEfl::LoginDelegateEfl(net::AuthChallengeInfo* auth_info, net::URLRequest* request) +/* LCOV_EXCL_START */ +LoginDelegateEfl::LoginDelegateEfl( + const net::AuthChallengeInfo* auth_info, + const GURL& url, + content::WebContents* web_contents, + LoginAuthRequiredCallback auth_required_callback, + bool first_auth_attempt) : auth_info_(auth_info), - request_(request), - render_process_id_(-1), - render_frame_id_(-1) { -#if !defined(EWK_BRINGUP) // FIXME: m85 bringup - bool result = ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_id_, &render_frame_id_); - - DCHECK(result); - DCHECK(render_process_id_ != -1); - DCHECK(render_frame_id_ != -1); -#endif - - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + url_(url), + web_contents_(web_contents), + auth_required_callback_(std::move(auth_required_callback)), + first_auth_attempt_(first_auth_attempt) { + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&LoginDelegateEfl::HandleHttpAuthRequestOnUIThread, base::Unretained(this))); } -LoginDelegateEfl::~LoginDelegateEfl() { -} void LoginDelegateEfl::Proceed(const char* user, const char* password) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&LoginDelegateEfl::ProceedOnIOThread, - base::Unretained(this), base::UTF8ToUTF16(user), - base::UTF8ToUTF16(password))); + std::move(auth_required_callback_).Run(net::AuthCredentials( + base::UTF8ToUTF16(user), base::UTF8ToUTF16(password))); } void LoginDelegateEfl::Cancel() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&LoginDelegateEfl::CancelOnIOThread, - base::Unretained(this))); + std::move(auth_required_callback_).Run(absl::nullopt); } void LoginDelegateEfl::HandleHttpAuthRequestOnUIThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - WebContents* web_contents = web_contents_utils::WebContentsFromFrameID(render_process_id_, render_frame_id_); - if (!web_contents) { + if (!web_contents_ || !web_contents_->GetDelegate()) { Cancel(); return; } content::WebContentsDelegateEfl* delegate = - static_cast(web_contents->GetDelegate()); - DCHECK(delegate); - delegate->OnAuthRequired(request_, auth_info_->realm, this); -} + static_cast( + web_contents_->GetDelegate()); -void LoginDelegateEfl::CancelOnIOThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (request_) { - request_->CancelAuth(); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_); -#endif - request_ = NULL; - } -} + if (first_auth_attempt_ && auth_info_->is_proxy) { + const EWebContext* web_context = delegate->web_view()->context()->GetImpl(); + DCHECK(web_context); -void LoginDelegateEfl::ProceedOnIOThread(const std::u16string& user, - const std::u16string& password) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (request_) { - request_->SetAuth(net::AuthCredentials(user, password)); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_); -#endif - request_ = NULL; + if (!web_context->GetProxyUsername().empty()) { + Proceed(web_context->GetProxyUsername().c_str(), + web_context->GetProxyPassword().c_str()); + return; + } } + + delegate->OnAuthRequired(auth_info_->realm, url_, this); } +/* LCOV_EXCL_STOP */ diff --git a/tizen_src/ewk/efl_integration/browser/login_delegate_efl.h b/tizen_src/ewk/efl_integration/browser/login_delegate_efl.h index 1f655fb..fb38567 100644 --- a/tizen_src/ewk/efl_integration/browser/login_delegate_efl.h +++ b/tizen_src/ewk/efl_integration/browser/login_delegate_efl.h @@ -7,31 +7,37 @@ #include "base/memory/ref_counted.h" #include "content/public/browser/login_delegate.h" +#include "url/gurl.h" namespace net { class AuthChallengeInfo; class URLRequest; } +namespace content { +class WebContents; +} + class LoginDelegateEfl : public content::LoginDelegate { public: - LoginDelegateEfl(net::AuthChallengeInfo* auth_info, net::URLRequest* request); - - virtual void Proceed(const char* user, const char* password); - virtual void Cancel(); - virtual ~LoginDelegateEfl(); - - private: - void HandleHttpAuthRequestOnUIThread(); - void CancelOnIOThread(); - void ProceedOnIOThread(const std::u16string& user, - const std::u16string& password); - void DeleteAuthHandlerSoon(); - - std::unique_ptr auth_info_; - net::URLRequest* request_; - int render_process_id_; - int render_frame_id_; + LoginDelegateEfl(const net::AuthChallengeInfo* auth_info, + const GURL& url, + content::WebContents* web_contents, + LoginAuthRequiredCallback auth_required_callback, + bool first_auth_attempt); + + void Proceed(const char* user, const char* password); + void Cancel(); + ~LoginDelegateEfl() override {}; + + private: + void HandleHttpAuthRequestOnUIThread(); + + const net::AuthChallengeInfo* auth_info_; + GURL url_; + content::WebContents* web_contents_; + LoginAuthRequiredCallback auth_required_callback_; + const bool first_auth_attempt_; }; #endif /* LOGIN_DELEGATE_EFL_H_ */ diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc index 418cbd1..508f87a 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -465,4 +465,21 @@ void ContentBrowserClientEfl::NotifyAcceptLangsChanged() { } } +std::unique_ptr ContentBrowserClientEfl::CreateLoginDelegate( + const net::AuthChallengeInfo& auth_info, + WebContents* web_contents, + const GlobalRequestID& request_id, + bool is_request_for_main_frame, + const GURL& url, + scoped_refptr response_headers, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback) { + if (web_contents) { + return std::unique_ptr(new LoginDelegateEfl( + &auth_info, url, web_contents, std::move(auth_required_callback), + first_auth_attempt)); + } + return nullptr; +} + } // namespace content diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.h b/tizen_src/ewk/efl_integration/content_browser_client_efl.h index cc11fb1..6df35ec 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.h +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.h @@ -111,6 +111,16 @@ class ContentBrowserClientEfl : public ContentBrowserClient { browser_context_efl_ = context; } + virtual std::unique_ptr CreateLoginDelegate( + const net::AuthChallengeInfo& auth_info, + WebContents* web_contents, + const GlobalRequestID& request_id, + bool is_request_for_main_frame, + const GURL& url, + scoped_refptr response_headers, + bool first_auth_attempt, + LoginAuthRequiredCallback auth_required_callback) override; + std::string GetProduct() override; std::string GetUserAgent() override; diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index d1d9ed8..d8b5a0f 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -512,6 +512,12 @@ void EWebContext::SetProxyUri(const char* uri) { #endif } +void EWebContext::SetProxyDefaultAuth(const char* username, + const char* password) { + proxy_username_ = (username != nullptr) ? string(username) : string(); + proxy_password_ = (password != nullptr) ? string(password) : string(); +} + void EWebContext::SetDidStartDownloadCallback( Ewk_Context_Did_Start_Download_Callback callback, void* user_data) { diff --git a/tizen_src/ewk/efl_integration/eweb_context.h b/tizen_src/ewk/efl_integration/eweb_context.h index e6f94ca..6b06804 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.h +++ b/tizen_src/ewk/efl_integration/eweb_context.h @@ -110,6 +110,9 @@ class EWebContext { void SetProxyUri(const char* uri); const char* GetProxyUri() const { return proxy_uri_.c_str(); } + void SetProxyDefaultAuth(const char* username, const char* password); + const std::string& GetProxyUsername() const { return proxy_username_; } + const std::string& GetProxyPassword() const { return proxy_password_; } //download start callback handlers void SetDidStartDownloadCallback(Ewk_Context_Did_Start_Download_Callback callback, void* user_data); @@ -184,6 +187,8 @@ class EWebContext { std::unique_ptr tizen_extensible_; std::unique_ptr ewk_favicon_database_; std::string proxy_uri_; + std::string proxy_username_; + std::string proxy_password_; std::string injected_bundle_path_; #if defined(OS_TIZEN) diff --git a/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h b/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h index 14172ff..ded617d 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h @@ -24,7 +24,7 @@ struct _Ewk_Auth_Challenge { is_suspended(false) { } - std::unique_ptr login_delegate; + LoginDelegateEfl* login_delegate; std::string url; std::string realm; bool is_decided; diff --git a/tizen_src/ewk/efl_integration/private/ewk_context_private.cc b/tizen_src/ewk/efl_integration/private/ewk_context_private.cc index ef5cd9e..95ea267 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_context_private.cc @@ -104,6 +104,11 @@ const char* Ewk_Context::GetProxyUri() const { return impl->GetProxyUri(); } +void Ewk_Context::SetProxyDefaultAuth(const char* username, + const char* password) { + impl->SetProxyDefaultAuth(username, password); +} + void Ewk_Context::NotifyLowMemory() { impl->NotifyLowMemory(); } diff --git a/tizen_src/ewk/efl_integration/private/ewk_context_private.h b/tizen_src/ewk/efl_integration/private/ewk_context_private.h index 050b60b..4b684af 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_context_private.h @@ -46,6 +46,7 @@ struct Ewk_Context : public base::RefCounted { // Proxy URI void SetProxyUri(const char* uri); const char* GetProxyUri() const; + void SetProxyDefaultAuth(const char* username, const char* password); // System void NotifyLowMemory(); diff --git a/tizen_src/ewk/efl_integration/public/ewk_context.cc b/tizen_src/ewk/efl_integration/public/ewk_context.cc index 89c0f12..e9676da 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_context.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_context.cc @@ -756,8 +756,14 @@ const char* ewk_context_proxy_bypass_rule_get(Ewk_Context* context) Eina_Bool ewk_context_proxy_default_auth_set(Ewk_Context* context, const char* username, const char* password) { - LOG_EWK_API_MOCKUP(); - return false; +#if defined(OS_TIZEN_TV_PRODUCT) + EINA_SAFETY_ON_NULL_RETURN_VAL(context, EINA_FALSE); + context->SetProxyDefaultAuth(username, password); + return EINA_TRUE; +#else + LOG_EWK_API_MOCKUP("Only for Tizen TV"); + return EINA_FALSE; +#endif } void ewk_context_password_confirm_popup_callback_set(Ewk_Context* context, Ewk_Context_Password_Confirm_Popup_Callback callback, void* user_data) diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc index 425fe6b..4cccc22 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -323,10 +323,10 @@ void WebContentsDelegateEfl::RequestMediaAccessPermission( } #endif -void WebContentsDelegateEfl::OnAuthRequired(net::URLRequest* request, - const std::string& realm, +void WebContentsDelegateEfl::OnAuthRequired(const std::string& realm, + const GURL& url, LoginDelegateEfl* login_delegate) { - web_view_->InvokeAuthCallback(login_delegate, request->url(), realm); + web_view_->InvokeAuthCallback(login_delegate, url, realm); } void WebContentsDelegateEfl::DidStartProvisionalLoadForFrame( diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h index c99f0bc..dbb08ea 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h @@ -186,8 +186,8 @@ class WebContentsDelegateEfl : public WebContentsDelegate, bool was_ignored_by_handler); // EWK_BRINGUP end. - void OnAuthRequired(net::URLRequest* request, - const std::string& realm, + void OnAuthRequired(const std::string& realm, + const GURL& url, LoginDelegateEfl* login_delegate); void DidDownloadFavicon(bool success, -- 2.7.4 From a9fb54668f5dddbdc62d2e82229c82837de393a4 Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Fri, 10 Dec 2021 23:06:17 +0530 Subject: [PATCH 09/16] [M94 Migration] Create |net::CertVerifier| on UI thread. |net::CertVerifier::CreateDefault()| invokes |getenv| which is not thread safe function [1]. Previously, |net::CertVerifier::CreateDefault()| was called in |GetURLRequestContext()| which is running on |BrowserThread::IO|. So sometime it has crash because of accessing invalid address. This patch creates |net::CertVerifier| on constructor which is running on |BrowserThread::UI| and uses when it necessary. [1] : https://rachelbythebay.com/w/2017/01/30/env/ Reference: https://review.tizen.org/gerrit/261757 Change-Id: I587f7377d64cfaaf57a258af2c8914c28787cf3b Signed-off-by: Gajendra N --- tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc | 6 ++++-- tizen_src/ewk/efl_integration/url_request_context_getter_efl.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc index 437244b..400fb3b 100644 --- a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc +++ b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.cc @@ -57,6 +57,9 @@ URLRequestContextGetterEfl::URLRequestContextGetterEfl( // Must first be created on the UI thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + cert_verifier_ = + net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr); + proxy_config_service_ = net::ConfiguredProxyResolutionService::CreateSystemProxyConfigService( io_task_runner); @@ -107,8 +110,7 @@ net::URLRequestContext* URLRequestContextGetterEfl::GetURLRequestContext() { command_line.GetSwitchValueASCII(network::switches::kHostResolverRules))); storage_->set_host_resolver(std::move(host_resolver)); - storage_->set_cert_verifier( - net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr)); + storage_->set_cert_verifier(std::move(cert_verifier_)); storage_->set_transport_security_state( base::WrapUnique(new net::TransportSecurityState)); storage_->set_ct_policy_enforcer( diff --git a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h index 97464f4..771d8e81 100644 --- a/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h +++ b/tizen_src/ewk/efl_integration/url_request_context_getter_efl.h @@ -19,6 +19,7 @@ #include "public/ewk_cookie_manager_internal.h" namespace net { +class CertVerifier; class HostResolver; class NetLog; } @@ -80,6 +81,7 @@ class URLRequestContextGetterEfl : public net::URLRequestContextGetter { std::unique_ptr proxy_config_service_; std::unique_ptr network_delegate_; std::unique_ptr storage_; + std::unique_ptr cert_verifier_; std::unique_ptr url_request_context_; base::WeakPtrFactory weak_ptr_factory_; -- 2.7.4 From 9bf7e03e296c59ee9b790a226719292fee994906 Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Tue, 7 Dec 2021 14:04:04 +0530 Subject: [PATCH 10/16] [M94 Migration] Introduce event resampler 1. Event resampler changes interval of touchmove, scroll, pinch event to vsync and recalculates touchmove position to improve smoothness 2. This change fixes touch event does not work issue. When a problem occurs, touch up event is handled by event_resampler. Because of this, for statement was returned without processing the next up event. It should be "continue" instead of "return" Cherry-picked from: https://review.tizen.org/gerrit/267576 Change-Id: Id20a585160b499d347cc9ad77af04d19a37ba633 Signed-off-by: Surya Kumar --- .../chromium_impl/content/browser/browser_efl.gni | 2 + .../browser/renderer_host/event_resampler.cc | 240 +++++++++++++++++++++ .../browser/renderer_host/event_resampler.h | 74 +++++++ .../renderer_host/render_widget_host_view_efl.cc | 39 +++- .../renderer_host/render_widget_host_view_efl.h | 10 +- 5 files changed, 358 insertions(+), 7 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc create mode 100644 tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index 6ad1ca9..b463e0d 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -79,6 +79,8 @@ external_content_browser_efl_sources = [ "//tizen_src/chromium_impl/content/browser/renderer_host/disambiguation_popup_efl.h", "//tizen_src/chromium_impl/content/browser/renderer_host/edge_effect.cc", "//tizen_src/chromium_impl/content/browser/renderer_host/edge_effect.h", + "//tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc", + "//tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h", "//tizen_src/chromium_impl/content/browser/renderer_host/im_context_efl.cc", "//tizen_src/chromium_impl/content/browser/renderer_host/im_context_efl.h", "//tizen_src/chromium_impl/content/browser/renderer_host/native_web_keyboard_event_efl.cc", diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc new file mode 100644 index 0000000..c043f2e --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc @@ -0,0 +1,240 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/event_resampler.h" + +#include "content/browser/renderer_host/render_widget_host_view_efl.h" +#include "ui/events/event_constants.h" + +namespace { +// Currently we can resample two fingers only. +const int kIdentifiableTouchCount = 2; + +// Two latest touchmove events are used for resampling. +const unsigned kTouchMoveEventQueueSize = 2; + +// Latency added during resampling. A few milliseconds doesn't hurt much but +// reduces the impact of mispredicted touch positions. +const float kResampleLatency = 5; + +// Minimum time difference between consecutive samples before attempting to +// resample. +const float kResampleMinDelta = 2; + +// Maximum time to predict forward from the last known state, to avoid +// predicting too far into the future. This time is further bounded by 50% of +// the last time delta. +const float kResampleMaxPrediction = 8; +} // namespace + +namespace content { + +EventResampler::EventResampler(EventResamplerClient* client) + : client_(client) {} + +EventResampler::~EventResampler() { + if (!vsync_animator_) + return; + + ecore_animator_del(vsync_animator_); + vsync_animator_ = nullptr; +} + +bool EventResampler::HandleTouchMoveEvent(ui::TouchEvent event) { + if (event.type() != ui::EventType::ET_TOUCH_MOVED) + return false; + + int id = event.pointer_details().id; + if (id >= kIdentifiableTouchCount) + return false; + + if (!vsync_animator_) { + vsync_animator_ = ecore_animator_add(VsyncAnimatorCallback, this); + return false; + } + + touch_move_event_queue_[id].push(event); + if (touch_move_event_queue_[id].size() > kTouchMoveEventQueueSize) + touch_move_event_queue_[id].pop(); + + has_pending_touch_move_event_[id] = true; + + return true; +} + +bool EventResampler::HandleGestureEvent(blink::WebGestureEvent& event) { + switch (event.GetType()) { + case blink::WebInputEvent::Type::kGestureScrollBegin: + has_pending_scroll_event_ = false; + pending_scroll_delta_.SetPoint(0.0, 0.0); + break; + case blink::WebInputEvent::Type::kGestureScrollUpdate: + last_scroll_update_event_ = event; + pending_scroll_delta_.Offset(event.data.scroll_update.delta_x, + event.data.scroll_update.delta_y); + has_pending_scroll_event_ = true; + if (!is_scroll_processed_in_last_callback_) { + ResampleScrollUpdate(); + is_scroll_processed_in_last_callback_ = true; + } + return true; + case blink::WebInputEvent::Type::kGesturePinchBegin: + has_pending_pinch_event_ = false; + pending_pinch_scale_ = 1.0; + break; + case blink::WebInputEvent::Type::kGesturePinchUpdate: + last_pinch_update_event_ = event; + pending_pinch_scale_ *= event.data.pinch_update.scale; + has_pending_pinch_event_ = true; + + if (!is_pinch_processed_in_last_callback_) { + ResamplePinchUpdate(); + is_pinch_processed_in_last_callback_ = true; + } + return true; + case blink::WebInputEvent::Type::kGestureFlingStart: + if (has_pending_scroll_event_) + ResampleScrollUpdate(); + break; + default: + break; + } + + return false; +} + +// static +Eina_Bool EventResampler::VsyncAnimatorCallback(void* data) { + auto resampler = static_cast(data); + for (unsigned i = 0; i < kIdentifiableTouchCount; i++) { + if (resampler->has_pending_touch_move_event_[i]) + resampler->ResampleTouchMove(i); + } + + resampler->is_scroll_processed_in_last_callback_ = false; + if (resampler->has_pending_scroll_event_) { + resampler->ResampleScrollUpdate(); + resampler->is_scroll_processed_in_last_callback_ = true; + } + + resampler->is_pinch_processed_in_last_callback_ = false; + if (resampler->has_pending_pinch_event_) { + resampler->ResamplePinchUpdate(); + resampler->is_pinch_processed_in_last_callback_ = true; + } + + if (resampler->CanDeleteAnimator()) { + resampler->ClearTouchMoveEventQueue(); + resampler->vsync_animator_ = nullptr; + return ECORE_CALLBACK_CANCEL; + } + + return ECORE_CALLBACK_RENEW; +} + +bool EventResampler::CanDeleteAnimator() { + if (client_->TouchPointCount() > 0) + return false; + + for (unsigned i = 0; i < kIdentifiableTouchCount; i++) { + if (has_pending_touch_move_event_[i]) + return false; + } + + return !has_pending_scroll_event_ && !has_pending_pinch_event_ && + !is_scroll_processed_in_last_callback_ && + !is_pinch_processed_in_last_callback_; +} + +void EventResampler::ResampleTouchMove(int id) { + if (touch_move_event_queue_[id].empty()) + return; + + has_pending_touch_move_event_[id] = false; + + ui::TouchEvent last_event = touch_move_event_queue_[id].back(); + if (touch_move_event_queue_[id].size() < kTouchMoveEventQueueSize) { + client_->ForwardTouchEvent(&last_event); + return; + } + + ui::TouchEvent first_event = touch_move_event_queue_[id].front(); + + float last_event_timestamp = + (last_event.time_stamp() - base::TimeTicks()).InMillisecondsF(); + float first_event_timestamp = + (first_event.time_stamp() - base::TimeTicks()).InMillisecondsF(); + + float delta = last_event_timestamp - first_event_timestamp; + if (delta < kResampleMinDelta) { + client_->ForwardTouchEvent(&last_event); + return; + } + + float x, y; + float sample_time = ecore_loop_time_get() * 1000 - kResampleLatency; + if (last_event_timestamp > sample_time) { + // Interpolation. + float alpha = (sample_time - first_event_timestamp) / delta; + x = first_event.location().x() + + (last_event.location().x() - first_event.location().x()) * alpha; + y = first_event.location().y() + + (last_event.location().y() - first_event.location().y()) * alpha; + } else { + // Extrapolation. + float max_predict = + last_event_timestamp + std::min(delta / 2, kResampleMaxPrediction); + sample_time = std::min(sample_time, max_predict); + + float alpha = (last_event_timestamp - sample_time) / delta; + x = last_event.location().x() + + (first_event.location().x() - last_event.location().x()) * alpha; + y = last_event.location().y() + + (first_event.location().y() - last_event.location().y()) * alpha; + } + + last_event.set_location_f(gfx::PointF(x, y)); + client_->ForwardTouchEvent(&last_event); +} + +void EventResampler::ResampleScrollUpdate() { + blink::WebGestureEvent event = last_scroll_update_event_; + + double scroll_delta_x = pending_scroll_delta_.x(); + double scroll_delta_y = pending_scroll_delta_.y(); + + // Convert delta type to Int for accuracy of top controls offset. + if (client_->TouchPointCount() == 1) { + scroll_delta_x = (scroll_delta_x > 0) ? std::floor(scroll_delta_x) + : std::ceil(scroll_delta_x); + + scroll_delta_y = (scroll_delta_y > 0) ? std::floor(scroll_delta_y) + : std::ceil(scroll_delta_y); + } + + pending_scroll_delta_.Offset(-scroll_delta_x, -scroll_delta_y); + event.data.scroll_update.delta_x = scroll_delta_x; + event.data.scroll_update.delta_y = scroll_delta_y; + has_pending_scroll_event_ = false; + + client_->ForwardGestureEvent(event); +} + +void EventResampler::ResamplePinchUpdate() { + blink::WebGestureEvent event = last_pinch_update_event_; + event.data.pinch_update.scale = pending_pinch_scale_; + pending_pinch_scale_ = 1.0; + has_pending_pinch_event_ = false; + + client_->ForwardGestureEvent(event); +} + +void EventResampler::ClearTouchMoveEventQueue() { + for (unsigned i = 0; i < kIdentifiableTouchCount; i++) { + std::queue empty; + std::swap(touch_move_event_queue_[i], empty); + } +} + +} // namespace content \ No newline at end of file diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h new file mode 100644 index 0000000..b2f9a86 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h @@ -0,0 +1,74 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EVENT_RESAMPLER +#define EVENT_RESAMPLER + +#include +#include + +#include "third_party/blink/public/common/input/web_gesture_event.h" +#include "ui/events/event.h" +#include "ui/gfx/geometry/point_f.h" + +#define MAX_TOUCH_COUNT 2 + +namespace content { + +class RenderWidgetHostViewEfl; + +class EventResamplerClient { + public: + // Forward resampled touch event. + virtual void ForwardTouchEvent(ui::TouchEvent*) {} + + // Forward resampled gesture event. + virtual void ForwardGestureEvent(blink::WebGestureEvent) {} + + // Return number of touch point. + virtual unsigned TouchPointCount() const { return 0; } +}; + +class EventResampler { + public: + explicit EventResampler(EventResamplerClient* client); + ~EventResampler(); + + bool HandleTouchMoveEvent(ui::TouchEvent event); + bool HandleGestureEvent(blink::WebGestureEvent& event); + + private: + static Eina_Bool VsyncAnimatorCallback(void* data); + + void ResampleTouchMove(int id); + void ResampleScrollUpdate(); + void ResamplePinchUpdate(); + + void ClearTouchMoveEventQueue(); + bool CanDeleteAnimator(); + + EventResamplerClient* client_; + + Ecore_Animator* vsync_animator_ = nullptr; + bool has_pending_touch_move_event_[MAX_TOUCH_COUNT] = { + false, + }; + bool has_pending_scroll_event_ = false; + bool has_pending_pinch_event_ = false; + + // To process without delay if event isn't processed in last callback. + bool is_scroll_processed_in_last_callback_ = false; + bool is_pinch_processed_in_last_callback_ = false; + + std::queue touch_move_event_queue_[MAX_TOUCH_COUNT]; + blink::WebGestureEvent last_scroll_update_event_; + blink::WebGestureEvent last_pinch_update_event_; + + gfx::PointF pending_scroll_delta_; + float pending_pinch_scale_ = 0.0; +}; + +} // namespace content + +#endif // EVENT_RESAMPLER \ No newline at end of file diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc index 3ff61a0..7802845 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc @@ -144,6 +144,7 @@ RenderWidgetHostViewEfl::RenderWidgetHostViewEfl(RenderWidgetHost* widget_host, touch_events_enabled_(false), background_color_(SK_ColorWHITE), web_contents_(web_contents), + event_resampler_(new EventResampler(this)), weak_factory_(this) { parent_view_ = static_cast(web_contents.GetNativeView()); evas_ = evas_object_evas_get(parent_view_); @@ -1158,7 +1159,7 @@ void RenderWidgetHostViewEfl::OnMultiTouchDownEvent(void* data, RenderWidgetHostViewEfl* rwhv = static_cast(data); CHECK(rwhv->touch_events_enabled_); rwhv->ProcessTouchEvents( - static_cast(event_info)->timestamp); + static_cast(event_info)->timestamp, true); } void RenderWidgetHostViewEfl::OnMultiTouchMoveEvent(void* data, @@ -1168,7 +1169,7 @@ void RenderWidgetHostViewEfl::OnMultiTouchMoveEvent(void* data, RenderWidgetHostViewEfl* rwhv = static_cast(data); CHECK(rwhv->touch_events_enabled_); rwhv->ProcessTouchEvents( - static_cast(event_info)->timestamp); + static_cast(event_info)->timestamp, true); } void RenderWidgetHostViewEfl::OnMultiTouchUpEvent(void* data, @@ -1178,7 +1179,7 @@ void RenderWidgetHostViewEfl::OnMultiTouchUpEvent(void* data, RenderWidgetHostViewEfl* rwhv = static_cast(data); CHECK(rwhv->touch_events_enabled_); rwhv->ProcessTouchEvents( - static_cast(event_info)->timestamp); + static_cast(event_info)->timestamp, true); } void RenderWidgetHostViewEfl::OnKeyDown(void* data, @@ -1272,7 +1273,8 @@ void RenderWidgetHostViewEfl::OnMouseWheel(void* data, } } -void RenderWidgetHostViewEfl::ProcessTouchEvents(unsigned int timestamp) { +void RenderWidgetHostViewEfl::ProcessTouchEvents(unsigned int timestamp, + bool is_multi_touch) { // These constants are used to map multi touch's touch id(s). // The poorly-written Tizen API document says: // "0 for Mouse Event and device id for Multi Event." @@ -1318,6 +1320,15 @@ void RenderWidgetHostViewEfl::ProcessTouchEvents(unsigned int timestamp) { ui::TouchEvent touch_event = MakeTouchEvent(pt, state, id, content_image_, timestamp); + + if (state == EVAS_TOUCH_POINT_MOVE) { + if ((id == 0 && is_multi_touch) || (id == 1 && !is_multi_touch)) + continue; + + if (event_resampler_->HandleTouchMoveEvent(touch_event)) + continue; + } + HandleTouchEvent(&touch_event); } } @@ -1367,9 +1378,11 @@ ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { void RenderWidgetHostViewEfl::SendGestureEvent(blink::WebGestureEvent& event) { HandleGesture(event); blink::WebInputEvent::Type event_type = event.GetType(); - if (magnifier_ && - event_type == blink::WebInputEvent::Type::kGestureScrollUpdate) + if ((magnifier_ && event_type == + blink::WebInputEvent::Type::kGestureScrollUpdate) || + event_resampler_->HandleGestureEvent(event)) return; + if (host_ && event_type != blink::WebInputEvent::Type::kUndefined) host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event)); } @@ -1491,6 +1504,20 @@ RenderWidgetHostViewEfl::CreateSyntheticGestureTarget() { return nullptr; } +void RenderWidgetHostViewEfl::ForwardTouchEvent(ui::TouchEvent* event) { + HandleTouchEvent(event); +} + +void RenderWidgetHostViewEfl::ForwardGestureEvent( + blink::WebGestureEvent event) { + if (host_ && event.GetType() != blink::WebInputEvent::Type::kUndefined) + host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event)); +} + +unsigned RenderWidgetHostViewEfl::TouchPointCount() const { + return PointerStatePointerCount(); +} + EdgeEffect& RenderWidgetHostViewEfl::EnsureEdgeEffect() { if (!edge_effect_) edge_effect_ = base::WrapUnique(new EdgeEffect(content_image_elm_host_)); diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h index 71d8fd1..fdbd287 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h @@ -20,6 +20,7 @@ #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/compositor/evasgl_delegated_frame_host.h" #include "content/browser/renderer_host/evas_event_handler.h" +#include "content/browser/renderer_host/event_resampler.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/selection/selection_controller_efl.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -73,6 +74,7 @@ struct TextInputState; class CONTENT_EXPORT RenderWidgetHostViewEfl : public RenderWidgetHostViewBase, public EvasGLDelegatedFrameHostClient, + public EventResamplerClient, public ui::GestureConsumer, public ui::GestureEventHelper, public base::SupportsWeakPtr, @@ -183,6 +185,11 @@ class CONTENT_EXPORT RenderWidgetHostViewEfl // IPC::Sender implementation: bool Send(IPC::Message*) override; + // EventResamplerClient implementation. + void ForwardTouchEvent(ui::TouchEvent*) override; + void ForwardGestureEvent(blink::WebGestureEvent) override; + unsigned TouchPointCount() const override; + void FilterInputMotion(const blink::WebGestureEvent& gesture_event); void EvasToBlinkCords(int x, int y, int* view_x, int* view_y); @@ -286,7 +293,7 @@ class CONTENT_EXPORT RenderWidgetHostViewEfl static void OnHWBackEvent(void*, Evas_Object*, void*); #endif - void ProcessTouchEvents(unsigned int timestamp); + void ProcessTouchEvents(unsigned int timestamp, bool is_multi_touch = false); void SetDoubleTapSupportEnabled(bool enabled); void OnOrientationChangeEvent(int); @@ -366,6 +373,7 @@ class CONTENT_EXPORT RenderWidgetHostViewEfl screen_capture_cb_map_; std::unique_ptr selection_controller_; + std::unique_ptr event_resampler_; viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; -- 2.7.4 From eb7ed26683e412da68c8a2a2cb912887f1086602 Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Wed, 8 Dec 2021 17:27:49 +0530 Subject: [PATCH 11/16] [M94 Migration] Fixed unintended tap gesture after scrolling Sometimes scroll gesture is recognized to tap incorrectly while loading. Touchmove events are stored and processed in |EventResampler|. The problem is that touchmove events which occurred between last ecore animator callback and touchend event are unused to detect gesture. This patch processes pending touchmove events when touchend occurred Cherry-picked from: https://review.tizen.org/gerrit/267676 https://review.tizen.org/gerrit/267723 Change-Id: I20fdbf55d1b02e14cb1f8014f111a82dd47a71fe Signed-off-by: Surya Kumar --- .../content/browser/renderer_host/event_resampler.cc | 13 ++++++++++--- .../content/browser/renderer_host/event_resampler.h | 4 ++-- .../browser/renderer_host/render_widget_host_view_efl.cc | 13 +++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc index c043f2e..9df97b8 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.cc @@ -41,14 +41,21 @@ EventResampler::~EventResampler() { vsync_animator_ = nullptr; } -bool EventResampler::HandleTouchMoveEvent(ui::TouchEvent event) { - if (event.type() != ui::EventType::ET_TOUCH_MOVED) +bool EventResampler::HandleTouchEvent(ui::TouchEvent& event) { + if (event.type() == ui::EventType::ET_TOUCH_PRESSED) return false; int id = event.pointer_details().id; if (id >= kIdentifiableTouchCount) return false; + if (event.type() == ui::EventType::ET_TOUCH_RELEASED || + event.type() == ui::EventType::ET_TOUCH_CANCELLED) { + if (has_pending_touch_move_event_[id]) + ResampleTouchMove(id); + return false; + } + if (!vsync_animator_) { vsync_animator_ = ecore_animator_add(VsyncAnimatorCallback, this); return false; @@ -237,4 +244,4 @@ void EventResampler::ClearTouchMoveEventQueue() { } } -} // namespace content \ No newline at end of file +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h index b2f9a86..9d0c985 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/event_resampler.h @@ -35,7 +35,7 @@ class EventResampler { explicit EventResampler(EventResamplerClient* client); ~EventResampler(); - bool HandleTouchMoveEvent(ui::TouchEvent event); + bool HandleTouchEvent(ui::TouchEvent& event); bool HandleGestureEvent(blink::WebGestureEvent& event); private: @@ -71,4 +71,4 @@ class EventResampler { } // namespace content -#endif // EVENT_RESAMPLER \ No newline at end of file +#endif // EVENT_RESAMPLER diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc index 7802845..c970f26 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc @@ -1304,6 +1304,9 @@ void RenderWidgetHostViewEfl::ProcessTouchEvents(unsigned int timestamp, // Internet Blame URL: // https://groups.google.com/d/msg/mailing-enlightenment-devel/-R-ezCzpkTk/HJ0KBCdz6CgJ id = evas_touch_point_list_nth_id_get(evas_, i); + if ((id == 0 && is_multi_touch) || (id == 1 && !is_multi_touch)) + continue; + DCHECK(id == kMultiTouchIDMapPart0SingleIndex || id >= kMultiTouchIDMapPart1StartIndex); @@ -1320,14 +1323,8 @@ void RenderWidgetHostViewEfl::ProcessTouchEvents(unsigned int timestamp, ui::TouchEvent touch_event = MakeTouchEvent(pt, state, id, content_image_, timestamp); - - if (state == EVAS_TOUCH_POINT_MOVE) { - if ((id == 0 && is_multi_touch) || (id == 1 && !is_multi_touch)) - continue; - - if (event_resampler_->HandleTouchMoveEvent(touch_event)) - continue; - } + if (event_resampler_->HandleTouchEvent(touch_event)) + continue; HandleTouchEvent(&touch_event); } -- 2.7.4 From 11b0e147ed25d40b4d9643afaac8553a7c9bc0b4 Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Wed, 8 Dec 2021 17:50:08 +0530 Subject: [PATCH 12/16] [M94 Migration] Add overscrolled related callbacks This patch adds overscrolled callbacks: - overscrolled,left - overscrolled,right - overscrolled,top - overscrolled,bottom They will be invoked when overscroll occurs for specific element. Cherry-picked from: https://review.tizen.org/gerrit/267677 Change-Id: Ia468853088a7068601d7d9672b29370b8dbeab04 Signed-off-by: Surya Kumar --- .../renderer_host/render_widget_host_view_efl.cc | 7 +++++++ .../browser/web_contents/web_contents_view_efl.cc | 8 ++++++++ .../browser/web_contents/web_contents_view_efl.h | 3 +++ .../browser/web_contents_view_efl_delegate.h | 4 ++++ tizen_src/ewk/efl_integration/eweb_view.cc | 24 ++++++++++++++++++---- tizen_src/ewk/efl_integration/eweb_view.h | 3 +++ .../ewk/efl_integration/eweb_view_callbacks.h | 8 ++++++++ .../web_contents_view_efl_delegate_ewk.cc | 8 +++++++- .../web_contents_view_efl_delegate_ewk.h | 3 +++ 9 files changed, 63 insertions(+), 5 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc index c970f26..be9a00b 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc @@ -983,6 +983,13 @@ void RenderWidgetHostViewEfl::SetNeedsBeginFrames(bool needs_begin_frames) { void RenderWidgetHostViewEfl::DidOverscroll( const ui::DidOverscrollParams& params) { + auto* web_contents_impl = static_cast(&web_contents_); + if (auto* wcve = + static_cast(web_contents_impl->GetView())) { + wcve->OnOverscrolled(params.accumulated_overscroll, + params.latest_overscroll_delta); + } + const gfx::Vector2dF& accumulated_overscroll = params.accumulated_overscroll; const gfx::Vector2dF& latest_overscroll_delta = params.latest_overscroll_delta; diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc index 605fbd8..3810387 100644 --- a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc @@ -373,4 +373,12 @@ bool WebContentsViewEfl::UseKeyPadWithoutUserAction() { return false; } +void WebContentsViewEfl::OnOverscrolled( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta) { + if (efl_delegate_) + efl_delegate_->OnOverscrolled(accumulated_overscroll, + latest_overscroll_delta); +} + } // namespace content diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.h b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.h index 24b19a8..5d6643e 100644 --- a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.h +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.h @@ -95,6 +95,9 @@ class CONTENT_EXPORT WebContentsViewEfl bool UseKeyPadWithoutUserAction(); + void OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta); + private: // Our optional, generic views wrapper. std::unique_ptr delegate_; diff --git a/tizen_src/chromium_impl/content/public/browser/web_contents_view_efl_delegate.h b/tizen_src/chromium_impl/content/public/browser/web_contents_view_efl_delegate.h index 5d19bd5..71bb716 100644 --- a/tizen_src/chromium_impl/content/public/browser/web_contents_view_efl_delegate.h +++ b/tizen_src/chromium_impl/content/public/browser/web_contents_view_efl_delegate.h @@ -46,6 +46,10 @@ class WebContentsViewEflDelegate { virtual void OrientationLock(device::mojom::ScreenOrientationLockType) = 0; virtual void OrientationUnlock() = 0; + + virtual void OnOverscrolled( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta) = 0; }; } // namespace content diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 52b66e3..401c454 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -11,7 +11,10 @@ #include "base/strings/utf_string_conversions.h" #include "browser/navigation_policy_handler_efl.h" #include "browser/quota_permission_context_efl.h" +#include "browser/selectpicker/popup_menu_item.h" +#include "browser/selectpicker/popup_menu_item_private.h" #include "browser/web_view_browser_message_filter.h" +#include "browser/web_view_evas_handler.h" #include "common/content_client_efl.h" #include "common/render_messages_ewk.h" #include "common/version_info.h" @@ -52,14 +55,11 @@ #include "tizen/system_info.h" #include "ui/base/l10n/l10n_util.h" #include "ui/display/screen.h" +#include "ui/gfx/geometry/vector2d_f.h" #include "web_contents_delegate_efl.h" #include "web_contents_efl_delegate_ewk.h" #include "web_contents_view_efl_delegate_ewk.h" -#include "browser/web_view_evas_handler.h" - -#include "browser/selectpicker/popup_menu_item.h" -#include "browser/selectpicker/popup_menu_item_private.h" #include #include #include @@ -2443,3 +2443,19 @@ void EWebView::ClosePage() { web_contents_->ClosePage(); } +void EWebView::OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta) { + const gfx::Vector2dF old_overscroll = + accumulated_overscroll - latest_overscroll_delta; + + if (latest_overscroll_delta.x() && !old_overscroll.x()) { + latest_overscroll_delta.x() < 0 + ? SmartCallback().call() + : SmartCallback().call(); + } + if (latest_overscroll_delta.y() && !old_overscroll.y()) { + latest_overscroll_delta.y() < 0 + ? SmartCallback().call() + : SmartCallback().call(); + } +} diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index b4abe90..6f46f2f 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -480,6 +480,9 @@ class EWebView { void SyncAcceptLanguages(const std::string& accept_languages); + void OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta); + private: void InitializeContent(); void SendDelayedMessages(content::RenderViewHost* render_view_host); diff --git a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h index 95aac0b..c4eaca46 100644 --- a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h +++ b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h @@ -111,6 +111,10 @@ enum CallbackType { EdgeRight, EdgeTop, EdgeBottom, + OverscrolledLeft, + OverscrolledRight, + OverscrolledTop, + OverscrolledBottom, TextStyleState, TextSelectionMode, SaveSessionData, @@ -253,6 +257,10 @@ DECLARE_EWK_VIEW_CALLBACK(EdgeLeft, "edge,left", void); DECLARE_EWK_VIEW_CALLBACK(EdgeTop, "edge,top", void); DECLARE_EWK_VIEW_CALLBACK(EdgeBottom, "edge,bottom", void); DECLARE_EWK_VIEW_CALLBACK(EdgeRight, "edge,right", void); +DECLARE_EWK_VIEW_CALLBACK(OverscrolledLeft, "overscrolled,left", void); +DECLARE_EWK_VIEW_CALLBACK(OverscrolledRight, "overscrolled,right", void); +DECLARE_EWK_VIEW_CALLBACK(OverscrolledTop, "overscrolled,top", void); +DECLARE_EWK_VIEW_CALLBACK(OverscrolledBottom, "overscrolled,bottom", void); DECLARE_EWK_VIEW_CALLBACK(TextStyleState, "text,style,state", _Ewk_Text_Style*); DECLARE_EWK_VIEW_CALLBACK(SaveSessionData, "save,session,data", void); DECLARE_EWK_VIEW_CALLBACK(UndoSize, "undo,size", size_t*); diff --git a/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.cc b/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.cc index 68d1b5f..1838af0 100644 --- a/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.cc +++ b/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "web_contents_view_efl_delegate_ewk.h" -#include "ewk/efl_integration/private/webview_delegate_ewk.h" #include "eweb_view.h" +#include "ewk/efl_integration/private/webview_delegate_ewk.h" WebContentsViewEflDelegateEwk::WebContentsViewEflDelegateEwk(EWebView* wv) : web_view_(wv) { @@ -82,3 +82,9 @@ void WebContentsViewEflDelegateEwk::OrientationLock( void WebContentsViewEflDelegateEwk::OrientationUnlock() { WebViewDelegateEwk::GetInstance().RequestHandleOrientationUnlock(web_view_); } + +void WebContentsViewEflDelegateEwk::OnOverscrolled( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta) { + web_view_->OnOverscrolled(accumulated_overscroll, latest_overscroll_delta); +} diff --git a/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.h b/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.h index e9371ef..6330b27 100644 --- a/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.h +++ b/tizen_src/ewk/efl_integration/web_contents_view_efl_delegate_ewk.h @@ -46,6 +46,9 @@ class WebContentsViewEflDelegateEwk virtual void OrientationUnlock() override; private: + void OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta) override; + EWebView* web_view_; }; -- 2.7.4 From 0bdeb46763ff361019257e346e0fc520d53594b5 Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Mon, 3 Jan 2022 13:26:33 +0530 Subject: [PATCH 13/16] [M94 Migration] Remove EWK_BRINGUP for WebContentsDelegateEfl::DidAddMessageToConsole() WebContentsDelegateEfl::DidAddMessageToConsole() is required majorly for debugging purposes. This patch enables printing console messages to terminal. Reference: https://review.tizen.org/gerrit/246836 Change-Id: Ia80c73a03a2d007e8f25d8b93e4692f138d68284 Signed-off-by: Gajendra N (cherry picked from commit aa4911baeaa2d91706df1ea2e8bb1fd1ac9268e9) --- tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc index 4cccc22..a8e50a8 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -665,16 +665,13 @@ bool WebContentsDelegateEfl::DidAddMessageToConsole( const std::u16string& message, int32_t line_no, const std::u16string& source_id) { -#if !defined(EWK_BRINGUP) // FIXME: m76 bringup std::unique_ptr<_Ewk_Console_Message> console_message( - new _Ewk_Console_Message(level, base::UTF16ToUTF8(message).c_str(), - line_no, base::UTF16ToUTF8(source_id).c_str())); + new _Ewk_Console_Message(static_cast(level), + base::UTF16ToUTF8(message).c_str(), line_no, + base::UTF16ToUTF8(source_id).c_str())); web_view_->SmartCallback().call( console_message.get()); return true; -#else - return false; -#endif } void WebContentsDelegateEfl::RunFileChooser( -- 2.7.4 From efb107414e82c92d62b23202b64ad392b2ab1030 Mon Sep 17 00:00:00 2001 From: Surya Kumar Date: Mon, 3 Jan 2022 22:06:55 +0530 Subject: [PATCH 14/16] [M94 Migration] Bringup notification and migrate related patches from M85 Notification related changes have been migrated from M85 Cherry-picked from: https://review.tizen.org/gerrit/266990 https://review.tizen.org/gerrit/267758 Change-Id: I098541a7a0782abd92d123ca5d2abac236fe62d8 Signed-off-by: Surya Kumar --- packaging/chromium-efl.spec | 2 + tizen_src/build/BUILD.gn | 26 + .../chromium_impl/content/common/paths_efl.cc | 34 + tizen_src/chromium_impl/content/common/paths_efl.h | 2 + tizen_src/ewk/efl_integration/BUILD.gn | 15 +- .../notification/notification_controller_efl.cc | 743 ++++++++++++++++----- .../notification/notification_controller_efl.h | 176 +++-- .../browser/notification/notification_helper.cc | 156 +++++ .../browser/notification/notification_helper.h | 68 ++ .../efl_integration/content_browser_client_efl.cc | 12 +- .../efl_integration/content_browser_client_efl.h | 10 +- .../ewk/efl_integration/eweb_view_callbacks.h | 6 +- .../permission_controller_delegate_efl.cc | 8 +- .../private/ewk_notification_private.cc | 16 +- .../private/ewk_notification_private.h | 8 +- .../ewk/efl_integration/public/ewk_context.cc | 35 +- .../ewk/efl_integration/public/ewk_notification.cc | 27 +- .../efl_integration/web_contents_delegate_efl.cc | 45 ++ .../efl_integration/web_contents_delegate_efl.h | 2 + 19 files changed, 1069 insertions(+), 322 deletions(-) create mode 100644 tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc create mode 100644 tizen_src/ewk/efl_integration/browser/notification/notification_helper.h diff --git a/packaging/chromium-efl.spec b/packaging/chromium-efl.spec index 068b3b6..9df53bb 100644 --- a/packaging/chromium-efl.spec +++ b/packaging/chromium-efl.spec @@ -51,6 +51,7 @@ BuildRequires: binutils-gold BuildRequires: bison, edje-tools, expat-devel, flex, gettext, gperf, libcap-devel BuildRequires: libjpeg-turbo-devel, ninja, perl, python3, python3-xml, which BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-appfw-app-manager) BuildRequires: pkgconfig(capi-location-manager) BuildRequires: pkgconfig(capi-media-audio-io) BuildRequires: pkgconfig(capi-media-camera) @@ -93,6 +94,7 @@ BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(libxslt) BuildRequires: pkgconfig(minizip) BuildRequires: pkgconfig(mm-player) +BuildRequires: pkgconfig(notification) BuildRequires: pkgconfig(nspr) BuildRequires: pkgconfig(nss) BuildRequires: pkgconfig(scim) diff --git a/tizen_src/build/BUILD.gn b/tizen_src/build/BUILD.gn index 2b26bb3..14ac742 100644 --- a/tizen_src/build/BUILD.gn +++ b/tizen_src/build/BUILD.gn @@ -198,6 +198,19 @@ config("capi-appfw-application-public") { } } +config("capi-appfw-app-manager") { + if (is_tizen) { + ldflags = [ "-lcapi-appfw-app-manager" ] + } +} + +tizen_pkg_config("libcapi-appfw-app-manager") { + packages = [] + if (is_tizen) { + packages = [ "capi-appfw-app-manager" ] + } +} + config("capi-location-manager") { if (is_tizen) { ldflags = [ "-lcapi-location-manager" ] @@ -505,6 +518,19 @@ config("mm-player-public") { } } +config("notification") { + if (is_tizen) { + ldflags = [ "-lnotification" ] + } +} + +tizen_pkg_config("libnotification") { + packages = [] + if (is_tizen) { + packages = [ "notification" ] + } +} + config("security-manager") { if (is_tizen) { ldflags = [ "-lsecurity-manager-client" ] diff --git a/tizen_src/chromium_impl/content/common/paths_efl.cc b/tizen_src/chromium_impl/content/common/paths_efl.cc index 27efdf2..1e31cef 100644 --- a/tizen_src/chromium_impl/content/common/paths_efl.cc +++ b/tizen_src/chromium_impl/content/common/paths_efl.cc @@ -16,20 +16,29 @@ #if defined(OS_TIZEN) #include +#include #include + +#include "base/logging.h" #endif namespace { + #if defined(OS_TIZEN) const base::FilePath::CharType kDataPath[] = FILE_PATH_LITERAL(DATA_DIR); const base::FilePath::CharType kExePath[] = FILE_PATH_LITERAL(EXE_DIR); const base::FilePath::CharType kApplicationDataDir[] = FILE_PATH_LITERAL("data"); const base::FilePath::CharType kApplicationCacheDir[] = FILE_PATH_LITERAL("cache"); +const base::FilePath::CharType kChromiumLibPath[] = + FILE_PATH_LITERAL("lib/" CHROMIUM_IMPL_LIB_FILE); +const base::FilePath::CharType kNotificationIconDir[] = FILE_PATH_LITERAL("noti"); #endif + #if !defined(EWK_BRINGUP) // FIXME: m67 bringup // FIXME: EWK_BRINGUP definition should be removed. const base::FilePath::CharType kLocalePath[] = FILE_PATH_LITERAL(LOCALE_DIR); #endif // !defined(EWK_BRINGUP) + const base::FilePath::CharType kEdjePath[] = FILE_PATH_LITERAL(EDJE_DIR); const base::FilePath::CharType kApplicationName[] = FILE_PATH_LITERAL("chromium-efl"); const base::FilePath::CharType kApplicationDataBaseDir[] = FILE_PATH_LITERAL("db"); @@ -46,6 +55,20 @@ bool GetDirAppDataTizen(base::FilePath& result) { return true; } +bool GetDirSharedDataTizen(base::FilePath& result) { + char* buffer = app_get_shared_data_path(); + + if (!buffer) { + LOG(ERROR) << "Failed to get shared/data path. " + << get_error_message(get_last_result()); + return false; + } + + result = base::FilePath(buffer); + free(buffer); + return true; +} + bool GetDirChromiumPrivateTizen(base::FilePath& result) { std::unique_ptr data_path(app_get_data_path()); if (data_path) { @@ -177,6 +200,17 @@ bool PathProvider(int key, base::FilePath* result) { return false; cur = cur.Append(kApplicationDataBaseDir); break; +#if defined(OS_TIZEN) + case DIR_SHARED: + if (!GetDirSharedDataTizen(cur)) + return false; + break; + case DIR_SHARED_NOTI_ICON: + if (!base::PathService::Get(DIR_SHARED, &cur)) + return false; + cur = cur.Append(kNotificationIconDir); + break; +#endif default: return false; } diff --git a/tizen_src/chromium_impl/content/common/paths_efl.h b/tizen_src/chromium_impl/content/common/paths_efl.h index 1aaaabf..5a4c3b2 100644 --- a/tizen_src/chromium_impl/content/common/paths_efl.h +++ b/tizen_src/chromium_impl/content/common/paths_efl.h @@ -18,6 +18,8 @@ enum { DIR_DOWNLOADS, DIR_DOWNLOAD_IMAGE, DIR_LOCALE, + DIR_SHARED, + DIR_SHARED_NOTI_ICON, PATH_END }; diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index e956ddf..9494d43 100644 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -58,6 +58,8 @@ shared_library("chromium-ewk") { configs += [ "//tizen_src/build:ui-gadget" ] configs += [ "//tizen_src/build:libui-gadget" ] public_configs += [ "//tizen_src/build:ui-gadget-public" ] + configs += [ "//tizen_src/build:notification" ] + configs += [ "//tizen_src/build:libnotification" ] deps = [ "//base/:base_static", "//components/autofill/content/browser", @@ -120,6 +122,8 @@ shared_library("chromium-ewk") { "browser/sound_effect.h", ] deps += [ "//cc:cc" ] + configs += [ "//tizen_src/build:capi-appfw-app-manager" ] + configs += [ "//tizen_src/build:libcapi-appfw-app-manager" ] } else { if (use_gio) { configs += [ "//build/linux:gio_config" ] @@ -148,11 +152,6 @@ shared_library("chromium-ewk") { public_configs += [ "../../build:capi-system-device-public" ] } - sources = [ - "browser/notification/notification_controller_efl.cc", - "browser/notification/notification_controller_efl.h", - ] - if (tizen_autofill_support) { defines = [ "TIZEN_AUTOFILL_SUPPORT=true" ] } @@ -179,7 +178,7 @@ shared_library("chromium-ewk") { libs = [ "atomic" ] } - sources += [ + sources = [ "authentication_challenge_popup.cc", "authentication_challenge_popup.h", "autofill_popup_view_efl.cc", @@ -301,6 +300,10 @@ shared_library("chromium-ewk") { "browser/inputpicker/InputPicker.h", "browser/inputpicker/color_chooser_efl.cc", "browser/inputpicker/color_chooser_efl.h", + "browser/notification/notification_controller_efl.cc", + "browser/notification/notification_controller_efl.h", + "browser/notification/notification_helper.cc", + "browser/notification/notification_helper.h", "browser/password_manager/password_manager_client_efl.cc", "browser/password_manager/password_manager_client_efl.h", "browser/password_manager/password_store_factory.cc", diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc b/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc index de7810d..4ff2e6b 100644 --- a/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc @@ -4,84 +4,474 @@ #include "browser/notification/notification_controller_efl.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "common/web_contents_utils.h" +#include "content/common/paths_efl.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/persistent_notification_status.h" #include "eweb_view.h" +#include "private/ewk_context_private.h" #include "private/ewk_notification_private.h" +#include "public/ewk_context.h" +#include "public/ewk_context_internal.h" +#include "third_party/leveldatabase/src/include/leveldb/db.h" +#include "ui/gfx/codec/png_codec.h" + +#if defined(OS_TIZEN) +#include +#include +#include +#endif using web_contents_utils::WebViewFromWebContents; -using namespace blink::mojom; +using blink::mojom::PermissionStatus; namespace content { -NotificationControllerEfl::NotificationControllerEfl() - : notification_show_callback_(nullptr) - , notification_cancel_callback_(nullptr) - , notification_callback_user_data_(nullptr) - , weak_factory_(this) -{ +static const char kPermissionDatabaseName[] = "permissions_db"; + +#if defined(OS_TIZEN) +bool SetNotificationImage(notification_h noti, + notification_image_type_e type, + const SkBitmap& bitmap, + const base::FilePath& path) { + std::vector data; + if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data)) { + LOG(ERROR) << "Bitmap color type " << bitmap.colorType(); + return false; + } + + FILE* f = base::OpenFile(path, "wb"); + if (!f) + return false; + + size_t written = fwrite(&*data.begin(), 1, data.size(), f); + base::CloseFile(f); + if (written == data.size()) { + if (notification_set_image(noti, type, path.value().data()) == + NOTIFICATION_ERROR_NONE) { + return true; + } + LOG(ERROR) << "Failed to set notification image." << path.value(); + } else { + LOG(ERROR) << "Failed to write image file. " << path.value() + << ", written size:" << written << "/" << data.size(); + } + base::DeleteFile(path); + return false; } -NotificationControllerEfl::~NotificationControllerEfl() { - // notifications_map_.Clear(); +void RemoveImageFiles(const std::string& tag) { + base::FilePath image_path; + if (!base::PathService::Get(PathsEfl::DIR_SHARED_NOTI_ICON, &image_path)) { + LOG(ERROR) << "Failed to retrieve the notification resource path"; + return; + } + + if (tag.empty()) { + // Remove all unused icons. + base::FileEnumerator enumerator(image_path, false, + base::FileEnumerator::FILES); + for (base::FilePath file = enumerator.Next(); !file.empty(); + file = enumerator.Next()) { + const std::string file_str = file.BaseName().value(); + size_t dot_at = file_str.find_last_of('.'); + if (dot_at != std::string::npos) { + notification_h noti = + notification_load_by_tag(file_str.substr(0, dot_at).c_str()); + if (noti) + notification_free(noti); + else if (!base::DeleteFile(file)) + LOG(ERROR) << "Failed to delete icon. " << file_str; + } + } + return; + } + + if (!base::DeleteFile(image_path.AppendASCII(tag + ".icon"))) { + LOG(ERROR) << "Failed to delete icon. " + << image_path.AppendASCII(tag).value(); + } + if (!base::DeleteFile(image_path.AppendASCII(tag + ".badge"))) { + LOG(ERROR) << "Failed to delete badge. " + << image_path.AppendASCII(tag).value(); + } } -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -void NotificationControllerEfl::NotificationAdd( - uint64_t notification_id, - const GURL& origin, - const std::u16string& replace_id, - std::unique_ptr delegate) { - NotificationData* new_notification( - new NotificationData(origin, replace_id, std::move(delegate))); - notifications_map_.AddWithID(new_notification, notification_id); + +static void NotificationEventCallback(notification_h noti, + int event_type, + void* userdata) { + auto thiz = static_cast(userdata); + int notification_priv_id = NOTIFICATION_PRIV_ID_NONE; + int notification_ret_val = NOTIFICATION_ERROR_NONE; + + notification_ret_val = + notification_get_id(noti, nullptr, ¬ification_priv_id); + if (notification_ret_val != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << " Can't get notification ID " << notification_ret_val; + return; + } + + uint64_t notification_id = + thiz->default_callback()->FindNotificationID(notification_priv_id); + bool ret = false; + if (notification_id) { + if (event_type == NOTIFICATION_EVENT_TYPE_PRESSED) { + ret = thiz->notification_helper()->NotificationClicked(notification_id); + } else { + ret = thiz->notification_helper()->NotificationClosed( + notification_id, + event_type != NOTIFICATION_EVENT_TYPE_HIDDEN_BY_TIMEOUT); + } + } + + const char* tag = nullptr; + notification_ret_val = notification_get_tag(noti, &tag); + if (tag && notification_ret_val == NOTIFICATION_ERROR_NONE) + RemoveImageFiles(tag); + + // TODO: Need to check the invalid case. + if (!ret) { + LOG(ERROR) << "Failed to handle notification, id:" << notification_id + << ", event_type:" << event_type; + } } -bool NotificationControllerEfl::NotificationClosed(uint64_t notification_id, - bool by_user) { +#endif // defined(OS_TIZEN) + +PermissionHandler::PermissionHandler() {} - NotificationData* saved_data = notifications_map_.Lookup(notification_id); - if (!saved_data) +PermissionHandler::~PermissionHandler() {} + +bool PermissionHandler::InitializePermissionDatabase(bool clear) { + if (permissions_db_) + return true; + + base::FilePath db_path; + if (!base::PathService::Get(PathsEfl::WEB_DATABASE_DIR, &db_path)) { + LOG(ERROR) << "Could not get web database directory."; return false; + } - saved_data->notification_delegate->NotificationClosed(); - notifications_map_.Remove(notification_id); - return true; + db_path = db_path.Append(FILE_PATH_LITERAL(kPermissionDatabaseName)); + if (clear) + base::DeletePathRecursively(db_path); + + leveldb::DB* db; + leveldb::Options options; + options.create_if_missing = true; + leveldb::Status status = + leveldb::DB::Open(options, db_path.AsUTF8Unsafe(), &db); + if (!status.ok()) { + LOG(ERROR) << "Could not open permissions db. " << db_path.AsUTF8Unsafe(); + return false; + } + + permissions_db_.reset(db); + // Load permissions from db. + if (!clear) { + std::unique_ptr it( + permissions_db_->NewIterator(leveldb::ReadOptions())); + for (it->SeekToFirst(); it->Valid(); it->Next()) { + GURL origin(it->key().ToString()); + bool allowed = *(const bool*)(it->value().data()); + permissions_map_[origin] = allowed; + } + } + + return (permissions_db_ != nullptr); } -#endif -void NotificationControllerEfl::NotificationCancelled(uint64_t notification_id) { - // NotificationClosed(notification_id, false); - if (notification_cancel_callback_) { - notification_cancel_callback_(notification_id, notification_callback_user_data_); + +void PermissionHandler::PutPermission(const GURL& origin, bool allowed) { + base::AutoLock locker(permissions_mutex_); + auto it = permissions_map_.find(origin); + if (it == permissions_map_.end() || it->second != allowed) { + permissions_map_[origin] = allowed; + if (InitializePermissionDatabase()) { + permissions_db_->Put(leveldb::WriteOptions(), + origin.possibly_invalid_spec(), + leveldb::Slice((const char*)&allowed, sizeof(bool))); + } } } -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -bool NotificationControllerEfl::NotificationClicked(uint64_t notification_id) { - NotificationData* saved_data = notifications_map_.Lookup(notification_id); - if (!saved_data) + +PermissionStatus PermissionHandler::CheckPermissionForOrigin( + const GURL& origin) { + base::AutoLock locker(permissions_mutex_); + InitializePermissionDatabase(); + PermissionStatus status = PermissionStatus::ASK; + auto it = permissions_map_.find(origin); + if (it != permissions_map_.end()) + status = it->second ? PermissionStatus::GRANTED : PermissionStatus::DENIED; + return status; +} + +void PermissionHandler::ClearPermissions() { + base::AutoLock locker(permissions_mutex_); + permissions_map_.clear(); + permissions_db_.reset(); + InitializePermissionDatabase(true); +} + +void PermissionHandler::RemovePermissions(Eina_List* origins) { + Eina_List* list = nullptr; + void* data = nullptr; + base::AutoLock locker(permissions_mutex_); + if (eina_list_count(origins) > 0) + InitializePermissionDatabase(); + + EINA_LIST_FOREACH(origins, list, data) { + _Ewk_Security_Origin* origin = static_cast<_Ewk_Security_Origin*>(data); + if (permissions_map_.erase(origin->GetURL()) && permissions_db_) { + permissions_db_->Delete(leveldb::WriteOptions(), + origin->GetURL().possibly_invalid_spec()); + } + } +} + +void PermissionHandler::RequestPermission( + EWebView* web_view, + const GURL& requesting_frame, + base::OnceCallback result_callback) { + if (!web_view) { + LOG(ERROR) << "Dropping PermissionNotification request caused by lack " + "of the WebView."; + std::move(result_callback).Run(PermissionStatus::DENIED); + return; + } + + if (!web_view->IsNotificationPermissionCallbackSet()) { + LOG(ERROR) << "Dropping PermissionNotification request caused by lack " + "of the Notification Permission Callback."; + std::move(result_callback).Run(PermissionStatus::DENIED); + return; + } + + blink::mojom::PermissionStatus web_notification_permission = + CheckPermissionForOrigin(requesting_frame); + + switch (web_notification_permission) { + case PermissionStatus::LAST: + { + std::unique_ptr notification_permission( + new Ewk_Notification_Permission_Request(std::move(result_callback), + requesting_frame)); + web_view->InvokeNotificationPermissionCallback( + notification_permission.get()); + // If policy is suspended, the API takes over the policy object lifetime + // and policy will be deleted after decision is made. + if (notification_permission->IsSuspended()) + ignore_result(notification_permission.release()); + } + break; + case PermissionStatus::GRANTED: + std::move(result_callback).Run(PermissionStatus::GRANTED); + break; + default: + std::move(result_callback).Run(PermissionStatus::DENIED); + } +} + +DefaultCallback::DefaultCallback() {} + +DefaultCallback::~DefaultCallback() {} + +#if defined(OS_TIZEN) +uint64_t DefaultCallback::FindNotificationID(int notification_priv_id) { + for (auto it = key_mapper_.begin(); it != key_mapper_.end(); it++) { + if (it->second == notification_priv_id) + return it->first; + } + + LOG(ERROR) << "Can't find notification ID " << notification_priv_id; + return 0; +} +#endif // defined(OS_TIZEN) + +bool DefaultCallback::ShowCallback(uint64_t tag, + const std::string& notification_id, + const GURL& origin, + const char* title, + const char* body, + const SkBitmap& icon, + const SkBitmap& badge, + bool is_persistent) { +#if defined(OS_TIZEN) + auto found = key_mapper_.find(tag); + if (found != key_mapper_.end()) + CancelCallback(tag); + + notification_h noti_h = + notification_new(NOTIFICATION_TYPE_NOTI, NOTIFICATION_GROUP_ID_DEFAULT, + NOTIFICATION_PRIV_ID_NONE); + if (!noti_h) { + LOG(ERROR) << "Can't create notification handle."; return false; + } + + std::unique_ptr::type, + decltype(notification_free)*> + auto_release{noti_h, notification_free}; + + // Set notification title. + int ret = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_TITLE, title, + nullptr, NOTIFICATION_VARIABLE_TYPE_NONE); + if (ret != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << "Can't set title" << ret; + return false; + } + + // Set notification content. + ret = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_CONTENT, body, + nullptr, NOTIFICATION_VARIABLE_TYPE_NONE); + if (ret != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << "Can't set content" << ret; + return false; + } + + base::FilePath noti_path; + if (base::PathService::Get(PathsEfl::DIR_SHARED_NOTI_ICON, ¬i_path)) { + bool has_images = false; + const std::string tag_str = std::to_string(tag); + + if (SetNotificationImage(noti_h, NOTIFICATION_IMAGE_TYPE_ICON, icon, + noti_path.AppendASCII(tag_str + ".icon"))) { + has_images = true; + } + if (SetNotificationImage(noti_h, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + badge, + noti_path.AppendASCII(tag_str + ".badge"))) { + has_images = true; + } + + // Set a tag to remove icon images after closing notification. + if (has_images) + notification_set_tag(noti_h, tag_str.c_str()); + } else { + LOG(ERROR) << "Failed to retrieve the notification resource path"; + } + + // Set notification type. + ret = notification_set_display_applist( + noti_h, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY | + NOTIFICATION_DISPLAY_APP_TICKER | + NOTIFICATION_DISPLAY_APP_INDICATOR); + if (ret != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << "notification_set_display_applist is failed with err " << ret; + return false; + } - saved_data->notification_delegate->NotificationClick(); - notifications_map_.Remove(notification_id); + if (is_persistent) { + app_control_h app_control = nullptr; + ret = app_control_create(&app_control); + if (ret != APP_CONTROL_ERROR_NONE) { + LOG(ERROR) << "app_control_create is failed with err " << ret; + return false; + } + + std::unique_ptr::type, + decltype(app_control_destroy)*> + auto_release{app_control, app_control_destroy}; + + char* app_id = nullptr; + int ret = app_manager_get_app_id(getpid(), &app_id); + if (ret != APP_MANAGER_ERROR_NONE) { + LOG(ERROR) << "app_manager_get_app_id is failed with err " << ret; + return false; + } + + app_control_set_app_id(app_control, app_id); + if (app_id) + free(app_id); + + app_control_add_extra_data(app_control, APP_CONTROL_DATA_BACKGROUND_LAUNCH, + "enable"); + app_control_add_extra_data(app_control, "notification_id", + notification_id.c_str()); + app_control_add_extra_data(app_control, "notification_origin", + origin.possibly_invalid_spec().c_str()); + + ret = notification_set_launch_option( + noti_h, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void*)app_control); + if (ret != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << "notification_set_launch_option is failed with err " << ret; + return false; + } + } + // TODO: If application has been killed, currently there is no way to launch + // application to run service worker when notification closed. If platform + // support new API, we don't need to use |notification_post_with_event_cb|. + ret = + notification_post_with_event_cb(noti_h, NotificationEventCallback, this); + if (ret != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << "notification_post_with_event_cb is failed with err " << ret; + return false; + } + + int notification_priv_id = NOTIFICATION_PRIV_ID_NONE; + ret = notification_get_id(noti_h, nullptr, ¬ification_priv_id); + if (ret != NOTIFICATION_ERROR_NONE) { + LOG(ERROR) << "Can't get notification ID " << ret; + return false; + } + + key_mapper_[tag] = notification_priv_id; return true; +#else + return false; +#endif // defined(OS_TIZEN) } -bool NotificationControllerEfl::NotificationDisplayed(uint64_t notification_id) { - NotificationData* saved_data = notifications_map_.Lookup(notification_id); - if (!saved_data) +bool DefaultCallback::CancelCallback(uint64_t tag) { +#if defined(OS_TIZEN) + auto found = key_mapper_.find(tag); + if (found == key_mapper_.end()) { + LOG(ERROR) << "Can't find notification."; return false; + } - saved_data->notification_delegate->NotificationDisplayed(); + notification_delete_by_priv_id(nullptr, NOTIFICATION_TYPE_NOTI, + found->second); + key_mapper_.erase(found); return true; +#else + return false; +#endif // defined(OS_TIZEN) } + +NotificationControllerEfl::NotificationControllerEfl() + : permission_handler_(std::make_unique()), + default_callback_(std::make_unique()), + notification_helper_(std::make_unique()) {} + +NotificationControllerEfl::~NotificationControllerEfl() { +#if defined(OS_TIZEN) + RemoveImageFiles(std::string()); #endif +} -blink::mojom::PermissionStatus NotificationControllerEfl::CheckPermissionOnIOThread( +void NotificationControllerEfl::NotificationCancelled( + uint64_t notification_id) { + notification_helper_->NotificationClosed(notification_id, false); + if (notification_cancel_callback_) { + notification_cancel_callback_(notification_id, + notification_callback_user_data_); + } else { + default_callback_->CancelCallback(notification_id); + } +} + +blink::mojom::PermissionStatus +NotificationControllerEfl::CheckPermissionOnIOThread( ResourceContext* resource_context, const GURL& origin, int render_process_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return CheckPermissionForOrigin(origin); + return permission_handler_->CheckPermissionForOrigin(origin); } void NotificationControllerEfl::DisplayNotification( @@ -90,54 +480,63 @@ void NotificationControllerEfl::DisplayNotification( const GURL& document_url, const blink::PlatformNotificationData& notification_data, const blink::NotificationResources& notification_resources) { -#if !defined(EWK_BRINGUP) // FIXME: m76 bringup - BrowserContextEfl* browser_context_efl = - static_cast(browser_context); - CHECK(browser_context_efl); - EWebContext* ctx = browser_context_efl->WebContext(); - CHECK(ctx); - - bool has_callbacks = ctx->HasNotificationCallbacks() - || (notification_show_callback_ && notification_cancel_callback_); - if (!has_callbacks) { - delegate->NotificationClosed(); + if (!web_view_ || !web_view_->context() || + !web_view_->context()->browser_context()) { + LOG(ERROR) << "Dropping DisplayNotification request caused by lack " + "of the WebView."; return; } - uint64_t replaceUniqueId = 0; - if (!notification_data.tag.empty() && - IsNotificationPresent(origin, - base::UTF8ToUTF16(notification_data.tag), replaceUniqueId)) { - if (!ctx->NotificationCancelCallback(replaceUniqueId)) - NotificationCancelled(replaceUniqueId); - else - NotificationClosed(replaceUniqueId, false); + EWebContext* ctx = web_view_->context()->browser_context()->WebContext(); + CHECK(ctx); + + bool has_callbacks = + ctx->HasNotificationCallbacks() || + (notification_show_callback_ && notification_cancel_callback_); + + uint64_t replace_unique_id = 0; + if (notification_helper_->IsNotificationPresent(origin, notification_id, + replace_unique_id)) { + if (!has_callbacks) + default_callback_->CancelCallback(replace_unique_id); + else if (!ctx->NotificationCancelCallback(replace_unique_id)) + NotificationCancelled(replace_unique_id); + + notification_helper_->NotificationClosed(replace_unique_id, false); } - uint64_t notificationUniqueId = reinterpret_cast(delegate.get()); - NotificationAdd(notificationUniqueId, origin, - base::UTF8ToUTF16(notification_data.tag), - std::move(delegate)); + uint64_t notification_unique_id = base::Hash(notification_id); - if (cancel_callback) - *cancel_callback = - base::BindOnce(&NotificationControllerEfl::NotificationCancelled, - weak_factory_.GetWeakPtr(), notificationUniqueId); + notification_helper_->SetNotification(origin, notification_id, + notification_unique_id); - Ewk_Notification* notification = - new Ewk_Notification(base::UTF16ToUTF8(notification_data.body), - notification_data.tag, - base::UTF16ToUTF8(notification_data.title), - notification_resources.notification_icon, - notification_data.silent, - notificationUniqueId, - origin); + Ewk_Notification notification(base::UTF16ToUTF8(notification_data.body), + base::UTF16ToUTF8(notification_data.title), + notification_resources.notification_icon, + notification_data.silent, + notification_unique_id, origin); - if (!ctx->NotificationShowCallback(notification)) - notification_show_callback_(notification, notification_callback_user_data_); + if (!has_callbacks) { + default_callback_->ShowCallback(notification_unique_id, notification_id, + origin, notification.GetTitle(), + notification.GetBody(), + notification_resources.notification_icon, + notification_resources.badge, false); + notification_helper_->NotificationDisplayed(notification_unique_id); + } else if (!ctx->NotificationShowCallback(¬ification)) { + notification_show_callback_(¬ification, + notification_callback_user_data_); + } +} - delete notification; -#endif +void NotificationControllerEfl::CloseNotification( + const std::string& notification_id) { + NOTIMPLEMENTED(); +} + +int64_t NotificationControllerEfl::ReadNextPersistentNotificationId() { + NOTIMPLEMENTED(); + return -1; } void NotificationControllerEfl::DisplayPersistentNotification( @@ -146,132 +545,114 @@ void NotificationControllerEfl::DisplayPersistentNotification( const GURL& origin, const blink::PlatformNotificationData& notification_data, const blink::NotificationResources& notification_resources) { - NOTIMPLEMENTED(); -} - -void NotificationControllerEfl::ClosePersistentNotification( - const std::string& notification_id) { - NOTIMPLEMENTED(); -} + if (!web_view_ || !web_view_->context() || + !web_view_->context()->browser_context()) { + LOG(ERROR) << "Dropping DisplayNotification request caused by lack " + "of the WebView."; + return; + } + EWebContext* ctx = web_view_->context()->browser_context()->WebContext(); + CHECK(ctx); -void NotificationControllerEfl::SetPermissionForNotification( - Ewk_Notification_Permission_Request* notification, bool isAllowed) { + bool has_callbacks = + ctx->HasNotificationCallbacks() || + (notification_show_callback_ && notification_cancel_callback_); - EWebView* wv = EWebView::FromEvasObject(notification->GetWebviewEvasObject()); - DCHECK(wv); - RenderViewHost* render_view_host = - wv->web_contents().GetRenderViewHost(); + uint64_t replace_unique_id = 0; + if (notification_helper_->IsPersistentNotificationPresent( + origin, notification_id, replace_unique_id)) { + if (!has_callbacks) + default_callback_->CancelCallback(replace_unique_id); + else if (!ctx->NotificationCancelCallback(replace_unique_id)) + NotificationCancelled(replace_unique_id); - if (render_view_host) { - GURL origin = notification->GetSecurityOrigin()->GetURL(); - // save decision in permissions map - permissions_mutex_.Acquire(); - permissions_map_[origin] = isAllowed; - permissions_mutex_.Release(); + notification_helper_->NotificationClosed(replace_unique_id, false); } -} -void NotificationControllerEfl::AddPermission(const GURL origin, - bool allowed) { - base::AutoLock locker(permissions_mutex_); - permissions_map_[origin] = allowed; -} + uint64_t notification_unique_id = base::Hash(notification_id); -blink::mojom::PermissionStatus -NotificationControllerEfl::CheckPermissionForOrigin( - const GURL &origin) const { - base::AutoLock locker(permissions_mutex_); - std::map::const_iterator it = permissions_map_.find(origin); - if (it == permissions_map_.end()) - return blink::mojom::PermissionStatus::ASK; - return it->second ? - blink::mojom::PermissionStatus::GRANTED : - blink::mojom::PermissionStatus::DENIED; + notification_helper_->SetPersistentNotification( + web_view_->context()->browser_context(), origin, notification_id, + notification_unique_id); + + Ewk_Notification notification(base::UTF16ToUTF8(notification_data.body), + base::UTF16ToUTF8(notification_data.title), + notification_resources.notification_icon, + notification_data.silent, + notification_unique_id, origin); + + if (!has_callbacks) { + default_callback_->ShowCallback(notification_unique_id, notification_id, + origin, notification.GetTitle(), + notification.GetBody(), + notification_resources.notification_icon, + notification_resources.badge, true); + } else if (!ctx->NotificationShowCallback(¬ification)) { + notification_show_callback_(¬ification, + notification_callback_user_data_); + } } -void NotificationControllerEfl::ClearPermissions() { - base::AutoLock locker(permissions_mutex_); - permissions_map_.clear(); +void NotificationControllerEfl::ClosePersistentNotification( + const std::string& notification_id) { + NOTIMPLEMENTED(); } -void NotificationControllerEfl::RemovePermissions(Eina_List* origins) { - Eina_List* list = NULL; - void* data = NULL; - base::AutoLock locker(permissions_mutex_); - EINA_LIST_FOREACH(origins, list, data) { - _Ewk_Security_Origin* origin = static_cast<_Ewk_Security_Origin*>(data); - permissions_map_.erase(origin->GetURL()); - } +void NotificationControllerEfl::GetDisplayedNotifications( + DisplayedNotificationsCallback callback) { + NOTIMPLEMENTED(); } -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -bool NotificationControllerEfl::IsNotificationPresent( - const GURL& origin, - const std::u16string& replaceid, - uint64_t& notification_id) { - IDMap::const_iterator it(¬ifications_map_); - for (; !it.IsAtEnd(); it.Advance()) { - if (replaceid == it.GetCurrentValue()->replace_id && - origin.spec() == it.GetCurrentValue()->origin_url) { - notification_id = it.GetCurrentKey(); - return true; - } +void NotificationControllerEfl::SetPermissionForNotification( + Ewk_Notification_Permission_Request* notification, + bool allowed) { + GURL origin = notification->GetSecurityOrigin()->GetURL(); + + if (web_view_) { + Ewk_Notification_Permission permission; + permission.origin = origin.possibly_invalid_spec().c_str(); + permission.allowed = allowed; + web_view_->SmartCallback() + .call(&permission); } - return false; + // Save decision in permissions map. + permission_handler_->PutPermission(origin, allowed); } -#endif void NotificationControllerEfl::RequestPermission( WebContents* web_contents, const GURL& requesting_frame, base::OnceCallback result_callback) { - EWebView* web_view = WebViewFromWebContents(web_contents); - if (!web_view) { - LOG(ERROR) << "Dropping PermissionNotification request caused by lack " - "of the WebView"; - std::move(result_callback).Run(PermissionStatus::DENIED); - return; - } - std::unique_ptr notification_permission( - new Ewk_Notification_Permission_Request(web_view->evas_object(), - std::move(result_callback), - requesting_frame)); - - if (!web_view->IsNotificationPermissionCallbackSet()) { - LOG(ERROR) << "Dropping PermissionNotification request caused by lack " - "of the Notification Permission Callback"; - std::move(result_callback).Run(PermissionStatus::DENIED); - return; - } - - blink::mojom::PermissionStatus web_notification_permission = - CheckPermissionForOrigin(requesting_frame); - if (web_notification_permission == - blink::mojom::PermissionStatus::LAST) { - web_view->InvokeNotificationPermissionCallback( - notification_permission.get()); - // if policy is suspended, the API takes over the policy object lifetime - // and policy will be deleted after decision is made - if (notification_permission->IsSuspended()) { - ignore_result(notification_permission.release()); - return; - } - } else { - if (web_notification_permission == blink::mojom::PermissionStatus::GRANTED) { - std::move(result_callback).Run(PermissionStatus::GRANTED); - } else { - std::move(result_callback).Run(PermissionStatus::DENIED); - } - } + web_view_ = WebViewFromWebContents(web_contents); + permission_handler_->RequestPermission(web_view_, requesting_frame, + std::move(result_callback)); } -void NotificationControllerEfl::SetNotificationCallbacks(Ewk_Notification_Show_Callback show_callback, Ewk_Notification_Cancel_Callback cancel_callback, void* user_data) { +void NotificationControllerEfl::SetNotificationCallbacks( + Ewk_Notification_Show_Callback show_callback, + Ewk_Notification_Cancel_Callback cancel_callback, + void* user_data) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); notification_show_callback_ = show_callback; notification_cancel_callback_ = cancel_callback; notification_callback_user_data_ = user_data; } -}//namespace +void NotificationControllerEfl::ScheduleTrigger(base::Time timestamp) { + NOTIMPLEMENTED(); +} + +base::Time NotificationControllerEfl::ReadNextTriggerTimestamp() { + NOTIMPLEMENTED(); + return base::Time::Max(); +} + +void NotificationControllerEfl::RecordNotificationUkmEvent( + const NotificationDatabaseData& data) { + NOTIMPLEMENTED(); +} + +} // namespace content + diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.h b/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.h index 5292855..19df7a9 100644 --- a/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.h +++ b/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.h @@ -9,85 +9,129 @@ #include -#include "base/containers/id_map.h" -#include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" +#include "browser/notification/notification_helper.h" #include "content/public/browser/platform_notification_service.h" #include "content/public/browser/resource_context.h" #include "public/ewk_notification_internal.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" #include "url/gurl.h" +class EWebView; +class SkBitmap; + +namespace leveldb { +class DB; +} + namespace content { class WebContents; +class BrowserContext; + +class PermissionHandler { + public: + PermissionHandler(); + ~PermissionHandler(); + + // Adds permission to map + void PutPermission(const GURL& origin, bool allowed); + + // Removes all stored permissions + void ClearPermissions(); + + // Removes stored permissions for given origins + void RemovePermissions(Eina_List* origins); + + blink::mojom::PermissionStatus CheckPermissionForOrigin(const GURL& origin); + + void RequestPermission( + EWebView* web_view, + const GURL& requesting_frame, + base::OnceCallback + result_callback); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -// DesktopNotificationDelegate is not defined -struct NotificationData { - const std::string origin_url; - const std::u16string replace_id; - std::unique_ptr notification_delegate; - - NotificationData(const GURL& origin, - const std::u16string& replaceid, - std::unique_ptr delegate) - : origin_url(origin.spec()), - replace_id(replaceid), - notification_delegate(std::move(delegate)) {} + private: + bool InitializePermissionDatabase(bool clear = false); + + std::map permissions_map_; + mutable base::Lock permissions_mutex_; + std::unique_ptr permissions_db_; }; -#endif // !defined(EWK_BRINGUP) -class NotificationControllerEfl: public PlatformNotificationService { + +class DefaultCallback { public: - NotificationControllerEfl(); - ~NotificationControllerEfl(); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - // DesktopNotificationDelegate is not defined - // Adds a new notification received from engine to a list - void NotificationAdd(uint64_t notification_id, - const GURL& origin, - const std::u16string& replace_id, - std::unique_ptr delegate); - - bool NotificationClosed(uint64_t notification_id, bool by_user); + DefaultCallback(); + ~DefaultCallback(); +#if defined(OS_TIZEN) + uint64_t FindNotificationID(int notification_priv_id); #endif + bool ShowCallback(uint64_t tag, + const std::string& notification_id, + const GURL& origin, + const char* title, + const char* body, + const SkBitmap& icon, + const SkBitmap& badge, + bool is_persistent); + bool CancelCallback(uint64_t tag); + + private: + std::map key_mapper_; +}; + +class NotificationControllerEfl : public PlatformNotificationService { + public: + NotificationControllerEfl(); + ~NotificationControllerEfl() override; + void NotificationCancelled(uint64_t notification_id); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - // DesktopNotificationDelegate is not defined + + bool NotificationClosed(uint64_t notification_id, bool by_user) { + return notification_helper_->NotificationClosed(notification_id, by_user); + } + // Notify engine when user clicked on the notification - bool NotificationClicked(uint64_t notification_id); + bool NotificationClicked(uint64_t notification_id) { + return notification_helper_->NotificationClicked(notification_id); + } + + bool PersistentNotificationClicked(BrowserContext* browser_context, + const char* id, + const char* origin) { + return notification_helper_->PersistentNotificationClicked(browser_context, + id, origin); + } + + bool NotificationDisplayed(uint64_t notification_id) { + return notification_helper_->NotificationDisplayed(notification_id); + } - // Notification engine that notification was displayed - bool NotificationDisplayed(uint64_t notification_id); -#endif // sets the permission for a particular pending notification void SetPermissionForNotification( Ewk_Notification_Permission_Request* notification, - bool isAllowed); + bool allowed); // Adds permission to map - void AddPermission(const GURL origin, bool allowed); + void PutPermission(const GURL& origin, bool allowed) { + permission_handler_->PutPermission(origin, allowed); + } // Removes all stored permissions - void ClearPermissions(); + void ClearPermissions() { permission_handler_->ClearPermissions(); } // Removes stored permissions for given origins - void RemovePermissions(Eina_List* origins); + void RemovePermissions(Eina_List* origins) { + permission_handler_->RemovePermissions(origins); + } -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - // DesktopNotificationDelegate is not defined - // Checks if the notification is already present. - // If present returns the notification id of the notification else false - bool IsNotificationPresent(const GURL& origin, - const std::u16string& replaceid, - uint64_t& notification_id); -#endif void RequestPermission( WebContents* web_contents, const GURL& requesting_frame, base::OnceCallback result_callback); void SetNotificationCallbacks(Ewk_Notification_Show_Callback show_callback, - Ewk_Notification_Cancel_Callback close_callback, void* user_data); + Ewk_Notification_Cancel_Callback close_callback, + void* user_data); // Checks if |origin| has permission to display Web Notifications. This method // exists to serve the synchronous IPC required by the Notification.permission @@ -109,6 +153,10 @@ class NotificationControllerEfl: public PlatformNotificationService { const blink::PlatformNotificationData& notification_data, const blink::NotificationResources& notification_resources) override; + void CloseNotification(const std::string& notification_id) override; + + int64_t ReadNextPersistentNotificationId() override; + // Displays the persistent notification described in |notification_data| to // the user. This method must be called on the UI thread. void DisplayPersistentNotification( @@ -127,27 +175,31 @@ class NotificationControllerEfl: public PlatformNotificationService { // Writes the ids of all currently displaying persistent notifications for the // given |browser_context| to |displayed_notifications|. Returns whether the // platform is able to provide such a set. - bool GetDisplayedPersistentNotifications( - std::set* displayed_notifications); + void GetDisplayedNotifications( + DisplayedNotificationsCallback callback) override; + + void ScheduleTrigger(base::Time timestamp) override; + base::Time ReadNextTriggerTimestamp() override; + void RecordNotificationUkmEvent( + const content::NotificationDatabaseData& data) override; + DefaultCallback* default_callback() { return default_callback_.get(); } + NotificationHelper* notification_helper() { + return notification_helper_.get(); + } private: - blink::mojom::PermissionStatus CheckPermissionForOrigin( - const GURL &origin) const; - - // IDMap notifications_map_; // This stores - // the notifications displayed to the user - std::map permissions_map_; - mutable base::Lock permissions_mutex_; - - Ewk_Notification_Show_Callback notification_show_callback_; - Ewk_Notification_Cancel_Callback notification_cancel_callback_; - void* notification_callback_user_data_; + Ewk_Notification_Show_Callback notification_show_callback_ = nullptr; + Ewk_Notification_Cancel_Callback notification_cancel_callback_ = nullptr; + void* notification_callback_user_data_ = nullptr; - base::WeakPtrFactory weak_factory_; + EWebView* web_view_ = nullptr; + std::unique_ptr permission_handler_; + std::unique_ptr default_callback_; + std::unique_ptr notification_helper_; DISALLOW_COPY_AND_ASSIGN(NotificationControllerEfl); }; -} //namespace +} // namespace content #endif // NOTIFICATION_CONTROLLER_EFL_H diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc b/tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc new file mode 100644 index 0000000..92492b9 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/notification/notification_helper.cc @@ -0,0 +1,156 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/notification/notification_helper.h" + +#include "base/bind.h" +#include "base/callback_forward.h" +#include "base/callback_helpers.h" +#include "base/logging.h" +#include "content/public/browser/notification_event_dispatcher.h" + +namespace content { + +void OnEventDispatchComplete(PersistentNotificationStatus status) { + LOG(INFO) << "Notifications.PersistentWebNotificationClickResult " + << (int)status; +} + +NotificationHelper::NotificationHelper() { + notification_event_dispatcher_ = + content::NotificationEventDispatcher::GetInstance(); +} + +NotificationHelper::~NotificationHelper() { + notifications_map_.clear(); + persistent_notification_map_.clear(); +} + +bool NotificationHelper::NotificationClosed(uint64_t notification_id, + bool by_user) { + auto itr = notifications_map_.find(notification_id); + if (itr != notifications_map_.end()) { + notification_event_dispatcher_->DispatchNonPersistentCloseEvent( + itr->second.non_persistent_id, base::DoNothing()); + notifications_map_.erase(notification_id); + return true; + } + + auto it = persistent_notification_map_.find(notification_id); + if (it != persistent_notification_map_.end()) { + notification_event_dispatcher_->DispatchNotificationCloseEvent( + it->second.browser_context, it->second.persistent_id, it->second.origin, + by_user, base::BindOnce(OnEventDispatchComplete)); + persistent_notification_map_.erase(notification_id); + return true; + } + + return false; +} + +bool NotificationHelper::PersistentNotificationClicked( + BrowserContext* browser_context, + const char* id, + const char* origin) { + if (!browser_context) + return false; + + notification_event_dispatcher_->DispatchNotificationClickEvent( + browser_context, std::string(id), GURL(base::StringPiece(origin)), + absl::optional(), absl::optional(), + base::BindOnce(OnEventDispatchComplete)); + // TODO: Currently if we click notification in quick panel, it will be + // deleted automatically by platform. If we can keep the notification + // after click, we don't need to call |DispatchNotificationCloseEvent| here. + notification_event_dispatcher_->DispatchNotificationCloseEvent( + browser_context, std::string(id), GURL(base::StringPiece(origin)), false, + base::BindOnce(OnEventDispatchComplete)); + return true; +} + +bool NotificationHelper::NotificationClicked(uint64_t notification_id) { + auto itr = persistent_notification_map_.find(notification_id); + if (itr != persistent_notification_map_.end()) { + persistent_notification_map_.erase(notification_id); + return true; + } + + auto it = notifications_map_.find(notification_id); + if (it != notifications_map_.end()) { + notification_event_dispatcher_->DispatchNonPersistentClickEvent( + it->second.non_persistent_id, base::DoNothing()); + + // TODO: Currently if we click notification in quick panel, it will be + // deleted automatically by platform. If we can keep the notification + // after click, we don't need to call |NotificationClosed| here. + notification_event_dispatcher_->DispatchNonPersistentCloseEvent( + it->second.non_persistent_id, base::DoNothing()); + notifications_map_.erase(notification_id); + return true; + } + + return false; +} + +bool NotificationHelper::NotificationDisplayed(uint64_t notification_id) { + auto itr = notifications_map_.find(notification_id); + if (itr == notifications_map_.end()) + return false; + + notification_event_dispatcher_->DispatchNonPersistentShowEvent( + itr->second.non_persistent_id); + return true; +} + +bool NotificationHelper::IsNotificationPresent( + const GURL& origin, + const std::string& notification_id, + uint64_t& replace_unique_id) { + for (auto it = notifications_map_.begin(); it != notifications_map_.end(); + ++it) { + if (notification_id == it->second.non_persistent_id && + origin == it->second.origin) { + replace_unique_id = it->first; + return true; + } + } + + return false; +} + +bool NotificationHelper::IsPersistentNotificationPresent( + const GURL& origin, + const std::string& notification_id, + uint64_t& replace_unique_id) { + for (auto it = persistent_notification_map_.begin(); + it != persistent_notification_map_.end(); ++it) { + if (notification_id == it->second.persistent_id && + origin == it->second.origin) { + replace_unique_id = it->first; + return true; + } + } + + return false; +} + +void NotificationHelper::SetNotification(const GURL& origin, + const std::string& notification_id, + uint64_t notification_unique_id) { + NotificationData new_notification = {origin, notification_id}; + notifications_map_[notification_unique_id] = new_notification; +} + +void NotificationHelper::SetPersistentNotification( + BrowserContext* browser_context, + const GURL& origin, + const std::string& notification_id, + uint64_t notification_unique_id) { + PersistentNotificationData persistent_notification_data = { + browser_context, origin, notification_id}; + persistent_notification_map_[notification_unique_id] = + persistent_notification_data; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_helper.h b/tizen_src/ewk/efl_integration/browser/notification/notification_helper.h new file mode 100644 index 0000000..8e50c9b --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/notification/notification_helper.h @@ -0,0 +1,68 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NOTIFICATION_HELPER_H +#define NOTIFICATION_HELPER_H + +#include + +#include "url/gurl.h" + +namespace content { + +class BrowserContext; +class NotificationEventDispatcher; + +struct NotificationData { + GURL origin; + std::string non_persistent_id; +}; + +struct PersistentNotificationData { + BrowserContext* browser_context; + GURL origin; + std::string persistent_id; +}; + +class NotificationHelper { + public: + NotificationHelper(); + ~NotificationHelper(); + + bool NotificationClosed(uint64_t notification_id, bool by_user); + + // Notify engine when user clicked on the notification + bool NotificationClicked(uint64_t notification_id); + + // Notification engine that notification was displayed + bool NotificationDisplayed(uint64_t notification_id); + + bool PersistentNotificationClicked(BrowserContext* browser_context, + const char* id, + const char* origin); + bool IsPersistentNotificationPresent(const GURL& origin, + const std::string& notification_id, + uint64_t& replace_unique_id); + bool IsNotificationPresent(const GURL& origin, + const std::string& notification_id, + uint64_t& replace_unique_id); + void SetNotification(const GURL& origin, + const std::string& notification_id, + uint64_t notification_unique_id); + + void SetPersistentNotification(BrowserContext* browser_context, + const GURL& origin, + const std::string& notification_id, + uint64_t notification_unique_id); + + private: + // This stores the notifications displayed to the user. + std::map notifications_map_; + std::map persistent_notification_map_; + NotificationEventDispatcher* notification_event_dispatcher_ = nullptr; +}; + +} // namespace content + +#endif // NOTIFICATION_HELPER_H diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc index 508f87a..1a35d5b 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -14,6 +14,7 @@ #include "web_contents_view_delegate_ewk.h" #include "devtools_manager_delegate_efl.h" #include "browser/editor_client_observer.h" +#include "browser/notification/notification_controller_efl.h" #include "browser/quota_permission_context_efl.h" #include "browser/render_message_filter_efl.h" #include "browser/web_view_browser_message_filter.h" @@ -38,10 +39,6 @@ #include "content/browser/speech/tts_message_filter_efl.h" #endif -#if defined(ENABLE_NOTIFICATIONS) -#include "browser/notification/notification_controller_efl.h" -#endif - #include "private/ewk_notification_private.h" using web_contents_utils::WebContentsFromFrameID; @@ -79,9 +76,7 @@ void PlatformLanguageChanged(keynode_t* keynode, void* data) { ContentBrowserClientEfl::ContentBrowserClientEfl() : browser_main_parts_efl_(nullptr), -#if defined(ENABLE_NOTIFICATIONS) notification_controller_(new NotificationControllerEfl), -#endif browser_context_efl_(nullptr), accept_langs_(kDefaultAcceptLanguages) { #if defined(OS_TIZEN) @@ -254,9 +249,9 @@ void ContentBrowserClientEfl::AllowCertificateError( #endif // !defined(EWK_BRINGUP) } -#if defined(ENABLE_NOTIFICATIONS) PlatformNotificationService* -ContentBrowserClientEfl::GetPlatformNotificationService() { +ContentBrowserClientEfl::GetPlatformNotificationService( + BrowserContext* browser_context) { return notification_controller_.get(); } @@ -264,7 +259,6 @@ NotificationControllerEfl* ContentBrowserClientEfl::GetNotificationController() const { return notification_controller_.get(); } -#endif bool ContentBrowserClientEfl::AllowGetCookie(const GURL& url, const GURL& first_party, diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.h b/tizen_src/ewk/efl_integration/content_browser_client_efl.h index 6df35ec..19ed7c3 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.h +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.h @@ -19,9 +19,7 @@ class Ewk_Notification; namespace content { class BrowserContextEfl; class BrowserMainPartsEfl; -#if defined(ENABLE_NOTIFICATIONS) class NotificationControllerEfl; -#endif class SharedURLLoaderFactoryEfl; class WebContents; class WebContentsView; @@ -70,12 +68,10 @@ class ContentBrowserClientEfl : public ContentBrowserClient { bool strict_enforcement, base::OnceCallback callback) override; -#if defined(ENABLE_NOTIFICATIONS) - virtual PlatformNotificationService* GetPlatformNotificationService() - override; + virtual PlatformNotificationService* GetPlatformNotificationService( + BrowserContext* browser_context) override; NotificationControllerEfl* GetNotificationController() const; -#endif bool AllowGetCookie(const GURL& url, const GURL& first_party, @@ -144,9 +140,7 @@ class ContentBrowserClientEfl : public ContentBrowserClient { BrowserMainPartsEfl* browser_main_parts_efl_; -#if defined(ENABLE_NOTIFICATIONS) std::unique_ptr notification_controller_; -#endif BrowserContextEfl* browser_context_efl_; diff --git a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h index c4eaca46..28593b6 100644 --- a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h +++ b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h @@ -140,7 +140,8 @@ enum CallbackType { NewWindowNavigationPolicyDecision, #endif // OS_TIZEN URIChanged, - DidNotAllowScript + DidNotAllowScript, + NotificationPermissionReply }; template @@ -292,6 +293,9 @@ DECLARE_EWK_VIEW_CALLBACK(StatusBarVisible, "statusbar,visible", bool*); DECLARE_EWK_VIEW_CALLBACK(ToolbarVisible, "toolbar,visible", bool*); DECLARE_EWK_VIEW_CALLBACK(WindowResizable, "window,resizable", bool*); DECLARE_EWK_VIEW_CALLBACK(DidNotAllowScript, "did,not,allow,script", void); +DECLARE_EWK_VIEW_CALLBACK(NotificationPermissionReply, + "notification,permission,reply", + Ewk_Notification_Permission*); } #endif diff --git a/tizen_src/ewk/efl_integration/permission_controller_delegate_efl.cc b/tizen_src/ewk/efl_integration/permission_controller_delegate_efl.cc index 4d9ac86..3993839 100644 --- a/tizen_src/ewk/efl_integration/permission_controller_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/permission_controller_delegate_efl.cc @@ -123,10 +123,9 @@ void PermissionControllerDelegateEfl::RequestPermissions( weak_ptr_factory_.GetWeakPtr(), request_id, i)); break; } -#if defined(ENABLE_NOTIFICATIONS) case PermissionType::NOTIFICATIONS: { ContentMainDelegateEfl& cmde = - EwkGlobalData::GetInstance()->GetContentMainDelegatEfl(); + EwkGlobalData::GetInstance()->GetContentMainDelegateEfl(); ContentBrowserClientEfl* cbce = static_cast( cmde.GetContentBrowserClient()); if (!cbce) { @@ -142,7 +141,6 @@ void PermissionControllerDelegateEfl::RequestPermissions( weak_ptr_factory_.GetWeakPtr(), request_id, i)); break; } -#endif case PermissionType::PROTECTED_MEDIA_IDENTIFIER: case PermissionType::MIDI_SYSEX: { NOTIMPLEMENTED() << "RequestPermission not implemented for " @@ -190,7 +188,6 @@ PermissionStatus PermissionControllerDelegateEfl::GetPermissionStatus( const GURL& embedding_origin) { switch (permission) { case PermissionType::BACKGROUND_SYNC: -#if defined(ENABLE_NOTIFICATIONS) case PermissionType::NOTIFICATIONS: { // requesting_origin should be the same as embedding_origin // using push API from iframes are not allowed @@ -198,7 +195,7 @@ PermissionStatus PermissionControllerDelegateEfl::GetPermissionStatus( return PermissionStatus::DENIED; ContentMainDelegateEfl& cmde = - EwkGlobalData::GetInstance()->GetContentMainDelegatEfl(); + EwkGlobalData::GetInstance()->GetContentMainDelegateEfl(); ContentBrowserClientEfl* cbce = static_cast(cmde.GetContentBrowserClient()); if (!cbce) { @@ -215,7 +212,6 @@ PermissionStatus PermissionControllerDelegateEfl::GetPermissionStatus( return notification_status; } -#endif case PermissionType::PROTECTED_MEDIA_IDENTIFIER: return PermissionStatus::GRANTED; default: diff --git a/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc b/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc index 60704c0..1378ac6 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc @@ -11,7 +11,6 @@ using content::BrowserThread; using namespace blink::mojom; Ewk_Notification::Ewk_Notification(const std::string& body, - const std::string& replaceID, const std::string& title, const SkBitmap& icon, bool silent, @@ -19,7 +18,6 @@ Ewk_Notification::Ewk_Notification(const std::string& body, const GURL& origin) : body_(body), icon_(icon), - replaceID_(replaceID), title_(title), silent_(silent), notificationID_(notificationID), @@ -31,10 +29,6 @@ const char* Ewk_Notification::GetBody() const { return body_.c_str(); } -const char* Ewk_Notification::GetReplaceId() const { - return replaceID_.c_str(); -} - const char* Ewk_Notification::GetTitle() const { return title_.c_str(); } @@ -82,21 +76,13 @@ bool Ewk_Notification::SaveAsPng(const char* path) const { } Ewk_Notification_Permission_Request::Ewk_Notification_Permission_Request( - Evas_Object* webview, base::OnceCallback callback, const GURL& source_origin) - : webview_(webview), - origin_(new _Ewk_Security_Origin(source_origin)), + : origin_(new _Ewk_Security_Origin(source_origin)), callback_(std::move(callback)), decided_(false), suspended_(false) {} -Ewk_Notification_Permission_Request::~Ewk_Notification_Permission_Request() {} - -Evas_Object* Ewk_Notification_Permission_Request::GetWebviewEvasObject() const { - return webview_; -} - const _Ewk_Security_Origin* Ewk_Notification_Permission_Request::GetSecurityOrigin() const { return origin_.get(); diff --git a/tizen_src/ewk/efl_integration/private/ewk_notification_private.h b/tizen_src/ewk/efl_integration/private/ewk_notification_private.h index 2414a35..a6b9de7 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_notification_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_notification_private.h @@ -19,7 +19,6 @@ class GURL; struct Ewk_Notification { public: Ewk_Notification(const std::string& body, - const std::string& replaceID, const std::string& title, const SkBitmap& icon, bool silent, @@ -28,7 +27,6 @@ struct Ewk_Notification { ~Ewk_Notification(); const char* GetBody() const; - const char* GetReplaceId() const; const char* GetTitle() const; bool IsSilent() const; Evas_Object* GetIcon(Evas* evas) const; @@ -39,7 +37,6 @@ struct Ewk_Notification { private: std::string body_; SkBitmap icon_; - std::string replaceID_; std::string title_; bool silent_; uint64_t notificationID_; @@ -52,12 +49,10 @@ struct Ewk_Notification { struct Ewk_Notification_Permission_Request { public: Ewk_Notification_Permission_Request( - Evas_Object* webview, base::OnceCallback callback, const GURL& source_origin); - ~Ewk_Notification_Permission_Request(); + ~Ewk_Notification_Permission_Request() {} - Evas_Object* GetWebviewEvasObject() const; const _Ewk_Security_Origin* GetSecurityOrigin() const; bool IsDecided() const; bool IsSuspended() const; @@ -65,7 +60,6 @@ struct Ewk_Notification_Permission_Request { bool Reply(bool allow); private: - Evas_Object* webview_; std::unique_ptr<_Ewk_Security_Origin> origin_; base::OnceCallback callback_; bool decided_; diff --git a/tizen_src/ewk/efl_integration/public/ewk_context.cc b/tizen_src/ewk/efl_integration/public/ewk_context.cc index e9676da..1b017b7 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_context.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_context.cc @@ -43,6 +43,12 @@ using content::ContentBrowserClientEfl; using content::ContentMainDelegateEfl; +#if defined(OS_TIZEN) +#include + +#include "browser/notification/notification_controller_efl.h" +#endif + namespace { ContentBrowserClientEfl* GetContentBrowserClient() { if (!EwkGlobalData::IsInitialized()) { @@ -906,8 +912,35 @@ Eina_Bool ewk_context_sound_overlap_set(Ewk_Context* context, Eina_Bool enable) Eina_Bool ewk_context_app_control_set(const Ewk_Context* context, void* app_control) { - LOG_EWK_API_MOCKUP(); +#if defined(OS_TIZEN) + EINA_SAFETY_ON_NULL_RETURN_VAL(context, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(app_control, EINA_FALSE); + + char* notification_id = nullptr; + app_control_h control = static_cast(app_control); + int ret = app_control_get_extra_data(control, "notification_id", + ¬ification_id); + if (ret != APP_CONTROL_ERROR_NONE) { + LOG(ERROR) << "app_control_get_extra_data is failed with err " << ret; + return EINA_FALSE; + } + + if (notification_id) { + ContentBrowserClientEfl* cbce = GetContentBrowserClient(); + if (cbce) { + char* notification_origin = nullptr; + app_control_get_extra_data(control, "notification_origin", + ¬ification_origin); + cbce->GetNotificationController()-> + PersistentNotificationClicked(context->browser_context(), + notification_id, + notification_origin); + } + } + return EINA_TRUE; +#else return EINA_FALSE; +#endif } void ewk_context_max_refresh_rate_set(Ewk_Context* context, int max_refresh_rate) diff --git a/tizen_src/ewk/efl_integration/public/ewk_notification.cc b/tizen_src/ewk/efl_integration/public/ewk_notification.cc index 5327cf8..e237480 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_notification.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_notification.cc @@ -32,9 +32,7 @@ #include "eweb_view.h" #include "ewk_global_data.h" #include "browser_context_efl.h" -#if defined(ENABLE_NOTIFICATIONS) #include "browser/notification/notification_controller_efl.h" -#endif #include "private/ewk_context_private.h" #include "private/ewk_security_origin_private.h" #include "private/ewk_notification_private.h" @@ -65,10 +63,7 @@ Eina_Bool ewk_notification_callbacks_set(Ewk_Notification_Show_Callback show_cal ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); -#if defined(ENABLE_NOTIFICATIONS) cbce->GetNotificationController()->SetNotificationCallbacks(show_callback, cancel_callback, user_data); -#endif - return EINA_TRUE; } @@ -77,9 +72,7 @@ Eina_Bool ewk_notification_callbacks_reset() ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); -#if defined(ENABLE_NOTIFICATIONS) cbce->GetNotificationController()->SetNotificationCallbacks(nullptr, nullptr, nullptr); -#endif return EINA_TRUE; } @@ -109,11 +102,7 @@ Eina_Bool ewk_notification_clicked(uint64_t notification_id) { ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); -#if defined(ENABLE_NOTIFICATIONS) return cbce->GetNotificationController()->NotificationClicked(notification_id); -#else - return EINA_FALSE; -#endif } const char* ewk_notification_icon_url_get(const Ewk_Notification* ewk_notification) @@ -131,16 +120,14 @@ Eina_Bool ewk_notification_cached_permissions_set(Eina_List* ewk_notification_pe { ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); -#if defined(ENABLE_NOTIFICATIONS) content::NotificationControllerEfl* notification_controller = cbce->GetNotificationController(); notification_controller->ClearPermissions(); Eina_List* list; void* data; EINA_LIST_FOREACH(ewk_notification_permissions, list, data) { Ewk_Notification_Permission* perm = static_cast(data); - notification_controller->AddPermission(GURL(perm->origin), (perm->allowed == EINA_TRUE)); + notification_controller->PutPermission(GURL(perm->origin), (perm->allowed == EINA_TRUE)); } -#endif return EINA_TRUE; } @@ -155,11 +142,9 @@ const Ewk_Security_Origin* ewk_notification_permission_request_origin_get( Eina_Bool ewk_notification_permission_reply(Ewk_Notification_Permission_Request* request, Eina_Bool allow) { EINA_SAFETY_ON_NULL_RETURN_VAL(request, EINA_FALSE); -#if defined(ENABLE_NOTIFICATIONS) ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); cbce->GetNotificationController()->SetPermissionForNotification(request, allow); -#endif return request->Reply(allow == EINA_TRUE); } @@ -177,11 +162,9 @@ Eina_Bool ewk_notification_permission_request_suspend(Ewk_Notification_Permissio Eina_Bool ewk_notification_policies_removed(Eina_List* origins) { EINA_SAFETY_ON_NULL_RETURN_VAL(origins, EINA_FALSE); -#if defined(ENABLE_NOTIFICATIONS) ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); cbce->GetNotificationController()->RemovePermissions(origins); -#endif return EINA_TRUE; } @@ -193,24 +176,16 @@ const Ewk_Security_Origin* ewk_notification_security_origin_get(const Ewk_Notifi Eina_Bool ewk_notification_showed(uint64_t notification_id) { -#if defined(ENABLE_NOTIFICATIONS) ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); return cbce->GetNotificationController()->NotificationDisplayed(notification_id); -#else - return EINA_FALSE; -#endif } Eina_Bool ewk_notification_closed(uint64_t notification_id, Eina_Bool by_user) { -#if defined(ENABLE_NOTIFICATIONS) ContentBrowserClientEfl* cbce = GetContentBrowserClient(); EINA_SAFETY_ON_NULL_RETURN_VAL(cbce, EINA_FALSE); return cbce->GetNotificationController()->NotificationClosed(notification_id, by_user); -#else - return EINA_FALSE; -#endif } const char* ewk_notification_title_get(const Ewk_Notification* ewk_notification) diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc index a8e50a8..024ed6b 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -37,6 +37,11 @@ #include "third_party/blink/public/common/input/web_input_event.h" #include "url/gurl.h" +#if defined(OS_TIZEN) +#include +#include +#endif + #if defined(TIZEN_MULTIMEDIA_SUPPORT) #include "content/public/browser/media_capture_devices.h" #include "media/capture/video/tizen/video_capture_device_tizen.h" @@ -55,6 +60,7 @@ using autofill::AutofillClientEfl; using autofill::ContentAutofillDriverFactory; using password_manager::PasswordManagerClientEfl; #endif + using std::u16string; using namespace ui; @@ -140,6 +146,9 @@ WebContents* WebContentsDelegateEfl::OpenURLFromTab( if (!new_object) return NULL; + if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB) + ActivateContents(source); + EWebView* wv = WebViewDelegateEwk::GetInstance().GetWebViewFromEvasObject(new_object); DCHECK(wv); @@ -460,6 +469,42 @@ void WebContentsDelegateEfl::RequestCertificateConfirm( } } +void WebContentsDelegateEfl::ActivateContents(WebContents* contents) { +#if defined(OS_TIZEN) + app_control_h app_control = nullptr; + int ret = app_control_create(&app_control); + if (ret != APP_CONTROL_ERROR_NONE) { + LOG(ERROR) << "app_control_create is failed with err " << ret; + return; + } + + std::unique_ptr::type, + decltype(app_control_destroy)*> + auto_release{app_control, app_control_destroy}; + + char* app_id = nullptr; + ret = app_manager_get_app_id(getpid(), &app_id); + if (ret != APP_MANAGER_ERROR_NONE) { + LOG(ERROR) << "app_manager_get_app_id is failed with err " << ret; + return; + } + + ret = app_control_set_app_id(app_control, app_id); + if (app_id) + free(app_id); + if (ret != APP_CONTROL_ERROR_NONE) { + LOG(ERROR) << "app_control_set_app_id is failed with err " << ret; + return; + } + + ret = app_control_send_launch_request(app_control, nullptr, nullptr); + if (ret != APP_CONTROL_ERROR_NONE) { + LOG(ERROR) << "app_control_send_launch_request is failed with err " << ret; + return; + } +#endif +} + void WebContentsDelegateEfl::SetContentSecurityPolicy( const std::string& policy, Ewk_CSP_Header_Type header_type) { diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h index dbb08ea..2b68c33 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h @@ -106,6 +106,8 @@ class WebContentsDelegateEfl : public WebContentsDelegate, JavaScriptDialogManager* GetJavaScriptDialogManager( WebContents* source) override; + void ActivateContents(WebContents* contents) override; + void OnUpdateSettings(const Ewk_Settings* settings); void SetContentSecurityPolicy(const std::string& policy, Ewk_CSP_Header_Type header_type); -- 2.7.4 From 4c7348f9f5d5d0317216e95a88566a02daf78702 Mon Sep 17 00:00:00 2001 From: uzair Date: Fri, 8 Jan 2021 16:21:05 +0530 Subject: [PATCH 15/16] Clean up interstitial page usage in web_contents_view_efl Interstitial page is completely removed in chromium upstream [1] and [2],hence removing its usage which was under EWK_BRINGUP macro. [1]https://chromium-review.googlesource.com/c/chromium/src/+/2146137 [2]https://chromium-review.googlesource.com/c/chromium/src/+/2147921 Reference: https://review.tizen.org/gerrit/c/251136 Change-Id: If1a8487e09c4f221ef527d4e7bc986fc2ca3c789 Signed-off-by: uzair (cherry picked from commit db43b00a85b61498b0719dc82827827f725f0626) --- .../content/browser/web_contents/web_contents_view_efl.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc index 3810387..a8d169d 100644 --- a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_efl.cc @@ -180,13 +180,6 @@ void WebContentsViewEfl::SizeContents(const gfx::Size& size) { } void WebContentsViewEfl::Focus() { -#if !defined(EWK_BRINGUP) // FIXME: m85 bringup - if (web_contents_->GetInterstitialPage()) { - web_contents_->GetInterstitialPage()->Focus(); - return; - } -#endif - if (delegate_.get() && delegate_->Focus()) return; -- 2.7.4 From 062b83aa082b7cc81fdeca586e66fe98a5753015 Mon Sep 17 00:00:00 2001 From: liwei Date: Thu, 3 Mar 2022 15:24:01 +0800 Subject: [PATCH 16/16] [M94 Migration] Refactor JavaScriptModalDialog for EWK and WRT JavaScriptModalDialog implementation is pretty much the same both EWK and WRT. - WRTJavaScriptModalDialog and JavaScriptModalDialogEfl This patch will refactor 2 almost identical classes by common code and be able to improve maintainability. Reference: https://review.tizen.org/gerrit/248006/ And for compile, upload some logic from https://review.tizen.org/gerrit/267646/. Change-Id: I10ce6e4e2de9575d869c33d6089cc5694c94a83a Signed-off-by: liwei --- .../chromium_impl/content/browser/browser_efl.gni | 2 + .../javascript_dialog/javascript_modal_dialog.cc | 499 +++++++++++++++++++++ .../javascript_dialog/javascript_modal_dialog.h | 93 ++++ tizen_src/chromium_impl/content/common/paths_efl.h | 1 + .../browser/javascript_dialog_manager_efl.cc | 12 +- .../browser/javascript_modal_dialog_efl.cc | 433 ++---------------- .../browser/javascript_modal_dialog_efl.h | 52 +-- .../efl_integration/context_menu_controller_efl.cc | 4 +- 8 files changed, 654 insertions(+), 442 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.cc create mode 100644 tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.h diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index b463e0d..c15aebe 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -72,6 +72,8 @@ external_content_browser_efl_sources = [ "//tizen_src/chromium_impl/content/browser/compositor/evasgl_delegated_frame_host.h", "//tizen_src/chromium_impl/content/browser/compositor/evasgl_output_surface.cc", "//tizen_src/chromium_impl/content/browser/compositor/evasgl_output_surface.h", + "//tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.cc", + "//tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.h", "//tizen_src/chromium_impl/content/browser/media/capture/mouse_cursor_overlay_controller_efl.cc", "//tizen_src/chromium_impl/content/browser/public/browser/web_contents_efl_delegate.h", "//tizen_src/chromium_impl/content/browser/public/browser/web_contents_view_efl_delegate.h", diff --git a/tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.cc b/tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.cc new file mode 100644 index 0000000..4e29476 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.cc @@ -0,0 +1,499 @@ +// Copyright 2020 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "javascript_modal_dialog.h" + +#include + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" +#include "content/common/paths_efl.h" +#include "content/public/browser/web_contents.h" +#include "tizen_src/chromium_impl/tizen/system_info.h" +#include "ui/display/device_display_info_efl.h" +#include "url/gurl.h" + +#if defined(OS_TIZEN) +#include +#endif + +namespace content { + +namespace { + +static void PromptEnterKeyDownCallback(void*, Evas_Object* obj, void*) { + elm_entry_input_panel_hide(obj); +} + +} // namespace + +// static +JavaScriptModalDialog* JavaScriptModalDialog::CreateDialogAndShow( + content::WebContents* web_contents, + Type type, + const std::u16string& message_text, + const std::u16string& default_prompt_text, + content::JavaScriptDialogManager::DialogClosedCallback callback, + Evas_Object* parent) { + JavaScriptModalDialog* dialog = new JavaScriptModalDialog( + web_contents, type, message_text, default_prompt_text, + std::move(callback), parent); + if (!dialog->ShowJavaScriptDialog()) { + LOG(ERROR) << "Could not create javascript dialog."; + delete dialog; + dialog = nullptr; + } + return dialog; +} + +JavaScriptModalDialog::JavaScriptModalDialog( + content::WebContents* web_contents, + Type type, + const std::u16string& message_text, + const std::u16string& default_prompt_text, + content::JavaScriptDialogManager::DialogClosedCallback callback, + Evas_Object* evas_object) + : window_(nullptr), + conformant_(nullptr), + popup_(nullptr), + prompt_entry_(nullptr), + parent_(elm_object_parent_widget_get(evas_object)), + is_callback_processed_(false), + is_showing_(false), + web_contents_(web_contents), + type_(type), + message_text_(message_text), + default_prompt_text_(default_prompt_text), + close_callback_(std::move(callback)), + prompt_entry_changed_callback_(nullptr) {} + +JavaScriptModalDialog::~JavaScriptModalDialog() { + Close(); +} + +bool JavaScriptModalDialog::ShowJavaScriptDialog() { + if (!parent_) + return false; + + Evas_Object* top_window = elm_object_top_widget_get(parent_); + + if (IsMobileProfile() || IsTvProfile()) + popup_ = CreatePopupOnNewWindow(top_window); + else + popup_ = CreatePopup(top_window); + + if (!popup_) + return false; + + if (IsWearableProfile()) + elm_object_style_set(popup_, "circle"); + + switch (type_) { + case PROMPT: + if (!CreatePromptLayout()) + return false; + break; + case NAVIGATION: + if (!CreateNavigationLayout()) + return false; + break; + case ALERT: + if (!CreateAlertLayout()) + return false; + break; + case CONFIRM: + if (!CreateConfirmLayout()) + return false; + break; + } + +#if defined(OS_TIZEN) + eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, + CancelButtonCallback, this); +#endif + + evas_object_focus_set(popup_, true); + evas_object_show(popup_); + + is_showing_ = true; + + return true; +} + +Evas_Object* JavaScriptModalDialog::CreatePopup(Evas_Object* window) { + if (!window) + return nullptr; + + conformant_ = elm_conformant_add(window); + if (!conformant_) + return nullptr; + + evas_object_size_hint_weight_set(conformant_, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(window, conformant_); + evas_object_show(conformant_); + Evas_Object* layout = elm_layout_add(conformant_); + if (!layout) + return nullptr; + + elm_layout_theme_set(layout, "layout", "application", "default"); + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(layout); + + elm_object_content_set(conformant_, layout); + + return elm_popup_add(layout); +} + +Evas_Object* JavaScriptModalDialog::CreatePopupOnNewWindow( + Evas_Object* top_window) { + if (!top_window) + return nullptr; + + window_ = elm_win_add(top_window, "JavaScriptModalDialog", ELM_WIN_BASIC); + if (!window_) + return nullptr; + + elm_win_alpha_set(window_, EINA_TRUE); + + if (elm_win_indicator_mode_get(top_window) == ELM_WIN_INDICATOR_SHOW) + elm_win_indicator_mode_set(window_, ELM_WIN_INDICATOR_SHOW); + + if (elm_win_indicator_opacity_get(top_window) == + ELM_WIN_INDICATOR_TRANSPARENT) + elm_win_indicator_opacity_set(window_, ELM_WIN_INDICATOR_TRANSPARENT); + + if (elm_win_wm_rotation_supported_get(top_window)) { + int rots[] = {0, 90, 180, 270}; + elm_win_wm_rotation_available_rotations_set(window_, rots, 4); + } + + display::DeviceDisplayInfoEfl display_info; + evas_object_resize(window_, display_info.GetDisplayWidth(), + display_info.GetDisplayHeight()); + + Evas_Object* popup = CreatePopup(window_); + elm_win_conformant_set(window_, EINA_TRUE); + evas_object_show(window_); + + return popup; +} + +bool JavaScriptModalDialog::CreatePromptLayout() { + Evas_Object* layout = elm_layout_add(popup_); + if (!layout) + return false; + if (IsWearableProfile()) { + elm_layout_theme_set(layout, "layout", "popup", "content/circle/buttons2"); + if (message_text_.c_str()) { + elm_object_part_text_set(layout, "elm.text.title", + base::UTF16ToUTF8(message_text_).c_str()); + } + } else { + if (message_text_.c_str()) { + elm_object_part_text_set(popup_, "title,text", + base::UTF16ToUTF8(message_text_).c_str()); + } + + elm_layout_file_set(layout, GetEdjPath().c_str(), "prompt"); + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + } + + prompt_entry_ = elm_entry_add(popup_); + if (!prompt_entry_) + return false; + + if (prompt_entry_changed_callback_) { + Ecore_IMF_Context* imf_context = static_cast( + elm_entry_imf_context_get(prompt_entry_)); + ecore_imf_context_input_panel_event_callback_add( + imf_context, ECORE_IMF_INPUT_PANEL_STATE_EVENT, + prompt_entry_changed_callback_, prompt_entry_); + } + elm_entry_single_line_set(prompt_entry_, EINA_TRUE); + elm_entry_input_panel_return_key_type_set( + prompt_entry_, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE); + evas_object_smart_callback_add(prompt_entry_, "activated", + PromptEnterKeyDownCallback, this); + elm_object_text_set(prompt_entry_, + base::UTF16ToUTF8(default_prompt_text_).c_str()); + elm_entry_scrollable_set(prompt_entry_, EINA_TRUE); + elm_entry_cursor_end_set(prompt_entry_); + + if (IsWearableProfile()) + elm_object_part_content_set(layout, "elm.swallow.content", prompt_entry_); + else + elm_object_part_content_set(layout, "prompt_container", prompt_entry_); + + elm_object_content_set(popup_, layout); + Evas_Object* cancel_btn = AddButton("IDS_WEBVIEW_BUTTON_CANCEL_ABB4", + "button1", CancelButtonCallback); + Evas_Object* ok_btn = + AddButton("IDS_WEBVIEW_BUTTON_OK_ABB4", "button2", OkButtonCallback); + if (!cancel_btn || !ok_btn) + return false; + + evas_object_focus_set(ok_btn, true); + return true; +} + +bool JavaScriptModalDialog::CreateNavigationLayout() { + if (message_text_.c_str()) { + elm_object_part_text_set(popup_, "title,text", + base::UTF16ToUTF8(message_text_).c_str()); + } + + std::string question(dgettext("WebKit", "IDS_WEBVIEW_POP_LEAVE_THIS_PAGE_Q")); + std::string message; + if (default_prompt_text_.c_str()) { + message = std::string(base::UTF16ToUTF8(default_prompt_text_).c_str()) + + ("\n") + question; + } else { + message = question; + } + if (IsWearableProfile() && + !AddCircleLayout(message, "content/circle/buttons2")) { + return false; + } else if (!message_text_.empty()) { + // Use GetPopupMessage() to modify the message_text_ + elm_object_text_set( + popup_, GetPopupMessage(base::UTF16ToUTF8(message_text_)).c_str()); + } + Evas_Object* cancel_btn = + AddButton("IDS_WEBVIEW_BUTTON_STAY", "button1", CancelButtonCallback); + Evas_Object* ok_btn = + AddButton("IDS_WEBVIEW_BUTTON_LEAVE", "button2", OkButtonCallback); + if (!cancel_btn || !ok_btn) + return false; + + evas_object_focus_set(ok_btn, true); + + return true; +} + +bool JavaScriptModalDialog::CreateAlertLayout() { + elm_object_part_text_set(popup_, "title,text", GetTitle().c_str()); + if (IsWearableProfile() && !AddCircleLayout(base::UTF16ToUTF8(message_text_), + "content/circle/buttons1")) + return false; + if (!message_text_.empty()) { + // Use GetPopupMessage() to modify the message_text_ + elm_object_text_set( + popup_, GetPopupMessage(base::UTF16ToUTF8(message_text_)).c_str()); + } + + Evas_Object* ok_btn = + AddButton("IDS_WEBVIEW_BUTTON_OK_ABB4", "button1", OkButtonCallback); + if (!ok_btn) + return false; + + evas_object_focus_set(ok_btn, true); + return true; +} + +bool JavaScriptModalDialog::CreateConfirmLayout() { + elm_object_part_text_set(popup_, "title,text", GetTitle().c_str()); + if (IsWearableProfile() && !AddCircleLayout(base::UTF16ToUTF8(message_text_), + "content/circle/buttons2")) + return false; + if (!message_text_.empty()) { + // Use GetPopupMessage() to modify the message_text_ + elm_object_text_set( + popup_, GetPopupMessage(base::UTF16ToUTF8(message_text_)).c_str()); + } + Evas_Object* cancel_btn = AddButton("IDS_WEBVIEW_BUTTON_CANCEL_ABB4", + "button1", CancelButtonCallback); + Evas_Object* ok_btn = + AddButton("IDS_WEBVIEW_BUTTON_OK_ABB4", "button2", OkButtonCallback); + if (!cancel_btn || !ok_btn) + return false; + + evas_object_focus_set(ok_btn, true); + + return true; +} + +std::string JavaScriptModalDialog::GetTitle() { + const GURL& url = web_contents_->GetVisibleURL(); + std::string text; + if (url.SchemeIsFile() || url.is_empty()) { + if (web_contents_->GetMainFrame()) + text = base::UTF16ToUTF8(web_contents_->GetTitle()); + } else + text = url.possibly_invalid_spec(); + + std::string title = + dgettext("WebKit", "IDS_WEBVIEW_HEADER_MESSAGE_FROM_PS_M_WEBSITE"); + + const std::string replaceStr("%s"); + size_t pos = title.find(replaceStr); + if (pos != std::string::npos) + title.replace(pos, replaceStr.length(), text); + + return title; +} + +std::string JavaScriptModalDialog::GetPopupMessage(const std::string& str) { + if (str.empty()) + return str; + // Replace new line with break in the string + std::string message = std::string(elm_entry_utf8_to_markup(str.c_str())); + base::ReplaceChars(message, "\n", "
", &message); + +#if !defined(OS_TIZEN_TV_PRODUCT) + if (!IsWearableProfile()) + message = "" + message + ""; +#endif + + return message; +} + +std::string JavaScriptModalDialog::GetEdjPath() { + base::FilePath edj_dir; + base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); + return edj_dir.Append(FILE_PATH_LITERAL("JavaScriptPopup.edj")) + .AsUTF8Unsafe(); +} + +// static +void JavaScriptModalDialog::CancelButtonCallback(void* data, + Evas_Object* obj, + void* event_info) { + JavaScriptModalDialog* dialog = static_cast(data); + + std::move(dialog->close_callback_).Run(false, std::u16string()); + evas_object_del(dialog->popup_); + dialog->CloseAndNotify(); +} + +// static +void JavaScriptModalDialog::OkButtonCallback(void* data, + Evas_Object* obj, + void* event_info) { + JavaScriptModalDialog* dialog = static_cast(data); + if (dialog->type_ == PROMPT && dialog->prompt_entry_) { + std::move(dialog->close_callback_) + .Run(true, + base::UTF8ToUTF16(elm_entry_entry_get(dialog->prompt_entry_))); + } else { + std::move(dialog->close_callback_).Run(true, std::u16string()); + } + dialog->CloseAndNotify(); +} + +void JavaScriptModalDialog::Close() { + if (!is_callback_processed_) + std::move(close_callback_).Run(false, std::u16string()); + + if ((IsMobileProfile() || IsTvProfile()) && window_) { + evas_object_del(window_); + window_ = nullptr; + conformant_ = nullptr; + } else if (conformant_) { + evas_object_del(conformant_); + conformant_ = nullptr; + } + + popup_ = nullptr; + prompt_entry_ = nullptr; + + is_showing_ = false; +} + +void JavaScriptModalDialog::SetPopupSize(int width, int height) { + if (!popup_) + return; + + evas_object_resize(popup_, width, height); + evas_object_move(popup_, 0, 0); +} + +Evas_Object* JavaScriptModalDialog::AddButton(const std::string& text, + const std::string& part, + Evas_Smart_Cb callback) { + Evas_Object* btn = elm_button_add(popup_); + if (!btn) + return nullptr; + if (IsWearableProfile()) { + Evas_Object* img; + if (type_ == ALERT) { + elm_object_style_set(btn, "bottom"); + img = AddButtonIcon(btn, "popup_btn_ok.png"); + } else if (part.compare("button1") == 0) { + elm_object_style_set(btn, "popup/circle/left"); + img = AddButtonIcon(btn, "popup_btn_cancel.png"); + } else { + elm_object_style_set(btn, "popup/circle/right"); + img = AddButtonIcon(btn, "popup_btn_ok.png"); + } + + if (!img) + return nullptr; + } else { + elm_object_style_set(btn, "popup"); + elm_object_domain_translatable_part_text_set(btn, nullptr, "WebKit", + text.c_str()); + } + elm_object_part_content_set(popup_, part.c_str(), btn); + evas_object_smart_callback_add(btn, "clicked", callback, this); + return btn; +} + +Evas_Object* JavaScriptModalDialog::AddButtonIcon(Evas_Object* btn, + const std::string& img) { + if (!IsWearableProfile()) + return nullptr; + + Evas_Object* icon = elm_image_add(btn); + if (!icon) + return nullptr; + + base::FilePath img_dir; + base::PathService::Get(PathsEfl::IMAGE_RESOURCE_DIR, &img_dir); + std::string file_path = img_dir.Append(FILE_PATH_LITERAL(img)).AsUTF8Unsafe(); + if (!elm_image_file_set(icon, file_path.c_str(), nullptr)) + return nullptr; + + evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_part_content_set(btn, "elm.swallow.content", icon); + evas_object_show(icon); + return icon; +} + +bool JavaScriptModalDialog::AddCircleLayout(const std::string& title, + const std::string& theme) { + if (!IsWearableProfile()) + return false; + + Evas_Object* layout = elm_layout_add(popup_); + if (!layout) + return false; + + elm_layout_theme_set(layout, "layout", "popup", theme.c_str()); + + if (!title.empty()) { + elm_object_part_text_set(layout, "elm.text", + GetPopupMessage(title).c_str()); + } + + elm_object_content_set(popup_, layout); + + return true; +} + +void JavaScriptModalDialog::SetPopupClosedCallback( + PopupClosedCallback& callback) { + popup_closed_callback_ = std::move(callback); +} + +void JavaScriptModalDialog::CloseAndNotify() { + is_callback_processed_ = true; + Close(); + if (popup_closed_callback_) + std::move(popup_closed_callback_).Run(); +} + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.h b/tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.h new file mode 100644 index 0000000..dcfd8d3 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/javascript_dialog/javascript_modal_dialog.h @@ -0,0 +1,93 @@ +// Copyright 2020 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_JAVASCRIPT_MODAL_DIALOG_H_ +#define CONTENT_BROWSER_JAVASCRIPT_MODAL_DIALOG_H_ + +#include +#include +#include + +#include "base/callback.h" +#include "content/public/browser/javascript_dialog_manager.h" + +namespace content { + +class JavaScriptModalDialog { + public: + typedef void (*PromptEntryChangedCallback)(void*, Ecore_IMF_Context*, int); + typedef base::OnceCallback PopupClosedCallback; + enum Type { ALERT, CONFIRM, NAVIGATION, PROMPT }; + static JavaScriptModalDialog* CreateDialogAndShow( + content::WebContents* web_contents, + Type type, + const std::u16string& message_text, + const std::u16string& default_prompt_text, + content::JavaScriptDialogManager::DialogClosedCallback callback, + Evas_Object* parent); + JavaScriptModalDialog( + content::WebContents* web_contents, + Type type, + const std::u16string& message_text, + const std::u16string& default_prompt_text, + content::JavaScriptDialogManager::DialogClosedCallback callback, + Evas_Object* parent); + virtual ~JavaScriptModalDialog(); + + bool IsShowing() { return is_showing_; } + void SetPopupSize(int width, int height); + void SetParentEvasObject(Evas_Object* parent) { parent_ = parent; } + void SetPromptEntryChangedCallback(PromptEntryChangedCallback callback) { + prompt_entry_changed_callback_ = callback; + } + void SetPopupClosedCallback(PopupClosedCallback& callback); + bool ShowJavaScriptDialog(); + + private: + static void CancelButtonCallback(void* data, + Evas_Object* obj, + void* event_info); + static void OkButtonCallback(void* data, Evas_Object* obj, void* event_info); + + void Close(); + void CloseAndNotify(); + + bool AddCircleLayout(const std::string& title, const std::string& theme); + bool CreatePromptLayout(); + bool CreateAlertLayout(); + bool CreateConfirmLayout(); + bool CreateNavigationLayout(); + + Evas_Object* AddButton(const std::string& text, + const std::string& part, + Evas_Smart_Cb callback); + Evas_Object* AddButtonIcon(Evas_Object* btn, const std::string& img); + Evas_Object* CreatePopup(Evas_Object* window); + Evas_Object* CreatePopupOnNewWindow(Evas_Object* top_window); + + std::string GetEdjPath(); + std::string GetPopupMessage(const std::string&); + std::string GetTitle(); + + Evas_Object* window_; + Evas_Object* conformant_; + Evas_Object* popup_; + Evas_Object* prompt_entry_; + Evas_Object* parent_; + + bool is_callback_processed_; + bool is_showing_; + + content::WebContents* web_contents_; + Type type_; + std::u16string message_text_; + std::u16string default_prompt_text_; + content::JavaScriptDialogManager::DialogClosedCallback close_callback_; + PromptEntryChangedCallback prompt_entry_changed_callback_; + PopupClosedCallback popup_closed_callback_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_JAVASCRIPT_MODAL_DIALOG_H_ diff --git a/tizen_src/chromium_impl/content/common/paths_efl.h b/tizen_src/chromium_impl/content/common/paths_efl.h index 5a4c3b2..b162d26 100644 --- a/tizen_src/chromium_impl/content/common/paths_efl.h +++ b/tizen_src/chromium_impl/content/common/paths_efl.h @@ -12,6 +12,7 @@ namespace PathsEfl { enum { PATH_START = 2000, EDJE_RESOURCE_DIR, + IMAGE_RESOURCE_DIR, WEB_DATABASE_DIR, DIR_USER_DATA, DIR_DATA_PATH, diff --git a/tizen_src/ewk/efl_integration/browser/javascript_dialog_manager_efl.cc b/tizen_src/ewk/efl_integration/browser/javascript_dialog_manager_efl.cc index 859d525..b11690a 100644 --- a/tizen_src/ewk/efl_integration/browser/javascript_dialog_manager_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/javascript_dialog_manager_efl.cc @@ -121,9 +121,9 @@ void JavaScriptDialogManagerEfl::RunJavaScriptDialog( } } - dialog_.reset(JavaScriptModalDialogEfl::CreateDialog( + dialog_.reset(JavaScriptModalDialogEfl::CreateDialogAndShow( web_contents, type, message_text, default_prompt_text, - std::move(callback))); + std::move(dialog_closed_callback_))); } void JavaScriptDialogManagerEfl::SetAlertCallback( @@ -156,7 +156,7 @@ void JavaScriptDialogManagerEfl::ExecuteDialogClosedCallBack( std::move(dialog_closed_callback_) .Run(result, base::UTF8ToUTF16(prompt_data)); if (dialog_) { - dialog_->close(); + dialog_.reset(nullptr); } } @@ -176,11 +176,11 @@ void JavaScriptDialogManagerEfl::RunBeforeUnloadDialog( EWebView* wv = WebViewFromWebContents(web_contents); wv->SmartCallback().call(0); - dialog_.reset(JavaScriptModalDialogEfl::CreateDialog( + dialog_.reset(JavaScriptModalDialogEfl::CreateDialogAndShow( web_contents, JavaScriptModalDialogEfl::NAVIGATION, base::UTF8ToUTF16( - std::string(dgettext("WebKit", "IDS_WEBVIEW_BEFOREUNLOAD_MESSAGE"))), - std::u16string(), std::move(callback))); + std::string(dgettext("WebKit", "IDS_WEBVIEW_POP_LEAVE_THIS_PAGE_Q"))), + std::u16string(), std::move(dialog_closed_callback_))); } bool JavaScriptDialogManagerEfl::HandleJavaScriptDialog( diff --git a/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.cc b/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.cc index cd9ae70..127dff1 100644 --- a/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.cc @@ -3,34 +3,26 @@ // found in the LICENSE file. #include "javascript_modal_dialog_efl.h" -#include "base/files/file_path.h" -#include "base/path_service.h" -#include "base/strings/utf_string_conversions.h" + +#include "base/callback.h" #include "common/web_contents_utils.h" -#include "content/common/paths_efl.h" #include "eweb_view.h" -#ifdef OS_TIZEN -#include -#endif +/* LCOV_EXCL_START */ +static void PromptEntryChanged(void* data, Ecore_IMF_Context* ctx, int value) { + if (value != ECORE_IMF_INPUT_PANEL_STATE_HIDE) + return; -using web_contents_utils::WebViewFromWebContents; + Evas_Object* entry = static_cast(data); + if (entry) + elm_object_focus_set(entry, EINA_FALSE); +} -//static -JavaScriptModalDialogEfl* JavaScriptModalDialogEfl::CreateDialog( - content::WebContents* web_contents, - Type type, - const std::u16string& message_text, - const std::u16string& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback callback) { - JavaScriptModalDialogEfl* dialog = - new JavaScriptModalDialogEfl(web_contents, type, message_text, - default_prompt_text, std::move(callback)); - if (!dialog->ShowJavaScriptDialog()) { - delete dialog; - dialog = NULL; +static void PopupReplyWaitFinish(EWebView* eweb_view) { + if (eweb_view) { + eweb_view->SmartCallback().call( + nullptr); } - return dialog; } JavaScriptModalDialogEfl::JavaScriptModalDialogEfl( @@ -38,372 +30,35 @@ JavaScriptModalDialogEfl::JavaScriptModalDialogEfl( Type type, const std::u16string& message_text, const std::u16string& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback callback) - : callback_(std::move(callback)), - label_(false), - type_(type), - message_text_(message_text), - default_prompt_text_(default_prompt_text), - web_view_(web_contents_utils::WebViewFromWebContents(web_contents)), - prompt_entry_(NULL), - ok_button_(NULL), - cancel_button_(NULL), - imfContext(NULL) {} - -static void promptEntryChanged(void* data, Ecore_IMF_Context* ctx, int value) { - if (value == ECORE_IMF_INPUT_PANEL_STATE_HIDE) { - Evas_Object* entry = static_cast(data); - if(entry) - elm_object_focus_set(entry, EINA_FALSE); - } -} - -static void promptEnterKeyDownCallback(void* data, Evas_Object* obj, void* eventInfo) { - elm_entry_input_panel_hide(obj); -} - -bool JavaScriptModalDialogEfl::ShowJavaScriptDialog() { - Evas_Object* parent = elm_object_top_widget_get( - elm_object_parent_widget_get(web_view_->evas_object())); - if (!parent) - parent = web_view_->evas_object(); - - Evas_Object* conformant = elm_conformant_add(parent); - if (!conformant) - return 0; - - evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_win_resize_object_add(parent, conformant); - evas_object_show(conformant); - - Evas_Object* layout_ = elm_layout_add(conformant); - if (!layout_) - return 0; - - elm_layout_theme_set(layout_, "layout", "application", "default"); - evas_object_size_hint_weight_set(layout_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(layout_); - - elm_object_content_set(conformant, layout_); - - popup_ = elm_popup_add(layout_); - - if (!popup_) - return false; - - if (type_ == PROMPT) { - if (message_text_.c_str()) - elm_object_part_text_set(popup_, "title,text", - base::UTF16ToUTF8(message_text_).c_str()); - - base::FilePath edj_dir; - base::FilePath javaScriptPopup_edj; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); - javaScriptPopup_edj = edj_dir.Append(FILE_PATH_LITERAL("JavaScriptPopup.edj")); - - Evas_Object* layout = elm_layout_add(popup_); - elm_layout_file_set(layout, javaScriptPopup_edj.AsUTF8Unsafe().c_str(), "prompt"); - evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - prompt_entry_ = elm_entry_add(popup_); - - imfContext = static_cast(elm_entry_imf_context_get(prompt_entry_)); - ecore_imf_context_input_panel_event_callback_add(imfContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, promptEntryChanged, prompt_entry_); - elm_entry_single_line_set(prompt_entry_, EINA_TRUE); - elm_entry_input_panel_return_key_type_set(prompt_entry_, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE ); - evas_object_smart_callback_add(prompt_entry_, "activated", promptEnterKeyDownCallback, this); - elm_object_text_set(prompt_entry_, - base::UTF16ToUTF8(default_prompt_text_).c_str()); - elm_entry_scrollable_set(prompt_entry_, EINA_TRUE); - elm_entry_cursor_end_set(prompt_entry_); - - elm_object_part_content_set(layout, "prompt_container", prompt_entry_); - elm_object_content_set(popup_, layout); - - cancel_button_ = elm_button_add(popup_); - elm_object_style_set(cancel_button_, "popup"); - elm_object_text_set(cancel_button_, dgettext("sys_string", "IDS_COM_SK_CANCEL")); - elm_object_part_content_set(popup_, "button1", cancel_button_); - evas_object_smart_callback_add(cancel_button_, "clicked", CancelButtonHandlerForPrompt, this); - - ok_button_ = elm_button_add(popup_); - elm_object_style_set(ok_button_, "popup"); - elm_object_text_set(ok_button_, dgettext("sys_string", "IDS_COM_SK_OK")); - elm_object_part_content_set(popup_, "button2", ok_button_); - evas_object_focus_set(ok_button_, true); - evas_object_smart_callback_add(ok_button_, "clicked", OkButtonHandlerForPrompt, this); - - } else if (type_ == NAVIGATION) { - if (message_text_.c_str()) - elm_object_part_text_set(popup_, "title,text", - base::UTF16ToUTF8(message_text_).c_str()); - - std::string question(dgettext("WebKit", "IDS_WEBVIEW_POP_LEAVE_THIS_PAGE_Q")); - - std::string message; - if (default_prompt_text_.c_str()) - message = std::string(base::UTF16ToUTF8(default_prompt_text_).c_str()) + - ("\n") + question; - else - message = question; - - setLabelText(message.c_str()); - - cancel_button_ = elm_button_add(popup_); - elm_object_style_set(cancel_button_, "popup"); - elm_object_text_set(cancel_button_, dgettext("WebKit", "IDS_WEBVIEW_BUTTON_LEAVE")); - elm_object_part_content_set(popup_, "button1", cancel_button_); - evas_object_smart_callback_add(cancel_button_, "clicked", OkButtonHandlerForPrompt, this); - - ok_button_ = elm_button_add(popup_); - elm_object_style_set(ok_button_, "popup"); - elm_object_text_set(ok_button_, dgettext("WebKit", "IDS_WEBVIEW_BUTTON_STAY")); - elm_object_part_content_set(popup_, "button2", ok_button_); - evas_object_smart_callback_add(ok_button_, "clicked", CancelButtonHandlerForPrompt, this); - } else if (type_ == ALERT) { - if (message_text_.c_str()) { - elm_object_part_text_set(popup_, "title,text", dgettext("WebKit", - "IDS_WEBVIEW_POP_JAVASCRIPT_ALERT")); - } - - if (!setLabelText(base::UTF16ToUTF8(message_text_).c_str())) - return false; - - ok_button_ = elm_button_add(popup_); - elm_object_style_set(ok_button_, "popup"); - elm_object_text_set(ok_button_, dgettext("sys_string", "IDS_COM_SK_OK")); - elm_object_part_content_set(popup_, "button1", ok_button_); - - evas_object_smart_callback_add(ok_button_, "clicked", OkButtonHandlerForAlert, this); - } else if (type_ == CONFIRM) { - if (message_text_.c_str()) { - elm_object_part_text_set(popup_, "title,text", dgettext("WebKit", - "IDS_WEBVIEW_POP_JAVASCRIPT")); - } - - if (!setLabelText(base::UTF16ToUTF8(message_text_).c_str())) - return false; - - cancel_button_ = elm_button_add(popup_); - elm_object_style_set(cancel_button_, "popup"); - elm_object_text_set(cancel_button_, dgettext("sys_string", "IDS_COM_SK_CANCEL")); - elm_object_part_content_set(popup_, "button1", cancel_button_); - evas_object_smart_callback_add(cancel_button_, "clicked", CancelButtonHandlerForConfirm, this); - - ok_button_ = elm_button_add(popup_); - elm_object_style_set(ok_button_, "popup"); - elm_object_text_set(ok_button_, dgettext("sys_string", "IDS_COM_SK_OK")); - elm_object_part_content_set(popup_, "button2", ok_button_); - evas_object_smart_callback_add(ok_button_, "clicked", OkButtonHandlerForConfirm, this); - } - -#if defined(OS_TIZEN) - if (type_ == PROMPT || type_ == NAVIGATION) - eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, CancelButtonHandlerForPrompt, this); - else if (type_ == ALERT) - eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, CancelButtonHandlerForAlert, this); - else - eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, CancelButtonHandlerForConfirm, this); -#endif - evas_object_event_callback_add(popup_, EVAS_CALLBACK_KEY_UP, KeyUpCallback, this); - evas_object_focus_set(popup_, true); - evas_object_show(popup_); - - int width = 0, height = 0; - const Ecore_Evas* ee = ecore_evas_ecore_evas_get(web_view_->GetEvas()); - ecore_evas_screen_geometry_get(ee, nullptr, nullptr, &width, &height); - evas_object_resize(popup_, width, height); - evas_object_move(popup_, 0, 0); - return true; -} - -bool JavaScriptModalDialogEfl::setLabelText(const char* message) { - if (!message) - return false; - - popupMessage_ = ("") + - std::string(elm_entry_utf8_to_markup(message)) + (""); - base::ReplaceChars(popupMessage_, "\n", "
", &popupMessage_); - - // Create label and put text to it. In case of resizing it will be reused in scroller. - Evas_Object* label = elm_label_add(popup_); - elm_label_line_wrap_set(label, ELM_WRAP_MIXED); - elm_object_text_set(label, popupMessage_.c_str()); - evas_object_show(label); - evas_object_event_callback_add(popup_, EVAS_CALLBACK_RESIZE, javascriptPopupResizeCallback, (void*)this); - elm_object_part_content_set(popup_, "default", label); - label_ = true; - - return true; -} - -void JavaScriptModalDialogEfl::javascriptPopupResizeCallback(void *data, Evas *e, Evas_Object *obj, void *event_info) { - if (!obj) - return; - - int popupHeight; - int width = 0, height = 0; -#if defined(USE_WAYLAND) -#if TIZEN_VERSION_AT_LEAST(5, 0, 0) - Ecore_Wl2_Display* wl2_display = ecore_wl2_connected_display_get(NULL); - ecore_wl2_display_screen_size_get(wl2_display, &width, &height); -#else - ecore_wl_screen_size_get(&width, &height); -#endif // TIZEN_VERSION_AT_LEAST(5, 0, 0) -#else - ecore_x_window_size_get(ecore_x_window_root_first_get(), &width, &height); -#endif - evas_object_geometry_get(obj, 0, 0, 0, &popupHeight); - - JavaScriptModalDialogEfl* popup = static_cast(data); - - if (!popup) - return; - - // Put label with displayed text to scroller in this case. - if (popupHeight > (height / 2)) { - Evas_Object* content = elm_object_part_content_get( - popup->popup_, "default"); - if (!content) - return; - - if (!popup->label_) - return; - - popup->label_ = false; - // Get label with text and remove it from content of popup. - Evas_Object* label = elm_object_part_content_unset( - popup->popup_, "default"); - - if (!label) - return; - - // Create scrollable layout. - Evas_Object* layout = elm_layout_add(popup->popup_); - - base::FilePath edj_dir; - base::FilePath javaScriptPopup_edj; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); - javaScriptPopup_edj = edj_dir.Append( - FILE_PATH_LITERAL("JavaScriptPopup.edj")); - - elm_layout_file_set( - layout, javaScriptPopup_edj.AsUTF8Unsafe().c_str(), "scroll"); - evas_object_show(layout); - evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL); - - Evas_Object* scroller = elm_scroller_add(layout); - elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_TRUE); - elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); - - evas_object_show(scroller); - elm_object_part_content_set(layout, "scroll_container", scroller); - - evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_content_set(scroller, label); - elm_object_part_content_set(popup->popup_, "default", layout); - } -} - -void JavaScriptModalDialogEfl::OkButtonHandlerForAlert(void *data, Evas_Object *obj, void *event_info) { - JavaScriptModalDialogEfl* dialog = (JavaScriptModalDialogEfl*)data; - - std::move(dialog->callback_).Run(true, std::u16string()); - evas_object_del(dialog->popup_); - dialog->close(); - - dialog->web_view_->SmartCallback().call(0); -} - -void JavaScriptModalDialogEfl::CancelButtonHandlerForAlert(void *data, Evas_Object *obj, void *event_info) { - JavaScriptModalDialogEfl* dialog = (JavaScriptModalDialogEfl*)data; - - std::move(dialog->callback_).Run(false, std::u16string()); - evas_object_del(dialog->popup_); - dialog->close(); - - dialog->web_view_->SmartCallback().call(0); -} - -void JavaScriptModalDialogEfl::OkButtonHandlerForConfirm(void *data, Evas_Object *obj, void *event_info) { - JavaScriptModalDialogEfl* dialog = (JavaScriptModalDialogEfl*)data; - - std::move(dialog->callback_).Run(true, std::u16string()); - evas_object_del(dialog->popup_); - dialog->close(); - - dialog->web_view_->SmartCallback().call(0); -} - -void JavaScriptModalDialogEfl::CancelButtonHandlerForConfirm(void *data, Evas_Object *obj, void *event_info) { - JavaScriptModalDialogEfl* dialog = (JavaScriptModalDialogEfl*)data; - - std::move(dialog->callback_).Run(false, std::u16string()); - evas_object_del(dialog->popup_); - dialog->close(); - - dialog->web_view_->SmartCallback().call(0); -} - -void JavaScriptModalDialogEfl::OkButtonHandlerForPrompt(void *data, Evas_Object *obj, void *event_info) { - JavaScriptModalDialogEfl* dialog = (JavaScriptModalDialogEfl*)data; - - std::string prompt_data; - if (dialog->prompt_entry_) - prompt_data = elm_entry_entry_get(dialog->prompt_entry_); - - std::move(dialog->callback_).Run(true, base::UTF8ToUTF16(prompt_data)); - evas_object_del(dialog->popup_); - dialog->close(); - - dialog->web_view_->SmartCallback().call(0); -} - -void JavaScriptModalDialogEfl::CancelButtonHandlerForPrompt(void *data, Evas_Object *obj, void *event_info) { - JavaScriptModalDialogEfl* dialog = (JavaScriptModalDialogEfl*)data; - - std::move(dialog->callback_).Run(false, std::u16string()); - evas_object_del(dialog->popup_); - dialog->close(); - - dialog->web_view_->SmartCallback().call(0); -} - -// General key up callback for all platforms designed to handle keyboard HW Back key -void JavaScriptModalDialogEfl::KeyUpCallback(void *data, Evas *e, Evas_Object *obj, void *event_info) { - Evas_Event_Key_Up* key_struct = static_cast(event_info); - if (!web_contents_utils::MapsToHWBackKey(key_struct->keyname)) - return; - - JavaScriptModalDialogEfl* dialog = static_cast(data); - - if (dialog->type_ == PROMPT || dialog->type_ == NAVIGATION) - CancelButtonHandlerForPrompt(data, obj, event_info); - else if (dialog->type_ == ALERT) - CancelButtonHandlerForAlert(data, obj, event_info); - else - CancelButtonHandlerForConfirm(data, obj, event_info); -} - -void JavaScriptModalDialogEfl::close() { - if(popup_) { - evas_object_del(popup_); - popup_ = 0; + content::JavaScriptDialogManager::DialogClosedCallback& callback) + : JavaScriptModalDialog(web_contents, + type, + message_text, + default_prompt_text, + std::move(callback), + nullptr) {} + +// static +JavaScriptModalDialogEfl* JavaScriptModalDialogEfl::CreateDialogAndShow( + content::WebContents* web_contents, + Type type, + const std::u16string& message_text, + const std::u16string& default_prompt_text, + content::JavaScriptDialogManager::DialogClosedCallback callback) { + auto* eweb_view = web_contents_utils::WebViewFromWebContents(web_contents); + auto* dialog = new JavaScriptModalDialogEfl(web_contents, type, message_text, + default_prompt_text, callback); + dialog->SetPromptEntryChangedCallback(PromptEntryChanged); + dialog->SetParentEvasObject(eweb_view->evas_object()); + + base::OnceCallback once_callback = + base::BindOnce(&PopupReplyWaitFinish, eweb_view); + dialog->SetPopupClosedCallback(once_callback); + if (!dialog->ShowJavaScriptDialog()) { + LOG(ERROR) << "Could not create javascript dialog."; + delete dialog; + dialog = nullptr; } - prompt_entry_ = 0; - imfContext = 0; -} - -void JavaScriptModalDialogEfl::SetPopupSize(int width, int height) { - if (!popup_) - return; - - evas_object_resize(popup_, width, height); - evas_object_move(popup_, 0, 0); -} - -JavaScriptModalDialogEfl::~JavaScriptModalDialogEfl() { - close(); + return dialog; } +/* LCOV_EXCL_STOP */ diff --git a/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.h b/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.h index 2f016b5..701513e6 100644 --- a/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.h +++ b/tizen_src/ewk/efl_integration/browser/javascript_modal_dialog_efl.h @@ -5,71 +5,33 @@ #ifndef JAVA_SCRIPT_MODAL_DIALOG_EFL_H_ #define JAVA_SCRIPT_MODAL_DIALOG_EFL_H_ -#include "content/public/browser/javascript_dialog_manager.h" #include -#include -#include -#include "base/callback.h" -#include "ecore_x_wayland_wrapper.h" +#include "content/browser/javascript_dialog/javascript_modal_dialog.h" -class EWebView; +// to avoid build errors +#include "ecore_x_wayland_wrapper.h" namespace content { class WebContentsDelegateEfl; } -class JavaScriptModalDialogEfl { +class JavaScriptModalDialogEfl : public content::JavaScriptModalDialog { public: - enum Type { - ALERT, - CONFIRM, - NAVIGATION, - PROMPT - }; - - virtual ~JavaScriptModalDialogEfl(); - static void OkButtonHandlerForAlert(void *data, Evas_Object *obj, void *event_info); - static void CancelButtonHandlerForAlert(void *data, Evas_Object *obj, void *event_info); - static void OkButtonHandlerForConfirm(void *data, Evas_Object *obj, void *event_info); - static void CancelButtonHandlerForConfirm(void *data, Evas_Object *obj, void *event_info); - static void OkButtonHandlerForPrompt(void *data, Evas_Object *obj, void *event_info); - static void CancelButtonHandlerForPrompt(void *data, Evas_Object *obj, void *event_info); - static void javascriptPopupResizeCallback(void *data, Evas *e, Evas_Object *obj, void *event_info); - static JavaScriptModalDialogEfl* CreateDialog( + static JavaScriptModalDialogEfl* CreateDialogAndShow( content::WebContents* web_contents, Type type, const std::u16string& message_text, const std::u16string& default_prompt_text, content::JavaScriptDialogManager::DialogClosedCallback callback); - static void KeyUpCallback(void *data, Evas *e, Evas_Object *obj, void *event_info); - bool ShowJavaScriptDialog(); - Evas_Object* popupAdd(); - bool setLabelText(const char* message); - void close(); - void SetPopupSize(int width, int height); - Evas_Object* popup_; - - private: JavaScriptModalDialogEfl( content::WebContents* web_contents, Type type, const std::u16string& message_text, const std::u16string& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback callback); - - content::JavaScriptDialogManager::DialogClosedCallback callback_; - bool label_; - Type type_; - std::u16string message_text_; - std::u16string default_prompt_text_; - EWebView* web_view_; - Evas_Object* prompt_entry_; - Evas_Object* ok_button_; - Evas_Object* cancel_button_; - std::string popupMessage_; - Ecore_IMF_Context* imfContext; + content::JavaScriptDialogManager::DialogClosedCallback& callback); + ~JavaScriptModalDialogEfl() = default; // LCOV_EXCL_LINE }; #endif /* JAVA_SCRIPT_MODAL_DIALOG_EFL_H_ */ diff --git a/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc b/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc index 275d7fe..d943f6e 100644 --- a/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc +++ b/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc @@ -528,7 +528,7 @@ void ContextMenuControllerEfl::OnDiskDownload( download::DownloadItem* item, download::DownloadInterruptReason interrupt_reason) { if (!item) { - save_fail_dialog_.reset(JavaScriptModalDialogEfl::CreateDialog( + save_fail_dialog_.reset(JavaScriptModalDialogEfl::CreateDialogAndShow( &web_contents_, JavaScriptModalDialogEfl::ALERT, base::UTF8ToUTF16( std::string(dgettext("WebKit", "IDS_WEBVIEW_POP_FAIL"))), @@ -554,7 +554,7 @@ void ContextMenuControllerEfl::OnDownloadUpdated( clipboard_download_items_.erase(download); } if (disk_download_items_.find(download) != disk_download_items_.end()) { - file_saved_dialog_.reset(JavaScriptModalDialogEfl::CreateDialog( + file_saved_dialog_.reset(JavaScriptModalDialogEfl::CreateDialogAndShow( &web_contents_, JavaScriptModalDialogEfl::ALERT, base::UTF8ToUTF16( std::string(dgettext("WebKit", "IDS_WEBVIEW_POP_SAVED"))), -- 2.7.4