From dffd083eb74d1b63fe3f664db6d0b46e18ecf909 Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Tue, 17 Jan 2023 14:39:53 +0530 Subject: [PATCH 01/16] Add WebContentsViewAuraHelperEfl class This patch introduces helper class for WebContentsViewAura for routing some calls to efl delegate classes. Also cleans up unnecessary code. Change-Id: I2949b17af7cdd05610973fb7f7b616b6d466cdb8 Signed-off-by: Gajendra N --- .../browser/web_contents/web_contents_view_aura.cc | 12 +- .../browser/web_contents/web_contents_view_aura.h | 14 ++ .../chromium_impl/content/browser/browser_efl.gni | 2 + .../web_contents_view_aura_helper_efl.cc | 181 +++++++++++++++++++++ .../web_contents_view_aura_helper_efl.h | 100 ++++++++++++ tizen_src/ewk/efl_integration/eweb_view.cc | 31 ++-- tizen_src/ewk/efl_integration/eweb_view.h | 5 +- 7 files changed, 322 insertions(+), 23 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.cc create mode 100644 tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.h diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index bdbb5a3..1662f20 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc @@ -711,7 +711,17 @@ WebContentsViewAura::WebContentsViewAura( current_rvh_for_drag_(ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE), drag_in_progress_(false), - init_rwhv_with_null_parent_for_testing_(false) {} + init_rwhv_with_null_parent_for_testing_(false) { +#if BUILDFLAG(IS_EFL) + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableOffscreenRendering)) { + return; + } + + wcva_helper_ = std::make_unique( + this, web_contents_, delegate_.get()); +#endif +} WebContentsViewAura::~WebContentsViewAura() { if (!window_) diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h index 3425436..db0945e 100644 --- a/content/browser/web_contents/web_contents_view_aura.h +++ b/content/browser/web_contents/web_contents_view_aura.h @@ -34,6 +34,10 @@ #include "ui/base/dragdrop/drop_target_event.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h" +#if BUILDFLAG(IS_EFL) +#include "content/browser/web_contents/web_contents_view_aura_helper_efl.h" +#endif + namespace ui { class DropTargetEvent; class TouchSelectionController; @@ -76,6 +80,12 @@ class CONTENT_EXPORT WebContentsViewAura static void InstallCreateHookForTests( RenderWidgetHostViewCreateFunction create_render_widget_host_view); +#if BUILDFLAG(IS_EFL) + WebContentsViewAuraHelperEfl* wcva_helper() const { + return wcva_helper_.get(); + } +#endif + private: // Just the metadata from DropTargetEvent that's safe and cheap to copy to // help locate drop events in the callback. @@ -398,6 +408,10 @@ class CONTENT_EXPORT WebContentsViewAura // Non-null when the WebContents is being captured for video. std::unique_ptr video_capture_lock_; +#if BUILDFLAG(IS_EFL) + std::unique_ptr wcva_helper_; +#endif + base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index 668d5d0..4a1548a 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -87,6 +87,8 @@ external_content_browser_efl_sources = [ "//tizen_src/chromium_impl/content/browser/tracing/tracing_controller_efl.h", "//tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc", "//tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.h", + "//tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.cc", + "//tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.h", "//tizen_src/chromium_impl/content/browser/web_contents/web_drag_dest_efl.cc", "//tizen_src/chromium_impl/content/browser/web_contents/web_drag_dest_efl.h", "//tizen_src/chromium_impl/content/browser/web_contents/web_drag_source_efl.cc", diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.cc b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.cc new file mode 100644 index 0000000..abdc627 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.cc @@ -0,0 +1,181 @@ +// Copyright (c) 2022 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/web_contents/web_contents_view_aura_helper_efl.h" + +#include "content/browser/web_contents/web_contents_view_aura.h" + +namespace content { + +WebContentsViewAuraHelperEfl::WebContentsViewAuraHelperEfl( + WebContentsViewAura* wcva, + WebContentsImpl* web_contents, + WebContentsViewDelegate* delegate) + : wcv_aura_(wcva), web_contents_(web_contents), view_delegate_(delegate) {} + +WebContentsViewAuraHelperEfl::~WebContentsViewAuraHelperEfl() { + popup_client_.reset(); +} + +void WebContentsViewAuraHelperEfl::DidSelectPopupMenuItems( + std::vector& indices) { + popup_client_->DidAcceptIndices(indices); +} + +#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) +void WebContentsViewAuraHelperEfl::ShowPopupMenu( + RenderFrameHost* render_frame_host, + mojo::PendingRemote popup_client, + const gfx::Rect& bounds, + int item_height, + double item_font_size, + int selected_item, + std::vector items, + bool right_aligned, + bool allow_multiple_selection) { + if (popup_client_) + HidePopupMenu(); + + popup_client_.Bind(std::move(popup_client)); + popup_client_.set_disconnect_handler(base::BindOnce( + &WebContentsViewAuraHelperEfl::HidePopupMenu, base::Unretained(this))); + + if (efl_delegate_) { + efl_delegate_->ShowPopupMenu( + render_frame_host, bounds, item_height, item_font_size, selected_item, + std::move(items), right_aligned, allow_multiple_selection); + } +} + +void WebContentsViewAuraHelperEfl::HidePopupMenu() { + if (efl_delegate_) + efl_delegate_->HidePopupMenu(); + popup_client_.reset(); +} + +void WebContentsViewAuraHelperEfl::DidCancelPopupMenu() { + if (popup_client_) + popup_client_->DidCancel(); +} +#endif + +void WebContentsViewAuraHelperEfl::SetEflDelegate( + WebContentsEflDelegate* delegate) { + efl_delegate_ = delegate; +} + +WebContentsEflDelegate* WebContentsViewAuraHelperEfl::GetEflDelegate() { + return efl_delegate_; +} + +void WebContentsViewAuraHelperEfl::UpdateDragDest(RenderViewHost* host) { + // Drag-and-drop is entirely managed by BrowserPluginGuest for guest + // processes in a largely platform independent way. WebDragDestEfl + // will result in spurious messages being sent to the guest process which + // will violate assumptions. + if (host->GetProcess() && host->GetProcess()->IsForGuestsOnly()) { + DCHECK(!drag_dest_); + return; + } + + RenderWidgetHostView* view = web_contents_->GetRenderWidgetHostView(); + if (!view) + return; + + // Create the new drag_dest_. + drag_dest_.reset(new WebDragDestEfl(web_contents_)); + drag_dest_->SetPageScaleFactor(page_scale_factor_); + + if (view_delegate_) + drag_dest_->SetDelegate(view_delegate_->GetDragDestDelegate()); +} + +void WebContentsViewAuraHelperEfl::StartDragging( + const DropData& drop_data, + blink::DragOperationsMask allowed_ops, + const gfx::ImageSkia& image, + const gfx::Vector2d& image_offset, + const blink::mojom::DragEventSourceInfo& event_info, + RenderWidgetHostImpl* source_rwh) { + if (drag_dest_) { + drag_dest_->SetDropData(drop_data); + drag_dest_->SetAction(allowed_ops); + } + + if (!drag_source_) { + drag_source_.reset(new WebDragSourceEfl(web_contents_)); + drag_source_->SetPageScaleFactor(page_scale_factor_); + } + + if (!drag_source_->StartDragging(drop_data, allowed_ops, event_info.location, + *image.bitmap(), image_offset)) { + web_contents_->SystemDragEnded(source_rwh); + } +} + +DropData* WebContentsViewAuraHelperEfl::GetDropData() const { + if (drag_dest_) + return drag_dest_->GetDropData(); + return nullptr; +} + +bool WebContentsViewAuraHelperEfl::IsDragging() const { + if (!drag_source_) + return false; + return drag_source_->IsDragging(); +} + +void WebContentsViewAuraHelperEfl::SetPageScaleFactor(float scale) { + page_scale_factor_ = scale; + if (drag_source_) + drag_source_->SetPageScaleFactor(scale); + if (drag_dest_) + drag_dest_->SetPageScaleFactor(scale); +} + +void WebContentsViewAuraHelperEfl::OnSelectionRectReceived( + const gfx::Rect& selection_rect) const { +#if !defined(EWK_BRINGUP) + view_delegate_->OnSelectionRectReceived(selection_rect); +#endif +} + +void WebContentsViewAuraHelperEfl::ShowContextMenu( + const ContextMenuParams& params) { + if (efl_delegate_) + efl_delegate_->ShowContextMenu(params); +} + +void WebContentsViewAuraHelperEfl::CancelContextMenu(int request_id) { + if (efl_delegate_) + efl_delegate_->CancelContextMenu(request_id); +} + +bool WebContentsViewAuraHelperEfl::ImePanelEnabled() const { +#if !defined(EWK_BRINGUP) + if (efl_delegate_) + return efl_delegate_->ImePanelEnabled(); +#endif + return true; +} + +bool WebContentsViewAuraHelperEfl::ImeHandleKeyEventEnabled() const { +#if !defined(EWK_BRINGUP) + if (efl_delegate_) + return efl_delegate_->ImeHandleKeyEventEnabled(); +#endif + return true; +} + +void WebContentsViewAuraHelperEfl::OnOverscrolled( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta) { +#if !defined(EWK_BRINGUP) + if (efl_delegate_) + efl_delegate_->OnOverscrolled(accumulated_overscroll, + latest_overscroll_delta); +#endif +} + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.h b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.h new file mode 100644 index 0000000..a732c19 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_view_aura_helper_efl.h @@ -0,0 +1,100 @@ +// Copyright (c) 2022 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 WEB_CONTENTS_VIEW_AURA_HELPER_EFL +#define WEB_CONTENTS_VIEW_AURA_HELPER_EFL + +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/browser/web_contents/web_contents_view.h" +#include "content/browser/web_contents/web_drag_dest_efl.h" +#include "content/browser/web_contents/web_drag_source_efl.h" +#include "content/common/buildflags.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents_efl_delegate.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/common/page/drag_operation.h" +#include "third_party/blink/public/mojom/choosers/popup_menu.mojom.h" +#include "ui/gfx/image/image_skia.h" + +namespace content { + +class RenderFrameHost; +class RenderWidgetHostImpl; +class RenderWidgetHostViewBase; +class WebContentsViewAura; +class WebContentsImpl; + +class CONTENT_EXPORT WebContentsViewAuraHelperEfl { + public: + WebContentsViewAuraHelperEfl(WebContentsViewAura* wcva, + WebContentsImpl* web_contents, + WebContentsViewDelegate* delegate); + ~WebContentsViewAuraHelperEfl(); + + WebContentsViewAuraHelperEfl(const WebContentsViewAuraHelperEfl&) = delete; + WebContentsViewAuraHelperEfl& operator=(const WebContentsViewAuraHelperEfl&) = + delete; + + void DidSelectPopupMenuItems(std::vector& indices); +#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) + void ShowPopupMenu( + RenderFrameHost* render_frame_host, + mojo::PendingRemote popup_client, + const gfx::Rect& bounds, + int item_height, + double item_font_size, + int selected_item, + std::vector items, + bool right_aligned, + bool allow_multiple_selection); + void HidePopupMenu(); + void DidCancelPopupMenu(); +#endif + bool ImePanelEnabled() const; + bool ImeHandleKeyEventEnabled() const; + + void SetEflDelegate(WebContentsEflDelegate*); + WebContentsEflDelegate* GetEflDelegate(); + void UpdateDragDest(RenderViewHost* host); + void StartDragging(const DropData& drop_data, + blink::DragOperationsMask allowed_ops, + const gfx::ImageSkia& image, + const gfx::Vector2d& image_offset, + const blink::mojom::DragEventSourceInfo& event_info, + RenderWidgetHostImpl* source_rwh); + + DropData* GetDropData() const; + bool IsDragging() const; + void SetPageScaleFactor(float); + + void OnSelectionRectReceived(const gfx::Rect& selection_rect) const; + void ShowContextMenu(const ContextMenuParams& params); + void CancelContextMenu(int request_id); + + void OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta); + + private: + mojo::Remote popup_client_; + + WebContentsViewAura* wcv_aura_ = nullptr; + WebContentsImpl* web_contents_ = nullptr; + + // Delegate owned by WebContentsImplEfl + WebContentsEflDelegate* efl_delegate_ = nullptr; + + // Our optional, generic views wrapper. + WebContentsViewDelegate* view_delegate_ = nullptr; + + // Helpers handling drag source/destination related interactions with EFL. + std::unique_ptr drag_source_; + std::unique_ptr drag_dest_; + float page_scale_factor_ = 1.0f; +}; + +} // namespace content + +#endif diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 3e44712..7da077e 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -26,6 +26,8 @@ #include "content/browser/renderer_host/ui_events_helper.h" #include "content/browser/web_contents/web_contents_impl_efl.h" #include "content/browser/web_contents/web_contents_view.h" +#include "content/browser/web_contents/web_contents_view_aura.h" +#include "content/browser/web_contents/web_contents_view_aura_helper_efl.h" #include "content/common/content_client_export.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_task_traits.h" @@ -185,11 +187,6 @@ void EWebView::Initialize() { scroll_detector_.reset(new ScrollDetector(this)); - web_contents_delegate_.reset(new WebContentsDelegateEfl(this)); - web_contents_->SetDelegate(web_contents_delegate_.get()); - back_forward_list_.reset( - new _Ewk_Back_Forward_List(web_contents_->GetController())); - DCHECK(web_contents_->GetRenderViewHost()); // Settings (content::WebPreferences) will be initalized by // RenderViewHostImpl::ComputeWebkitPrefs() based on command line switches. @@ -311,6 +308,11 @@ content::RenderWidgetHostViewAura* EWebView::rwhva() const { web_contents_->GetRenderWidgetHostView()); } +content::WebContentsViewAura* EWebView::wcva() const { + WebContentsImpl* wc = static_cast(web_contents_.get()); + return static_cast(wc->GetView()); +} + void EWebView::ResetContextMenuController() { return context_menu_.reset(); } @@ -645,12 +647,7 @@ void EWebView::HandleTouchEvents(Ewk_Touch_Event_Type type, } #endif } -#if !defined(USE_AURA) -content::WebContentsViewEfl* EWebView::GetWebContentsViewEfl() const { - WebContentsImpl* wc = static_cast(web_contents_.get()); - return static_cast(wc->GetView()); -} -#endif + bool EWebView::TouchEventsEnabled() const { return touch_events_enabled_; } @@ -1965,9 +1962,7 @@ double EWebView::GetScale() { void EWebView::DidChangePageScaleFactor(double scale_factor) { page_scale_factor_ = scale_factor; -#if !defined(USE_AURA) - GetWebContentsViewEfl()->SetPageScaleFactor(scale_factor); -#endif + wcva()->wcva_helper()->SetPageScaleFactor(scale_factor); SetScaledContentsSize(); } @@ -2114,11 +2109,7 @@ void EWebView::SetCertificatePem(const std::string& certificate) { } bool EWebView::IsDragging() const { -#if !defined(USE_AURA) - return GetWebContentsViewEfl()->IsDragging(); -#else - return false; -#endif + return wcva()->wcva_helper()->IsDragging(); } void EWebView::ShowFileChooser(content::RenderFrameHost* render_frame_host, @@ -2302,6 +2293,8 @@ void EWebView::InitializeContent() { WebContentsImplEfl* wc_efl = static_cast(web_contents_.get()); wc_efl->SetEflDelegate(new WebContentsEflDelegateEwk(this)); + wcva()->wcva_helper()->SetEflDelegate(wc_efl->GetEflDelegate()); + back_forward_list_.reset( new _Ewk_Back_Forward_List(web_contents_->GetController())); diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 83b9bd4..6b09cf1 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -66,6 +66,7 @@ class RenderFrameHost; class RenderViewHost; class RenderWidgetHostViewAura; class WebContentsDelegateEfl; +class WebContentsViewAura; class ContextMenuControllerEfl; class PopupControllerEfl; } @@ -184,6 +185,7 @@ class EWebView { content::WebContentsEflDelegate::WebContentsCreateCallback); static Evas_Object* GetHostWindowDelegate(const content::WebContents*); + content::WebContentsViewAura* wcva() const; content::RenderWidgetHostViewAura* rwhva() const; Ewk_Context* context() const { return context_.get(); } Evas_Object* evas_object() const { return evas_object_; } @@ -506,9 +508,6 @@ class EWebView { int y, Ewk_Hit_Test_Mode mode, WebViewAsyncRequestHitTestDataCallback* cb); -#if !defined(USE_AURA) - content::WebContentsViewEfl* GetWebContentsViewEfl() const; -#endif #if BUILDFLAG(IS_TIZEN) && !defined(EWK_BRINGUP) static void cameraResultCb(service_h request, service_h reply, -- 2.7.4 From 6d30a22e404e60873f06d1c284c80ef899151588 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Mon, 16 Jan 2023 18:15:08 +0530 Subject: [PATCH 02/16] [M108 Migration] Bring up Geolocation This patch brings up Geolocation feature to M108. Reference: https://review.tizen.org/gerrit/274261/ Change-Id: I004a61ee5b1800c97c5ca97f3714e5fce16a8a59 Signed-off-by: Ayush Kumar --- services/device/geolocation/location_arbitrator.cc | 17 ++- .../modules/geolocation/geolocation_coordinates.cc | 11 +- tizen_src/ewk/efl_integration/BUILD.gn | 9 -- .../browser/geolocation/location_provider_efl.cc | 116 ++++++++++++--------- .../browser/geolocation/location_provider_efl.h | 53 ++++++---- .../efl_integration/content_browser_client_efl.cc | 3 - .../private/ewk_geolocation_private.cc | 9 +- .../private/ewk_geolocation_private.h | 2 +- 8 files changed, 130 insertions(+), 90 deletions(-) diff --git a/services/device/geolocation/location_arbitrator.cc b/services/device/geolocation/location_arbitrator.cc index 723328e..f875edf 100644 --- a/services/device/geolocation/location_arbitrator.cc +++ b/services/device/geolocation/location_arbitrator.cc @@ -17,6 +17,11 @@ #include "services/device/public/cpp/geolocation/geoposition.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +#if BUILDFLAG(IS_TIZEN) +#include "base/base_switches.h" +#include "base/command_line.h" +#endif + namespace device { // To avoid oscillations, set this to twice the expected update interval of a @@ -149,8 +154,8 @@ LocationArbitrator::NewNetworkLocationProvider( scoped_refptr url_loader_factory, const std::string& api_key) { DCHECK(url_loader_factory); -#if BUILDFLAG(IS_ANDROID) - // Android uses its own SystemLocationProvider. +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_TIZEN) + // Android/Tizen uses its own SystemLocationProvider. return nullptr; #else return std::make_unique( @@ -161,6 +166,14 @@ LocationArbitrator::NewNetworkLocationProvider( std::unique_ptr LocationArbitrator::NewSystemLocationProvider() { +#if BUILDFLAG(IS_TIZEN) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableOffscreenRendering)) { + return device::NewSystemLocationProvider(main_task_runner_, + geolocation_manager_); + } +#endif + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) return nullptr; #else diff --git a/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc b/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc index fb01ad3..54930be 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc +++ b/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc @@ -25,6 +25,10 @@ #include "third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h" +#if BUILDFLAG(IS_TIZEN) +#include +#endif + namespace blink { absl::optional GeolocationCoordinates::altitude() const { @@ -40,8 +44,13 @@ absl::optional GeolocationCoordinates::altitudeAccuracy() const { } absl::optional GeolocationCoordinates::heading() const { - if (can_provide_heading_) + if (can_provide_heading_) { +#if BUILDFLAG(IS_TIZEN) + if (can_provide_speed_ && speed_ == 0.0) + return std::numeric_limits::quiet_NaN(); +#endif return heading_; + } return absl::nullopt; } diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index e9d015b..da0da3390 100644 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -143,13 +143,6 @@ shared_library("chromium-ewk") { "browser/geolocation/location_provider_efl.cc", "browser/geolocation/location_provider_efl.h", ] - if (ewk_bringup) { - # FIXME: EWK_BRINGUP - exclude_source_set -= [ - "browser/geolocation/location_provider_efl.cc", - "browser/geolocation/location_provider_efl.h", - ] - } } # TODO : Below dependency is set in chromium/device/battery_tizen.gypi, @@ -605,8 +598,6 @@ shared_library("chromium-ewk") { # FIXME: Followings are guarded just for bringup. if (ewk_bringup) { sources -= [ - "browser/geolocation/location_provider_efl.cc", - "browser/geolocation/location_provider_efl.h", "browser/vibration/vibration_provider_client.cc", "browser/vibration/vibration_provider_client.h", "permission_popup_manager.cc", diff --git a/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.cc b/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.cc index 13bb051..2b8b815 100644 --- a/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.cc @@ -3,74 +3,98 @@ // found in the LICENSE file. #include "browser/geolocation/location_provider_efl.h" - #include "base/bind.h" #include "base/logging.h" #include "base/time/time.h" -#include "base/message_loop/message_loop.h" -#include "content/public/common/geoposition.h" -namespace content { +#include "services/device/public/cpp/geolocation/geolocation_manager.h" -LocationProviderEfl::LocationProviderEfl() - : LocationProviderBase() - , location_manager_(NULL) - , geolocation_message_loop_(base::MessageLoop::current()) { +namespace device { + +static double KilometerPerHourToMeterPerSecond(double kilometer_per_hour) { + return kilometer_per_hour * 5 / 18; } +LocationProviderEfl::LocationProviderEfl() + : location_manager_(nullptr), + task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + LocationProviderEfl::~LocationProviderEfl() { StopProvider(); } // static -void LocationProviderEfl::GeoPositionChangedCb( - double latitude, double longitude, double altitude, - time_t timestamp, void* user_data) { +void LocationProviderEfl::GeoPositionChangedCb(double latitude, + double longitude, + double altitude, + double speed, + double direction, + double horizontal_accuracy, + time_t timestamp, + void* user_data) { LocationProviderEfl* location_provider = static_cast(user_data); DCHECK(location_provider); - location_provider->NotifyPositionChanged( - latitude, longitude, altitude, timestamp); + location_provider->NotifyPositionChanged(latitude, longitude, altitude, speed, + direction, horizontal_accuracy, + timestamp); +} +void LocationProviderEfl::NotifyCallback(const mojom::Geoposition& position) { + if (!callback_.is_null()) + callback_.Run(this, position); } -void LocationProviderEfl::NotifyPositionChanged( - double latitude, double longitude, double altitude, time_t timestamp) { - location_accuracy_level_e level; +void LocationProviderEfl::SetUpdateCallback( + const LocationProviderUpdateCallback& callback) { + callback_ = callback; +} +void LocationProviderEfl::NotifyPositionChanged(double latitude, + double longitude, + double altitude, + double speed, + double direction, + double horizontal_accuracy, + time_t timestamp) { DCHECK(location_manager_); - DCHECK(geolocation_message_loop_); + DCHECK(task_runner_); last_position_.latitude = latitude; last_position_.longitude = longitude; + last_position_.altitude = altitude; last_position_.timestamp = base::Time::FromTimeT(timestamp); + last_position_.speed = KilometerPerHourToMeterPerSecond(speed); + last_position_.heading = direction; + location_accuracy_level_e level; location_manager_get_last_accuracy(location_manager_, &level, &last_position_.accuracy, &last_position_.altitude_accuracy); - base::Closure task = base::BindOnce(&LocationProviderEfl::NotifyCallback, - base::Unretained(this), last_position_); - geolocation_message_loop_->PostTask(FROM_HERE, task); + base::OnceClosure task = + base::BindOnce(&LocationProviderEfl::NotifyCallback, + base::Unretained(this), last_position_); + task_runner_->PostTask(FROM_HERE, std::move(task)); } -bool LocationProviderEfl::StartProvider(bool high_accuracy) { +void LocationProviderEfl::StartProvider(bool high_accuracy) { if (location_manager_) { // already started! - return false; + return; } int ret = location_manager_create(LOCATIONS_METHOD_HYBRID, &location_manager_); if (ret != LOCATIONS_ERROR_NONE) { LOG(ERROR) << "Failed to create location manager!"; - return false; + return; } - ret = location_manager_set_position_updated_cb( - location_manager_, GeoPositionChangedCb, 1, this); + ret = location_manager_set_location_changed_cb(location_manager_, + GeoPositionChangedCb, 1, this); if (ret != LOCATIONS_ERROR_NONE) { LOG(ERROR) << "Failed to register position changed callback!"; location_manager_destroy(location_manager_); - location_manager_ = NULL; - return false; + location_manager_ = nullptr; + return; } ret = static_cast(location_manager_start(location_manager_)); @@ -78,40 +102,34 @@ bool LocationProviderEfl::StartProvider(bool high_accuracy) { LOG(ERROR) << "Failed to start location manager: " << ret; location_manager_unset_position_updated_cb(location_manager_); location_manager_destroy(location_manager_); - location_manager_ = NULL; - return false; + location_manager_ = nullptr; } - - return true; } void LocationProviderEfl::StopProvider() { - if (location_manager_) { - int ret = location_manager_stop(location_manager_); - if (ret == LOCATIONS_ERROR_NONE) { - location_manager_unset_position_updated_cb(location_manager_); - } + if (!location_manager_) + return; - // TODO: didn't stop but destroy? - location_manager_destroy(location_manager_); - location_manager_ = NULL; - } -} + int ret = location_manager_stop(location_manager_); + if (ret == LOCATIONS_ERROR_NONE) + location_manager_unset_position_updated_cb(location_manager_); -void LocationProviderEfl::GetPosition(Geoposition* position) { - DCHECK(position); - *position = last_position_; + // TODO: didn't stop but destroy? + location_manager_destroy(location_manager_); + location_manager_ = nullptr; } -void LocationProviderEfl::RequestRefresh() { +const mojom::Geoposition& LocationProviderEfl::GetPosition() { + return last_position_; } void LocationProviderEfl::OnPermissionGranted() { } -//static -LocationProvider* LocationProviderEfl::Create() { - return new LocationProviderEfl(); +std::unique_ptr NewSystemLocationProvider( + scoped_refptr main_task_runner, + GeolocationManager* geolocation_manager) { + return base::WrapUnique(new LocationProviderEfl()); } -} // namespace content +} // namespace device diff --git a/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.h b/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.h index b47d447..5616c1b 100644 --- a/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.h +++ b/tizen_src/ewk/efl_integration/browser/geolocation/location_provider_efl.h @@ -6,43 +6,50 @@ #define LOCATION_PROVIDER_EFL_H_ #include "base/compiler_specific.h" -#include "content/browser/geolocation/location_provider_base.h" -#include "content/public/common/geoposition.h" +#include "base/memory/ptr_util.h" +#include "services/device/geolocation/geolocation_provider.h" +#include "services/device/public/cpp/geolocation/geoposition.h" +#include "services/device/public/cpp/geolocation/location_provider.h" #include -namespace base { -class MessageLoop; -} +namespace device { -namespace content { - -class LocationProviderEfl : public LocationProviderBase { +class LocationProviderEfl : public LocationProvider { public: - virtual ~LocationProviderEfl(); + LocationProviderEfl(); + ~LocationProviderEfl() override; - static LocationProvider* Create(); + void SetUpdateCallback( + const LocationProviderUpdateCallback& callback) override; + void StartProvider(bool high_accuracy) override; + void StopProvider() override; + const mojom::Geoposition& GetPosition() override; - virtual bool StartProvider(bool high_accuracy) override; - virtual void StopProvider() override; - virtual void GetPosition(Geoposition* position) override; - virtual void RequestRefresh() override; - virtual void OnPermissionGranted() override; + void OnPermissionGranted() override; private: - LocationProviderEfl(); - LocationProviderEfl(const LocationProviderEfl&) = delete; LocationProviderEfl& operator=(const LocationProviderEfl&) = delete; - static void GeoPositionChangedCb(double, double, double, time_t, void*); - void NotifyPositionChanged(double, double, double, time_t); - - Geoposition last_position_; + static void GeoPositionChangedCb(double, + double, + double, + double, + double, + double, + time_t, + void*); + void + NotifyPositionChanged(double, double, double, double, double, double, time_t); + void NotifyCallback(const mojom::Geoposition&); + + mojom::Geoposition last_position_; location_manager_h location_manager_; - base::MessageLoop* geolocation_message_loop_; + scoped_refptr task_runner_; + LocationProviderUpdateCallback callback_; }; -} // namespace content +} // namespace device #endif // LOCATION_PROVIDER_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 878d02a..7b36d0f 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -35,9 +35,6 @@ #include "web_contents_view_delegate_ewk.h" #if BUILDFLAG(IS_TIZEN) -#if !defined(EWK_BRINGUP) -#include "browser/geolocation/location_provider_efl.h" -#endif #include #include "content/browser/speech/tts_message_filter_efl.h" #endif diff --git a/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.cc b/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.cc index a705b07..4091a6d 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "ewk_geolocation_private.h" +#include "content/public/browser/browser_thread.h" #include "private/ewk_security_origin_private.h" - -#include +#include "services/device/geolocation/geolocation_provider_impl.h" using content::BrowserThread; using namespace blink::mojom; @@ -22,6 +22,11 @@ _Ewk_Geolocation_Permission_Request::~_Ewk_Geolocation_Permission_Request() { } void _Ewk_Geolocation_Permission_Request::runCallback(bool allowed) { + if (allowed) { + device::GeolocationProviderImpl::GetInstance() + ->UserDidOptIntoLocationServices(); + } + std::move(callback_).Run(allowed ? PermissionStatus::GRANTED : PermissionStatus::DENIED); } diff --git a/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.h b/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.h index e3619d0..ab83c11 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_geolocation_private.h @@ -20,7 +20,7 @@ class _Ewk_Geolocation_Permission_Request : public Ewk_Suspendable_Object{ _Ewk_Geolocation_Permission_Request( const GURL& origin_url, base::OnceCallback callback); - ~_Ewk_Geolocation_Permission_Request(); + ~_Ewk_Geolocation_Permission_Request() override; _Ewk_Security_Origin* GetOrigin() const { return origin_; } -- 2.7.4 From 196de70fcf647c674e1ef5e2123745286a69f4f2 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Tue, 17 Jan 2023 09:29:53 +0530 Subject: [PATCH 03/16] [M108 Migration][NativeControl] InputPicker Migration This patch includes below changes: - Rename InputPicker.[h|cc] to input_picker.[h|cc]. - And rename inputpicker directory to input_picker too. - Layout struct was changed to class and it take charge of creating layout and handling callbacks. - Add static |CreateAndShow*| functions to create and show pickers instead of |show*Popup|. - Integrate |*popupCallback| for date picker to reduce duplication. - Use Android's ColorChooserUIController for color chooser implementation. Reference: https://review.tizen.org/gerrit/274457/ Change-Id: Iaac7ace5541067b799fc8f6fb804d6de3dd86cf6 Signed-off-by: Ayush Kumar --- content/browser/web_contents/web_contents_impl.cc | 10 +- content/browser/web_contents/web_contents_impl.h | 6 +- content/public/browser/web_contents.h | 2 +- third_party/blink/public/mojom/BUILD.gn | 2 +- .../core/html/forms/color_chooser_ui_controller.cc | 4 +- .../core/html/forms/color_chooser_ui_controller.h | 2 +- .../blink/renderer/core/page/chrome_client_impl.cc | 7 + tizen_src/ewk/efl_integration/BUILD.gn | 8 +- .../color_chooser_efl.cc | 8 +- .../color_chooser_efl.h | 11 +- .../browser/input_picker/input_picker.cc | 726 ++++++++++++++++ .../browser/input_picker/input_picker.h | 111 +++ .../browser/inputpicker/InputPicker.cc | 957 --------------------- .../browser/inputpicker/InputPicker.h | 83 -- tizen_src/ewk/efl_integration/eweb_view.cc | 14 +- tizen_src/ewk/efl_integration/eweb_view.h | 6 +- tizen_src/ewk/efl_integration/resource/BUILD.gn | 4 +- .../efl_integration/web_contents_delegate_efl.cc | 2 +- 18 files changed, 881 insertions(+), 1082 deletions(-) mode change 100644 => 100755 content/browser/web_contents/web_contents_impl.h mode change 100644 => 100755 content/public/browser/web_contents.h mode change 100644 => 100755 tizen_src/ewk/efl_integration/BUILD.gn rename tizen_src/ewk/efl_integration/browser/{inputpicker => input_picker}/color_chooser_efl.cc (86%) rename tizen_src/ewk/efl_integration/browser/{inputpicker => input_picker}/color_chooser_efl.h (63%) create mode 100644 tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc create mode 100644 tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h delete mode 100755 tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.cc delete mode 100755 tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.h mode change 100644 => 100755 tizen_src/ewk/efl_integration/eweb_view.h diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 0d4eb02..2fc5272 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -712,7 +712,7 @@ class WebContentsImpl::WebContentsDestructionObserver raw_ptr owner_; }; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) // TODO(sreejakshetty): Make |WebContentsImpl::ColorChooserHolder| per-frame // instead of WebContents-owned. // WebContentsImpl::ColorChooserHolder ----------------------------------------- @@ -1045,7 +1045,7 @@ WebContentsImpl::~WebContentsImpl() { dialog_manager_->CancelDialogs(this, /*reset_state=*/true); } -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) color_chooser_holder_.reset(); #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) find_request_manager_.reset(); @@ -5390,7 +5390,7 @@ WebContents* WebContentsImpl::GetFirstWebContentsInLiveOriginalOpenerChain() { : nullptr; } -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) { OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidChooseColorInColorChooser", @@ -6447,7 +6447,7 @@ void WebContentsImpl::OnColorChooserFactoryReceiver( color_chooser_factory_receivers_.Add(this, std::move(receiver)); } -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) void WebContentsImpl::OpenColorChooser( mojo::PendingReceiver chooser_receiver, mojo::PendingRemote client, @@ -9413,7 +9413,7 @@ void WebContentsImpl::RenderFrameHostStateChanged( dict.Add("new", new_state); }); -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) if (old_state == LifecycleState::kActive && !render_frame_host->GetParent()) { // TODO(sreejakshetty): Remove this reset when ColorChooserHolder becomes // per-frame. diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h old mode 100644 new mode 100755 index bd28298..b8ab515 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -529,7 +529,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, RenderFrameHostImpl* GetOpener() override; bool HasLiveOriginalOpenerChain() override; WebContents* GetFirstWebContentsInLiveOriginalOpenerChain() override; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) void DidChooseColorInColorChooser(SkColor color) override; void DidEndColorChooser() override; #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) @@ -1046,7 +1046,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // blink::mojom::ColorChooserFactory --------------------------------------- void OnColorChooserFactoryReceiver( mojo::PendingReceiver receiver); -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) void OpenColorChooser( mojo::PendingReceiver chooser, mojo::PendingRemote client, @@ -2127,7 +2127,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, gfx::Size device_emulation_size_; gfx::Size view_size_before_emulation_; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) // Holds information about a current color chooser dialog, if one is visible. class ColorChooserHolder; std::unique_ptr color_chooser_holder_; diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h old mode 100644 new mode 100755 index aea5078..273d548 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h @@ -1045,7 +1045,7 @@ class WebContents : public PageNavigator, // Returns false if the request is no longer valid, otherwise true. virtual bool GotResponseToKeyboardLockRequest(bool allowed) = 0; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) // Called when the user has selected a color in the color chooser. virtual void DidChooseColorInColorChooser(SkColor color) = 0; diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index ea681fe..40822a7 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn @@ -326,7 +326,7 @@ mojom("mojom_platform") { if (use_ozone) { enabled_features += [ "is_selection_clipboard_buffer_possible" ] } - if (is_android || is_mac) { + if (is_android || is_mac || use_efl) { enabled_features += [ "is_using_open_color_chooser" ] } if (tizen_product_tv) { diff --git a/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc b/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc index 97b2064..140bc65 100644 --- a/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc +++ b/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc @@ -53,7 +53,7 @@ void ColorChooserUIController::Trace(Visitor* visitor) const { } void ColorChooserUIController::OpenUI() { -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_EFL) OpenColorChooser(); #else NOTREACHED() << "ColorChooserUIController should only be used on Android"; @@ -79,7 +79,7 @@ void ColorChooserUIController::DidChooseColor(uint32_t color) { client_->DidChooseColor(Color::FromRGBA32(color)); } -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) void ColorChooserUIController::OpenColorChooser() { DCHECK(!chooser_); frame_->GetBrowserInterfaceBroker().GetInterface( diff --git a/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h b/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h index 41e6097..0c3e11e 100644 --- a/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h +++ b/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h @@ -63,7 +63,7 @@ class CORE_EXPORT ColorChooserUIController void DidChooseColor(uint32_t color) final; protected: -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_EFL) void OpenColorChooser(); #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) mojo::Remote chooser_; diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 5a1b86b..ec0e285 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc @@ -711,6 +711,12 @@ ColorChooser* ChromeClientImpl::OpenColorChooser( if (frame->GetDocument()->GetSettings()->GetImmersiveModeEnabled()) return nullptr; +#if defined(USE_EFL) + // EFL port's color picker implementation is based on + // ColorChooserUIController, similar to Android's impl. + controller = + MakeGarbageCollected(frame, chooser_client); +#else if (RuntimeEnabledFeatures::PagePopupEnabled()) { controller = MakeGarbageCollected( frame, this, chooser_client); @@ -721,6 +727,7 @@ ColorChooser* ChromeClientImpl::OpenColorChooser( controller = MakeGarbageCollected(frame, chooser_client); } +#endif controller->OpenUI(); return controller; } diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn old mode 100644 new mode 100755 index da0da3390..8965db0 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -309,10 +309,10 @@ shared_library("chromium-ewk") { "browser/geolocation/geolocation_permission_context_efl.h", "browser/geolocation/location_provider_efl.cc", "browser/geolocation/location_provider_efl.h", - "browser/inputpicker/InputPicker.cc", - "browser/inputpicker/InputPicker.h", - "browser/inputpicker/color_chooser_efl.cc", - "browser/inputpicker/color_chooser_efl.h", + "browser/input_picker/color_chooser_efl.cc", + "browser/input_picker/color_chooser_efl.h", + "browser/input_picker/input_picker.cc", + "browser/input_picker/input_picker.h", "browser/network_service/browser_url_loader_throttle_efl.cc", "browser/network_service/browser_url_loader_throttle_efl.h", "browser/notification/notification_controller_efl.cc", diff --git a/tizen_src/ewk/efl_integration/browser/inputpicker/color_chooser_efl.cc b/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.cc similarity index 86% rename from tizen_src/ewk/efl_integration/browser/inputpicker/color_chooser_efl.cc rename to tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.cc index 102e50b..4a91cc5 100644 --- a/tizen_src/ewk/efl_integration/browser/inputpicker/color_chooser_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.cc @@ -9,11 +9,9 @@ namespace content { ColorChooserEfl::ColorChooserEfl(WebContents& web_contents) - : web_contents_(web_contents) { -} + : web_contents_(web_contents) {} -ColorChooserEfl::~ColorChooserEfl() { -} +ColorChooserEfl::~ColorChooserEfl() {} void ColorChooserEfl::SetSelectedColor(SkColor color) { #if !defined(EWK_BRINGUP) // FIXME: m94 bringup @@ -26,4 +24,4 @@ void ColorChooserEfl::End() { web_contents_.DidEndColorChooser(); #endif } -} +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/inputpicker/color_chooser_efl.h b/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h similarity index 63% rename from tizen_src/ewk/efl_integration/browser/inputpicker/color_chooser_efl.h rename to tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h index 59d6fdb..9091a33 100644 --- a/tizen_src/ewk/efl_integration/browser/inputpicker/color_chooser_efl.h +++ b/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ColorChooserEfl_h -#define ColorChooserEfl_h +#ifndef EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_COLOR_CHOOSER_EFL_H_ +#define EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_COLOR_CHOOSER_EFL_H_ #include "content/public/browser/color_chooser.h" #include "third_party/skia/include/core/SkColor.h" @@ -20,6 +20,9 @@ class ColorChooserEfl : public ColorChooser { ColorChooserEfl(WebContents& web_contents); ~ColorChooserEfl(); + ColorChooserEfl(const ColorChooserEfl&) = delete; + ColorChooserEfl& operator=(const ColorChooserEfl&) = delete; + // ColorChooser implementation. void SetSelectedColor(SkColor color) override; void End() override; @@ -28,6 +31,6 @@ class ColorChooserEfl : public ColorChooser { WebContents& web_contents_; }; -} +} // namespace content -#endif // ColorChooserEfl_h +#endif // EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_COLOR_CHOOSER_EFL_H_ diff --git a/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc new file mode 100644 index 0000000..af7b8ff --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc @@ -0,0 +1,726 @@ +// Copyright 2014 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 "input_picker.h" + +#include +#include +#include +#include + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/time/time.h" +#include "common/web_contents_utils.h" +#include "content/common/paths_efl.h" +#include "content/public/browser/web_contents.h" +#include "eweb_view.h" +#include "tizen/system_info.h" + +#if BUILDFLAG(IS_TIZEN) +#include +#include +#endif + +namespace content { + +static const char* kDefaultDatetimeFormat = "%Y/%m/%d %H:%M"; + +InputPicker::Layout::Layout(InputPicker* parent) : parent_(parent) { + CHECK(parent_); + evas_object_focus_set(parent_->web_view_->evas_object(), false); + // FIXME: Workaround. OSP requirement. OSP want to block own touch event + // while webkit internal picker is running. + evas_object_smart_callback_call(parent_->web_view_->evas_object(), + "input,picker,show", 0); +} + +InputPicker::Layout::~Layout() { + // FIXME: Workaround. OSP requirement. OSP want to block own touch event + // while webkit internal picker is running. + evas_object_smart_callback_call(parent_->web_view_->evas_object(), + "input,picker,hide", 0); + evas_object_focus_set(parent_->web_view_->evas_object(), true); + + if (!conformant_) + return; + + if (is_color_picker_) + DeleteColorPickerCallbacks(); + else + DeleteDatePickerCallbacks(); + + evas_object_del(conformant_); + conformant_ = nullptr; +} + +// static +std::unique_ptr +InputPicker::Layout::CreateAndShowColorPickerLayout(InputPicker* parent, + int r, + int g, + int b) { + std::unique_ptr picker_layout(new Layout(parent)); + picker_layout->is_color_picker_ = true; + + if (!picker_layout->AddBaseLayout("Select color", + "colorselector_popup_layout")) + return nullptr; + + picker_layout->color_rect_ = + evas_object_rectangle_add(evas_object_evas_get(picker_layout->layout_)); + if (!picker_layout->color_rect_) + return nullptr; + + evas_object_size_hint_weight_set(picker_layout->color_rect_, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_show(picker_layout->color_rect_); + evas_object_color_set(picker_layout->color_rect_, r, g, b, 255); + elm_object_part_content_set(picker_layout->layout_, "rect", + picker_layout->color_rect_); + + if (!picker_layout->AddColorSelector(r, g, b)) + return nullptr; + + if (!picker_layout->AddOKButton()) + return nullptr; + + evas_object_show(picker_layout->layout_); + elm_object_content_set(picker_layout->popup_, picker_layout->layout_); + evas_object_show(picker_layout->popup_); + + picker_layout->red_ = r; + picker_layout->green_ = g; + picker_layout->blue_ = b; + + picker_layout->AddColorPickerCallbacks(); + + return picker_layout; +} + +static char* GetDateTimeFormat() { +#if BUILDFLAG(IS_TIZEN) + char* language = getenv("LANGUAGE"); + setenv("LANGUAGE", "en_US", 1); + + char* region_format = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (!region_format) + return nullptr; + + int time_value = 0; + char buf[256] = {0}; + vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &time_value); + if (time_value == VCONFKEY_TIME_FORMAT_24) + snprintf(buf, sizeof(buf), "%s_DTFMT_24HR", region_format); + else + snprintf(buf, sizeof(buf), "%s_DTFMT_12HR", region_format); + + free(region_format); + + // FIXME: Workaround fix for region format. + int buf_length = strlen(buf); + for (int i = 0; i < buf_length - 4; i++) { + if (buf[i] == 'u' && buf[i + 1] == 't' && buf[i + 2] == 'f') { + if (buf[i + 3] == '8') { + // utf8 -> UTF-8 + for (int j = buf_length; j > i + 3; j--) + buf[j] = buf[j - 1]; + buf[i + 3] = '-'; + buf[buf_length + 1] = '\0'; + } else if (buf[i + 3] == '-' && buf[i + 4] == '8') { + // utf-8 -> UTF-8 + } else { + break; + } + + buf[i] = 'U'; + buf[i + 1] = 'T'; + buf[i + 2] = 'F'; + break; + } + } + + if (!language || !strcmp(language, "")) + unsetenv("LANGUAGE"); + else + setenv("LANGUAGE", language, 1); + + char* date_time_format = dgettext("dt_fmt", buf); + // FIXME: Workaround fix for not supported dt_fmt. + // Use default format if dt_fmt string is not exist. + if (strlen(date_time_format) == strlen(buf) && + !strncmp(date_time_format, buf, strlen(buf))) + return nullptr; + + return strdup(date_time_format); +#else + return nullptr; +#endif +} + +// static +std::unique_ptr +InputPicker::Layout::CreateAndShowDateLayout(InputPicker* parent, + struct tm* current_time, + ui::TextInputType type) { + std::unique_ptr picker_layout(new Layout(parent)); + + picker_layout->input_type_ = type; + + std::string title; + switch (type) { + case ui::TEXT_INPUT_TYPE_DATE: { + title = "IDS_WEBVIEW_HEADER_SET_DATE"; + break; + } + case ui::TEXT_INPUT_TYPE_WEEK: { + title = "IDS_WEBVIEW_HEADER_SET_WEEK"; + break; + } + case ui::TEXT_INPUT_TYPE_MONTH: { + title = "IDS_WEBVIEW_HEADER_SET_MONTH"; + break; + } + default: + NOTREACHED(); + break; + } + + if (!picker_layout->AddBaseLayout(dgettext("WebKit", title.c_str()), + "date_popup")) + return nullptr; + + picker_layout->date_picker_ = elm_datetime_add(picker_layout->layout_); + if (!picker_layout->date_picker_) + return nullptr; + + elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime", + picker_layout->date_picker_); + + char* format = GetDateTimeFormat(); + if (format) { + elm_datetime_format_set(picker_layout->date_picker_, format); + free(format); + } else { + elm_datetime_format_set(picker_layout->date_picker_, + kDefaultDatetimeFormat); + } + + elm_datetime_value_set(picker_layout->date_picker_, current_time); + + if (!picker_layout->AddOKButton()) + return nullptr; + + if (type == ui::TEXT_INPUT_TYPE_MONTH) { + elm_datetime_field_visible_set(picker_layout->date_picker_, + ELM_DATETIME_DATE, EINA_FALSE); + } + elm_datetime_field_visible_set(picker_layout->date_picker_, ELM_DATETIME_HOUR, + EINA_FALSE); + elm_datetime_field_visible_set(picker_layout->date_picker_, + ELM_DATETIME_MINUTE, EINA_FALSE); + + picker_layout->AddDatePickerCallbacks(); + + elm_object_content_set(picker_layout->popup_, picker_layout->layout_); + evas_object_show(picker_layout->popup_); + + return picker_layout; +} + +// static +std::unique_ptr +InputPicker::Layout::CreateAndShowDateTimeLayout(InputPicker* parent, + struct tm* current_time, + ui::TextInputType type) { + std::unique_ptr picker_layout(new Layout(parent)); + + picker_layout->input_type_ = type; + + elm_object_scale_set(picker_layout->popup_, 0.7); + if (!picker_layout->AddBaseLayout( + dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_DATE_AND_TIME"), + "datetime_popup")) + return nullptr; + + picker_layout->time_picker_ = elm_datetime_add(picker_layout->layout_); + picker_layout->date_picker_ = elm_datetime_add(picker_layout->layout_); + if (!picker_layout->time_picker_ || !picker_layout->date_picker_) + return nullptr; + + elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime", + picker_layout->time_picker_); + elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime2", + picker_layout->date_picker_); + elm_object_style_set(picker_layout->time_picker_, "time_layout"); + + char* format = GetDateTimeFormat(); + if (format) { + elm_datetime_format_set(picker_layout->date_picker_, format); + elm_datetime_format_set(picker_layout->time_picker_, format); + free(format); + } else { + elm_datetime_format_set(picker_layout->date_picker_, + kDefaultDatetimeFormat); + elm_datetime_format_set(picker_layout->time_picker_, + kDefaultDatetimeFormat); + } + + elm_datetime_value_set(picker_layout->date_picker_, current_time); + elm_datetime_value_set(picker_layout->time_picker_, current_time); + + if (!picker_layout->AddOKButton()) + return nullptr; + + picker_layout->AddDatePickerCallbacks(); + + elm_object_content_set(picker_layout->popup_, picker_layout->layout_); + evas_object_show(picker_layout->popup_); + + return picker_layout; +} + +// static +std::unique_ptr +InputPicker::Layout::CreateAndShowTimeLayout(InputPicker* parent, + struct tm* current_time) { + std::unique_ptr picker_layout(new Layout(parent)); + + picker_layout->input_type_ = ui::TEXT_INPUT_TYPE_TIME; + + if (!picker_layout->AddBaseLayout( + dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_TIME"), "date_popup")) + return nullptr; + + picker_layout->time_picker_ = elm_datetime_add(picker_layout->layout_); + if (!picker_layout->time_picker_) + return nullptr; + + elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime", + picker_layout->time_picker_); + elm_object_style_set(picker_layout->time_picker_, "time_layout"); + + elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime", + picker_layout->time_picker_); + + char* format = GetDateTimeFormat(); + if (format) { + elm_datetime_format_set(picker_layout->time_picker_, format); + free(format); + } else { + elm_datetime_format_set(picker_layout->time_picker_, + kDefaultDatetimeFormat); + } + + elm_datetime_value_set(picker_layout->time_picker_, current_time); + + if (!picker_layout->AddOKButton()) + return nullptr; + + elm_datetime_field_visible_set(picker_layout->time_picker_, ELM_DATETIME_YEAR, + EINA_FALSE); + elm_datetime_field_visible_set(picker_layout->time_picker_, + ELM_DATETIME_MONTH, EINA_FALSE); + elm_datetime_field_visible_set(picker_layout->time_picker_, ELM_DATETIME_DATE, + EINA_FALSE); + + picker_layout->AddDatePickerCallbacks(); + + elm_object_content_set(picker_layout->popup_, picker_layout->layout_); + evas_object_show(picker_layout->popup_); + + return picker_layout; +} + +bool InputPicker::Layout::AddBaseLayout(const char* title, + const char* layout_group) { + Evas_Object* top_widget = elm_object_top_widget_get( + elm_object_parent_widget_get(parent_->web_view_->evas_object())); + if (!top_widget) + return false; + + conformant_ = elm_conformant_add(top_widget); + if (!conformant_) + return false; + + evas_object_size_hint_weight_set(conformant_, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(top_widget, conformant_); + evas_object_show(conformant_); + + Evas_Object* 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); + evas_object_show(layout); + elm_object_content_set(conformant_, layout); + + popup_ = elm_popup_add(layout); + if (!popup_) + return false; + + elm_popup_align_set(popup_, ELM_NOTIFY_ALIGN_FILL, 1.0); + elm_object_part_text_set(popup_, "title,text", title); + evas_object_size_hint_weight_set(popup_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + + layout_ = elm_layout_add(popup_); + if (!layout_) + return false; + + base::FilePath edj_dir; + base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); + base::FilePath control_path; + control_path = edj_dir.Append(FILE_PATH_LITERAL("control.edj")); + elm_layout_file_set(layout_, control_path.AsUTF8Unsafe().c_str(), + layout_group); + + 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); + + return true; +} + +bool InputPicker::Layout::AddOKButton() { + ok_button_ = elm_button_add(popup_); + if (!ok_button_) + return false; + + elm_object_style_set(ok_button_, "popup"); + elm_object_text_set(ok_button_, "OK"); + elm_object_part_content_set(popup_, "button1", ok_button_); + evas_object_focus_set(ok_button_, true); + + return true; +} + +bool InputPicker::Layout::AddColorSelector(int r, int g, int b) { + color_picker_ = elm_colorselector_add(layout_); + if (!color_picker_) + return false; + + elm_colorselector_mode_set(color_picker_, ELM_COLORSELECTOR_PALETTE); + evas_object_size_hint_fill_set(color_picker_, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(color_picker_, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + + if (IsTvProfile()) { + elm_colorselector_color_set(color_picker_, r, g, b, 255); + } else { + Eina_List* color_list = const_cast( + elm_colorselector_palette_items_get(color_picker_)); + Eina_List* list = nullptr; + Elm_Object_Item* it = nullptr; + void* item = nullptr; + int red = 0, green = 0, blue = 0, alpha = 0; + + EINA_LIST_FOREACH(color_list, list, item) { + if (item) { + Elm_Object_Item* elm_item = static_cast(item); + elm_colorselector_palette_item_color_get(elm_item, &red, &green, &blue, + &alpha); + if (red == r && green == g && blue == b) { + it = elm_item; + break; + } + } + } + + if (!it) + it = static_cast(eina_list_nth(color_list, 0)); + + elm_object_item_signal_emit(it, "elm,state,selected", "elm"); + } + + elm_object_part_content_set(layout_, "colorpalette", color_picker_); + + return true; +} + +void InputPicker::Layout::AddColorPickerCallbacks() { + evas_object_smart_callback_add(color_picker_, "color,item,selected", + ColorPickerItemSelectedCallback, color_rect_); + + evas_object_smart_callback_add(ok_button_, "clicked", + ColorPickerSelectFinishedCallback, this); +#if BUILDFLAG(IS_TIZEN) + eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, + ColorPickerBackKeyCallback, this); +#endif +} + +void InputPicker::Layout::DeleteColorPickerCallbacks() { + if (color_picker_) { + evas_object_smart_callback_del(color_picker_, "color,item,selected", + ColorPickerItemSelectedCallback); + } + + if (ok_button_) { + evas_object_smart_callback_del(ok_button_, "clicked", + ColorPickerSelectFinishedCallback); + } + +#if BUILDFLAG(IS_TIZEN) + if (popup_) { + eext_object_event_callback_del(popup_, EEXT_CALLBACK_BACK, + ColorPickerBackKeyCallback); + } +#endif +} + +void InputPicker::Layout::AddDatePickerCallbacks() { + evas_object_smart_callback_add(ok_button_, "clicked", + DatePickerSelectFinishedCallback, this); + + if (input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD || + input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME || + input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL) { + evas_object_smart_callback_add(date_picker_, "changed", + DatePickerItemChangedCallback, this); + evas_object_smart_callback_add(time_picker_, "changed", + DatePickerItemChangedCallback, this); + } + + if (IsTvProfile()) { + elm_object_signal_emit(layout_, "TV", "align,swallow.datetime"); + } + +#if BUILDFLAG(IS_TIZEN) + eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, + DatePickerBackKeyCallback, this); +#endif +} + +void InputPicker::Layout::DeleteDatePickerCallbacks() { + if (ok_button_) { + evas_object_smart_callback_del(ok_button_, "clicked", + DatePickerSelectFinishedCallback); + } + + if (input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD || + input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME || + input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL) { + if (date_picker_) { + evas_object_smart_callback_del(date_picker_, "changed", + DatePickerItemChangedCallback); + } + if (time_picker_) { + evas_object_smart_callback_del(time_picker_, "changed", + DatePickerItemChangedCallback); + } + } + +#if BUILDFLAG(IS_TIZEN) + if (popup_) { + eext_object_event_callback_del(popup_, EEXT_CALLBACK_BACK, + DatePickerBackKeyCallback); + } +#endif +} + +// static +void InputPicker::Layout::ColorPickerItemSelectedCallback(void* data, + Evas_Object* obj, + void* event_info) { + int r = 0, g = 0, b = 0, a = 0; + Elm_Object_Item* color_it = static_cast(event_info); + elm_colorselector_palette_item_color_get(color_it, &r, &g, &b, &a); + evas_object_color_set(static_cast(data), r, g, b, a); +} + +// static +void InputPicker::Layout::ColorPickerSelectFinishedCallback(void* data, + Evas_Object* obj, + void* event_info) { + Layout* picker_layout = static_cast(data); + + int r = 0, g = 0, b = 0, a = 0; + evas_object_color_get(picker_layout->color_rect_, &r, &g, &b, &a); + + picker_layout->parent_->web_view_->web_contents() + .DidChooseColorInColorChooser(SkColorSetARGB(a, r, g, b)); + picker_layout->parent_->RemoveColorPicker(); +} + +// static +void InputPicker::Layout::DatePickerSelectFinishedCallback(void* data, + Evas_Object* obj, + void* event_info) { + struct tm current_time; + memset(¤t_time, 0, sizeof(struct tm)); + + Layout* picker_layout = static_cast(data); + + if (picker_layout->input_type_ == ui::TEXT_INPUT_TYPE_TIME) + elm_datetime_value_get(picker_layout->time_picker_, ¤t_time); + else + elm_datetime_value_get(picker_layout->date_picker_, ¤t_time); + + char dateStr[20] = { + 0, + }; + + switch (picker_layout->input_type_) { + case ui::TEXT_INPUT_TYPE_DATE: { + strftime(dateStr, 20, "%F", ¤t_time); + break; + } + case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: + case ui::TEXT_INPUT_TYPE_DATE_TIME: { + strftime(dateStr, 20, "%FT%RZ", ¤t_time); + break; + } + case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: { + strftime(dateStr, 20, "%FT%R", ¤t_time); + break; + } + case ui::TEXT_INPUT_TYPE_TIME: { + strftime(dateStr, 20, "%R", ¤t_time); + break; + } + case ui::TEXT_INPUT_TYPE_WEEK: { + // Call mktime: current_time.tm_wday will be set + mktime(¤t_time); + strftime(dateStr, 20, "%G-W%V", ¤t_time); + break; + } + case ui::TEXT_INPUT_TYPE_MONTH: { + strftime(dateStr, 20, "%Y-%m", ¤t_time); + break; + } + default: + NOTREACHED(); + break; + } + + picker_layout->parent_->RemoveDatePicker(); +} + +// static +void InputPicker::Layout::DatePickerItemChangedCallback(void* data, + Evas_Object* obj, + void* event_info) { + struct tm current_time; + memset(¤t_time, 0, sizeof(struct tm)); + + Layout* picker_layout = static_cast(data); + if (obj == picker_layout->date_picker_) { + elm_datetime_value_get(picker_layout->date_picker_, ¤t_time); + elm_datetime_value_set(picker_layout->time_picker_, ¤t_time); + } else if (obj == picker_layout->time_picker_) { + elm_datetime_value_get(picker_layout->time_picker_, ¤t_time); + elm_datetime_value_set(picker_layout->date_picker_, ¤t_time); + } +} + +#if BUILDFLAG(IS_TIZEN) +// static +void InputPicker::Layout::ColorPickerBackKeyCallback(void* data, + Evas_Object* obj, + void* event_info) { + Layout* picker_layout = static_cast(data); + + picker_layout->parent_->web_view_->web_contents() + .DidChooseColorInColorChooser(SkColorSetARGB(255, picker_layout->red_, + picker_layout->green_, + picker_layout->blue_)); + picker_layout->parent_->RemoveColorPicker(); +} + +// static +void InputPicker::Layout::DatePickerBackKeyCallback(void* data, + Evas_Object* obj, + void* event_info) { + Layout* picker_layout = static_cast(data); + if (picker_layout) + picker_layout->parent_->RemoveDatePicker(); +} +#endif + +InputPicker::InputPicker(EWebView* view) : web_view_(view) {} + +void InputPicker::ShowColorPicker(int r, int g, int b, int a) { + picker_layout_ = Layout::CreateAndShowColorPickerLayout(this, r, g, b); + if (!picker_layout_) { + LOG(ERROR) << "Failed to create color picker."; + // We need to notify engine that default color is chosen + // otherwise selecting will never be finished. + web_view_->web_contents().DidChooseColorInColorChooser( + SkColorSetARGB(a, r, g, b)); + } +} + +void InputPicker::ShowDatePicker(ui::TextInputType input_type, + double input_date) { + web_view_->ExecuteEditCommand("Unselect", 0); + + time_t timep; + struct tm tm; + if (!std::isfinite(input_date)) { + time(&timep); + localtime_r(&timep, &tm); + } else if (input_type == ui::TEXT_INPUT_TYPE_MONTH) { + // When type is month, input_date is number of month since epoch. + unsigned int year = floor(input_date / 12.0) + 1970.0; + unsigned int month = input_date - (year - 1970) * 12 + 1; + CHECK_LE(month, 12u); + + char date[12]; + snprintf(date, sizeof(date), "%d-%d", year, month); + char* last_char = strptime(date, "%Y-%m", &tm); + DCHECK(last_char); + } else { + // In all other cases, input_date is number of milliseconds since epoch. + timep = base::Time::FromDoubleT(input_date / 1000).ToTimeT(); + gmtime_r(&timep, &tm); + } + struct tm* current_time = &tm; + + switch (input_type) { + case ui::TEXT_INPUT_TYPE_DATE: + case ui::TEXT_INPUT_TYPE_WEEK: + case ui::TEXT_INPUT_TYPE_MONTH: { + picker_layout_ = + Layout::CreateAndShowDateLayout(this, current_time, input_type); + break; + } + case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: + case ui::TEXT_INPUT_TYPE_DATE_TIME: + case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: { + picker_layout_ = + Layout::CreateAndShowDateTimeLayout(this, current_time, input_type); + break; + } + case ui::TEXT_INPUT_TYPE_TIME: { + picker_layout_ = Layout::CreateAndShowTimeLayout(this, current_time); + break; + } + default: + LOG(ERROR) << "Invalid date picker type."; + break; + } + + if (!picker_layout_) { + LOG(ERROR) << "Failed to create date picker."; + } +} + +void InputPicker::RemoveColorPicker() { + if (!picker_layout_) + return; + + picker_layout_.reset(); + web_view_->web_contents().DidEndColorChooser(); +} + +void InputPicker::RemoveDatePicker() { + if (!picker_layout_) + return; + + picker_layout_.reset(); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h new file mode 100644 index 0000000..ab2737ef --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h @@ -0,0 +1,111 @@ +// Copyright 2014 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_BROWSER_INPUT_PICKER_INPUT_PICKER_H_ +#define EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_INPUT_PICKER_H_ + +#include +#include +#include + +#include "ewk/efl_integration/eweb_view.h" +#include "ui/base/ime/text_input_type.h" + +class EWebView; + +namespace content { + +class InputPicker { + public: + explicit InputPicker(EWebView* web_view); + + InputPicker(const InputPicker&) = delete; + InputPicker& operator=(const InputPicker&) = delete; + + void ShowColorPicker(int r, int g, int b, int a); + void ShowDatePicker(ui::TextInputType input_type, double input_date); + + private: + class Layout { + public: + static std::unique_ptr + CreateAndShowColorPickerLayout(InputPicker* parent, int r, int g, int b); + static std::unique_ptr CreateAndShowDateLayout( + InputPicker* parent, + struct tm* currentTime, + ui::TextInputType type); + static std::unique_ptr CreateAndShowDateTimeLayout( + InputPicker* parent, + struct tm* currentTime, + ui::TextInputType type); + static std::unique_ptr CreateAndShowTimeLayout( + InputPicker* parent, + struct tm* currentTime); + + ~Layout(); + + private: + explicit Layout(InputPicker* parent); + + Layout(const Layout&) = delete; + Layout& operator=(const Layout&) = delete; + + bool AddBaseLayout(const char* title, const char* layout_group); + bool AddOKButton(); + bool AddColorSelector(int r, int g, int b); + void AddColorPickerCallbacks(); + void DeleteColorPickerCallbacks(); + void AddDatePickerCallbacks(); + void DeleteDatePickerCallbacks(); + + static void ColorPickerSelectFinishedCallback(void* data, + Evas_Object* obj, + void* event_info); + static void ColorPickerItemSelectedCallback(void* data, + Evas_Object* obj, + void* event_info); + static void DatePickerSelectFinishedCallback(void* data, + Evas_Object* obj, + void* event_info); + static void DatePickerItemChangedCallback(void* data, + Evas_Object* obj, + void* event_info); + +#if BUILDFLAG(IS_TIZEN) + static void ColorPickerBackKeyCallback(void* data, + Evas_Object* obj, + void* event_info); + static void DatePickerBackKeyCallback(void* data, + Evas_Object* obj, + void* event_info); +#endif + + InputPicker* parent_ = nullptr; + + Evas_Object* conformant_ = nullptr; + Evas_Object* popup_ = nullptr; + Evas_Object* layout_ = nullptr; + Evas_Object* ok_button_ = nullptr; + Evas_Object* color_picker_ = nullptr; + Evas_Object* color_rect_ = nullptr; + Evas_Object* date_picker_ = nullptr; + Evas_Object* time_picker_ = nullptr; + + ui::TextInputType input_type_; + bool is_color_picker_ = false; + int red_ = 0; + int green_ = 0; + int blue_ = 0; + }; + + void RemoveColorPicker(); + void RemoveDatePicker(); + + EWebView* web_view_; + std::unique_ptr picker_layout_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_INPUT_PICKER_H_ diff --git a/tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.cc b/tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.cc deleted file mode 100755 index 8346d52..0000000 --- a/tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.cc +++ /dev/null @@ -1,957 +0,0 @@ -// Copyright 2014 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 "InputPicker.h" - -#include "base/path_service.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/time/time.h" -#include "common/web_contents_utils.h" -#include "content/common/paths_efl.h" -#include "content/public/browser/web_contents.h" -#include "eweb_view.h" -#include "tizen/system_info.h" - -#include -#include -#include - -#include -#if BUILDFLAG(IS_TIZEN) -#include -#include -#include -extern void* EflExtensionHandle; -#endif - -namespace content { - -static const unsigned maxDatetimeLength = 32; -static const unsigned maxDateStringLength = 10; -static const char defaultDatetimeFormat[] = "%Y/%m/%d %H:%M"; - -struct InputPicker::Layout { - Layout(Evas_Object *ewkView) - : ewk_view_(ewkView) - , parent(elm_object_top_widget_get(elm_object_parent_widget_get(ewk_view_))) - , popup(0) - , layout(0) - , datePicker(0) - , time_picker(0) - , color_picker(0) - , color_rect(0) - , dataListEditField(0) - , initial_r(0) - , initial_g(0) - , initial_b(0) - , datetime_local(false) { - evas_object_focus_set(ewk_view_, false); - - /* FIXME : Workaround. OSP requirement. - OSP want to block own touch event while webkit internal picker is running. */ - evas_object_smart_callback_call(ewk_view_, "input,picker,show", 0); - } - - bool BuildColorSelector(); - bool CreateColorSelector(); - bool CreateOKButton(); - void SetPopupSize(int width, int height); - - base::FilePath GetLayoutFilePath() { - base::FilePath edj_dir; - base::FilePath control_edj; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); - control_edj = edj_dir.Append(FILE_PATH_LITERAL("control.edj")); - return control_edj; - } - - ~Layout() { - /* FIXME : Workaround. OSP requirement. - OSP want to block own touch event while webkit internal picker is running. */ - evas_object_smart_callback_call(ewk_view_, "input,picker,hide", 0); - - evas_object_focus_set(ewk_view_, true); - } - - Evas_Object* ewk_view_; - Evas_Object* parent; - Evas_Object* popup; - Evas_Object* layout; - Evas_Object* datePicker; - Evas_Object* time_picker; - Evas_Object* color_picker; - Evas_Object* color_rect; - Evas_Object* okButton; - Evas_Object* dataListEditField; - int initial_r; - int initial_g; - int initial_b; - bool datetime_local; -}; - -bool InputPicker::Layout::BuildColorSelector() { - /* add color palette widget */ - color_picker = elm_colorselector_add(layout); - if (!color_picker) - return false; - - elm_colorselector_mode_set(color_picker, ELM_COLORSELECTOR_PALETTE); - evas_object_size_hint_fill_set(color_picker, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(color_picker, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - if (IsTvProfile()) { - elm_colorselector_color_set(color_picker, initial_r, initial_g, initial_b, 255); - } else { - Eina_List* color_list = const_cast - (elm_colorselector_palette_items_get(color_picker)); - Eina_List* list = 0; - void* item = 0; - int r = 0; - int g = 0; - int b = 0; - int a = 0; - Elm_Object_Item* it = NULL; - - EINA_LIST_FOREACH(color_list, list, item) { - if (item) { - elm_colorselector_palette_item_color_get((Elm_Object_Item*)item, &r, &g, &b, &a); - if (r == initial_r && g == initial_g && b == initial_b) { - it = (Elm_Object_Item*)item; - break; - } - } - } - - if (!it) - it = (Elm_Object_Item*)eina_list_nth(color_list, 0); - - elm_object_item_signal_emit((Elm_Object_Item*)it, "elm,state,selected", "elm"); - } - - elm_object_part_content_set(layout, "colorpalette", color_picker); - return true; -} - -bool InputPicker::Layout::CreateOKButton() { - okButton = elm_button_add(popup); - if (!okButton) - return false; - - elm_object_style_set(okButton, "popup"); - elm_object_text_set(okButton, "OK"); - elm_object_part_content_set(popup, "button1", okButton); - evas_object_focus_set(okButton, true); - return true; -} - -void InputPicker::Layout::SetPopupSize(int width, int height) { - if(popup) { - evas_object_resize(popup, width, height); - evas_object_move(popup, 0, 0); - } -} - -bool InputPicker::Layout::CreateColorSelector() { - popup = elm_popup_add(parent); - if (!popup) - return false; - - elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0); - elm_object_part_text_set(popup, "title,text", "Select color"); - evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - base::FilePath control_edj = GetLayoutFilePath(); - - layout = elm_layout_add(popup); - if (!layout) - return false; - - elm_layout_file_set(layout, control_edj.AsUTF8Unsafe().c_str(), - "colorselector_popup_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); - - color_rect = evas_object_rectangle_add(evas_object_evas_get(layout)); - - if (color_rect) { - evas_object_size_hint_weight_set(color_rect, - EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(color_rect); - evas_object_color_set(color_rect, initial_r, initial_g, initial_b, 255); - elm_object_part_content_set(layout, "rect", color_rect); - } - - BuildColorSelector(); - - evas_object_show(layout); - elm_object_content_set(popup, layout); - return CreateOKButton(); -} - -struct ColorPopupUserData { - InputPicker* inputPicker; - Evas_Object* colorRect; - Evas_Object* color; - Evas_Object* colorAccessObject; -}; - -struct Input_Date { - int year; - int mon; - int day; - int hour; - int min; - int sec; -}; - -struct Input_Date_Str { - char year[maxDateStringLength]; - char mon[maxDateStringLength]; - char day[maxDateStringLength]; - char hour[maxDateStringLength]; - char min[maxDateStringLength]; - char sec[maxDateStringLength]; -}; - -static char* datetimeFormat() { -#if BUILDFLAG(IS_TIZEN) - char* datetimeFormat = NULL; - char* regionFormat = NULL; - char* language = NULL; - char buf[256] = { 0, }; - int timeValue = 0; - int isHour24 = 0; - int returnValue = 0; - - language = getenv("LANGUAGE"); - setenv("LANGUAGE", "en_US", 1); - - regionFormat = vconf_get_str(VCONFKEY_REGIONFORMAT); - if (!regionFormat) - return 0; - - returnValue = vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &timeValue); - if (returnValue < 0) - isHour24 = 0; - else if (timeValue == VCONFKEY_TIME_FORMAT_12 || - timeValue == VCONFKEY_TIME_FORMAT_24) - isHour24 = timeValue - 1; - - if (isHour24) - snprintf(buf, sizeof(buf), "%s_DTFMT_24HR", regionFormat); - else - snprintf(buf, sizeof(buf), "%s_DTFMT_12HR", regionFormat); - - free(regionFormat); - - // FIXME: Workaround fix for region format. - int bufLength = strlen(buf); - for (int i = 0; i < bufLength - 4; i++) { - if (buf[i] == 'u' && buf[i + 1] == 't' && buf[i + 2] == 'f') { - if (buf[i + 3] == '8') { - // utf8 -> UTF-8 - for (int j = bufLength; j > i + 3; j--) - buf[j] = buf[j - 1]; - buf[i + 3] = '-'; - buf[bufLength + 1] = '\0'; - } else if (buf[i + 3] == '-' && buf[i + 4] == '8') { - // utf-8 -> UTF-8 - } else { - break; - } - - buf[i] = 'U'; - buf[i + 1] = 'T'; - buf[i + 2] = 'F'; - break; - } - } - - datetimeFormat = dgettext("dt_fmt", buf); - - if(!language || !strcmp(language, "")) - unsetenv("LANGUAGE"); - else - setenv("LANGUAGE", language, 1); - - // FIXME: Workaround fix for not supported dt_fmt. - // Use default format if dt_fmt string is not exist. - if (strlen(datetimeFormat) == strlen(buf) && - !strncmp(datetimeFormat, buf, strlen(buf))) { - return 0; - } - - return strdup(datetimeFormat); -#else - return NULL; -#endif -} - -InputPicker::InputPicker(EWebView& web_view_) - : web_view_(web_view_) - , ewk_view_(web_view_.evas_object()) - , picker_layout_(0) - , data_list_(0) { -} - -InputPicker::~InputPicker() { - if (picker_layout_) { - if (picker_layout_->popup) - evas_object_del(picker_layout_->popup); - delete picker_layout_; - } -} - -void InputPicker::SetPopupSize(int width, int height) { - if (picker_layout_) - picker_layout_->SetPopupSize(width, height); -} - -#if BUILDFLAG(IS_TIZEN) -void InputPicker::endEditingCallback( - void* data, Evas_Object* obj, void* event_info) -{ - if (IsMobileProfile() || IsWearableProfile()) { - InputPicker* inputPicker = static_cast(data); - if (inputPicker) - inputPicker->removeDatetimePickerDelayed(); - } -} -#endif - -void InputPicker::showDatePicker(ui::TextInputType input_type, double input_date) -{ - web_view_.ExecuteEditCommand("Unselect", 0); - - time_t timep; - struct tm tm; - struct tm* currentTime; - - if (!std::isfinite(input_date)) { - time(&timep); - currentTime = localtime(&timep); - } else if (input_type == ui::TEXT_INPUT_TYPE_MONTH) { - // when type is month, input_date is number of month since epoch - unsigned int year = floor(input_date / 12.0) + 1970.0; - unsigned int month = input_date - (year - 1970) * 12 + 1; - CHECK(month <= 12); - - char date[12]; - snprintf(date, 12, "%d-%d", year, month); - - char* last_char = strptime(date, "%Y-%m", &tm); - DCHECK(last_char); - - currentTime = &tm; - } else { - // in all other cases, input_date is number of milliseconds since epoch - base::Time doubleT = base::Time::FromDoubleT(input_date/1000); - timep = doubleT.ToTimeT(); - currentTime = gmtime(&timep); - } - - switch (input_type) { - case ui::TEXT_INPUT_TYPE_DATE: - showDatePopup(currentTime); - break; - case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: - case ui::TEXT_INPUT_TYPE_DATE_TIME: - showDatetimePopup(currentTime, false /*datetime*/); - break; - case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: - showDatetimePopup(currentTime, true /* datetime_local */); - break; - case ui::TEXT_INPUT_TYPE_TIME: - showTimePopup(currentTime); - break; - case ui::TEXT_INPUT_TYPE_WEEK: - showWeekPopup(currentTime); - break; - case ui::TEXT_INPUT_TYPE_MONTH: - showMonthPopup(currentTime); - break; - default: - break; - } -} - -void InputPicker::ColorPickerKeyUpCallback(void* data, Evas*, 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; - - HandleBackKeyColorPicker(data, obj, event_info); -} - -void InputPicker::ShowColorPicker(int r, int g, int b, int alpha) { - if (picker_layout_) { - elm_colorselector_color_set(picker_layout_->color_picker, r, g, b, alpha); - evas_object_focus_set(picker_layout_->okButton, true); - evas_object_show(picker_layout_->layout); - return; - } - - picker_layout_ = new InputPicker::Layout(ewk_view_); - - picker_layout_->initial_r = r; - picker_layout_->initial_g = g; - picker_layout_->initial_b = b; - - picker_layout_->CreateColorSelector(); - - evas_object_smart_callback_add(picker_layout_->color_picker, - "color,item,selected", - SelectedColorCallback, - picker_layout_->color_rect); -#if BUILDFLAG(IS_TIZEN) - eext_object_event_callback_add(picker_layout_->popup, EEXT_CALLBACK_BACK, - HandleBackKeyColorPicker, this); -#endif - evas_object_event_callback_add(picker_layout_->popup, EVAS_CALLBACK_KEY_UP, - ColorPickerKeyUpCallback, this); - - evas_object_smart_callback_add( - picker_layout_->okButton, - "clicked", - ColorPickerCallback, - this); - - evas_object_show(picker_layout_->popup); -} - -void InputPicker::HideColorPicker() { - if (!picker_layout_) - return; -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - web_view_.web_contents().DidEndColorChooser(); -#endif - if (picker_layout_->popup) { - evas_object_del(picker_layout_->popup); - picker_layout_->popup = 0; - } - - delete picker_layout_; - picker_layout_ = 0; -} - -void InputPicker::SelectedColorCallback( - void* data, Evas_Object* obj, void* event_info) { - int r = 0; - int g = 0; - int b = 0; - int a = 0; - - Elm_Object_Item *color_it = static_cast(event_info); - elm_colorselector_palette_item_color_get(color_it, &r, &g, &b, &a); - evas_object_color_set(static_cast(data), r, g, b, a); -} - -void InputPicker::ColorPickerCallback( - void* data, Evas_Object* obj, void* event_info) { - InputPicker* inputPicker = static_cast(data); - - int r(0), g(0), b(0), a(0); - evas_object_color_get(inputPicker->picker_layout_->color_rect, &r, &g, &b, &a); -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - inputPicker->web_view_.web_contents().DidChooseColorInColorChooser( - SkColorSetARGB(a, r, g, b)); -#endif - inputPicker->HideColorPicker(); -} - -void InputPicker::HandleBackKeyColorPicker( - void* data, Evas_Object* obj, void* event_info) { - InputPicker* inputPicker = static_cast(data); - - int r = inputPicker->picker_layout_->initial_r; - int g = inputPicker->picker_layout_->initial_g; - int b = inputPicker->picker_layout_->initial_b; - int a = 255; -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - inputPicker->web_view_.web_contents().DidChooseColorInColorChooser( - SkColorSetARGB(a, r, g, b)); -#endif - inputPicker->HideColorPicker(); -} - -void InputPicker::showDatePopup(struct tm* currentTime) { - if (picker_layout_) { - // Just update the value. - elm_datetime_value_set(picker_layout_->datePicker, currentTime); - evas_object_focus_set(picker_layout_->okButton, true); - return; - } - - picker_layout_ = new InputPicker::Layout(ewk_view_); - CreatePopupLayout(dgettext("WebKit","IDS_WEBVIEW_HEADER_SET_DATE"), - currentTime); - - picker_layout_->CreateOKButton(); - - evas_object_smart_callback_add( - picker_layout_->okButton, "clicked", datePopupCallback, this); - elm_object_content_set(picker_layout_->popup, picker_layout_->layout); - evas_object_show(picker_layout_->popup); -} - -void InputPicker::showWeekPopup(struct tm* currentTime) { - if (picker_layout_) { - // Just update the value. - elm_datetime_value_set(picker_layout_->datePicker, currentTime); - evas_object_focus_set(picker_layout_->okButton, true); - return; - } - - picker_layout_ = new InputPicker::Layout(ewk_view_); - CreatePopupLayout(dgettext("WebKit","IDS_WEBVIEW_HEADER_SET_WEEK"), - currentTime); - - picker_layout_->CreateOKButton(); - - evas_object_smart_callback_add( - picker_layout_->okButton, "clicked", weekPopupCallback, this); - elm_object_content_set(picker_layout_->popup, picker_layout_->layout); - evas_object_show(picker_layout_->popup); -} - -void InputPicker::showTimePopup(struct tm* currentTime) { - if (picker_layout_) { - // Just update the value. - elm_datetime_value_set(picker_layout_->time_picker, currentTime); - evas_object_focus_set(picker_layout_->okButton, true); - return; - } - - picker_layout_ = new InputPicker::Layout(ewk_view_); - CreateTimePopupLayout(dgettext("WebKit","IDS_WEBVIEW_HEADER_SET_TIME"), - currentTime); - - picker_layout_->CreateOKButton(); - - evas_object_smart_callback_add( - picker_layout_->okButton, "clicked", timePopupCallback, this); - elm_object_content_set(picker_layout_->popup, picker_layout_->layout); - evas_object_show(picker_layout_->popup); -} - -void InputPicker::showMonthPopup(struct tm* currentTime) { - if (picker_layout_) { - // Just update the value. - elm_datetime_value_set(picker_layout_->datePicker, currentTime); - evas_object_focus_set(picker_layout_->okButton, true); - return; - } - - picker_layout_ = new InputPicker::Layout(ewk_view_); - CreatePopupLayout(dgettext("WebKit","IDS_WEBVIEW_HEADER_SET_MONTH"), - currentTime); - - picker_layout_->CreateOKButton(); - - evas_object_smart_callback_add( - picker_layout_->okButton, "clicked", monthPopupCallback, this); - elm_object_content_set(picker_layout_->popup, picker_layout_->layout); - evas_object_show(picker_layout_->popup); -} - -void InputPicker::showDatetimePopup(struct tm* currentTime, bool datetime_local) { - if (picker_layout_) { - // Just update the value. - picker_layout_->datetime_local = datetime_local; - - elm_datetime_value_set(picker_layout_->datePicker, currentTime); - evas_object_focus_set(picker_layout_->okButton, true); - return; - } - - picker_layout_ = new InputPicker::Layout(ewk_view_); - picker_layout_->datetime_local = datetime_local; - - CreateDateTimePopupLayout( - dgettext("WebKit","IDS_WEBVIEW_HEADER_SET_DATE_AND_TIME"), currentTime); - - picker_layout_->CreateOKButton(); - - evas_object_smart_callback_add( - picker_layout_->okButton, "clicked", datetimePopupCallback, this); - evas_object_smart_callback_add( - picker_layout_->datePicker, "changed", datetimeChangedCallback, this); - evas_object_smart_callback_add( - picker_layout_->time_picker, "changed", datetimeChangedCallback, this); - - elm_object_content_set(picker_layout_->popup, picker_layout_->layout); - evas_object_show(picker_layout_->popup); - -} - -Eina_Bool InputPicker::removeDatetimePicker(void* data) { - InputPicker* inputPicker = static_cast(data); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - inputPicker->web_view_.web_contents().DidCancelDialog(); -#endif - - if (!inputPicker->picker_layout_) - return ECORE_CALLBACK_CANCEL; - - inputPicker->web_view_.ExecuteEditCommand("Unselect", 0); - - inputPicker->deletePopupLayout(); - delete inputPicker->picker_layout_; - inputPicker->picker_layout_ = 0; - - return ECORE_CALLBACK_CANCEL; -} - -void InputPicker::removeDatetimePickerDelayed() { - ecore_timer_add(0.1, removeDatetimePicker, this); -} - -void InputPicker::DatePickerKeyUpCallback(void* data, Evas*, 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; - - HandleBackKeyDatePicker(data, obj, event_info); -} - -void InputPicker::CreatePopupLayout(const char* title, struct tm* currentTime) { - picker_layout_->popup = elm_popup_add(picker_layout_->parent); - evas_object_size_hint_weight_set( - picker_layout_->popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_part_text_set(picker_layout_->popup, "title,text", title); - -#if BUILDFLAG(IS_TIZEN) - if (EflExtensionHandle) { - void (*webkit_eext_object_event_callback_add)( - Evas_Object *, Eext_Callback_Type , Eext_Event_Cb func, void *); - webkit_eext_object_event_callback_add = (void (*)( - Evas_Object *, - Eext_Callback_Type , - Eext_Event_Cb func, - void *)) dlsym(EflExtensionHandle, "eext_object_event_callback_add"); - (*webkit_eext_object_event_callback_add)( - picker_layout_->popup, EEXT_CALLBACK_BACK, HandleBackKeyDatePicker, this); - } -#endif - evas_object_event_callback_add(picker_layout_->popup, EVAS_CALLBACK_KEY_UP, - DatePickerKeyUpCallback, this); - - base::FilePath edj_dir; - base::FilePath control_edj; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); - control_edj = edj_dir.Append(FILE_PATH_LITERAL("control.edj")); - - - picker_layout_->layout = elm_layout_add(picker_layout_->popup); - elm_layout_file_set( - picker_layout_->layout, - control_edj.AsUTF8Unsafe().c_str(), - "date_popup"); - evas_object_size_hint_weight_set( - picker_layout_->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - picker_layout_->datePicker = elm_datetime_add(picker_layout_->layout); - elm_object_part_content_set( - picker_layout_->layout, - "elm.swallow.datetime", - picker_layout_->datePicker); - - char* format = datetimeFormat(); - if (format) { - elm_datetime_format_set(picker_layout_->datePicker, format); - free(format); - } else { - elm_datetime_format_set(picker_layout_->datePicker, defaultDatetimeFormat); - } - - elm_datetime_value_set(picker_layout_->datePicker, currentTime); - -#if BUILDFLAG(IS_TIZEN) - if (IsTvProfile()) { - elm_object_signal_emit(picker_layout_->layout,"TV","align,swallow.datetime"); - } else if (IsMobileProfile() || IsWearableProfile()) { - evas_object_smart_callback_add( - picker_layout_->datePicker, "edit,end", endEditingCallback, 0); - } -#endif -} - -void InputPicker::CreateDateTimePopupLayout(const char* title, struct tm* currentTime) { - picker_layout_->popup = elm_popup_add(picker_layout_->parent); - elm_object_scale_set(picker_layout_->popup, 0.7); - evas_object_size_hint_weight_set( - picker_layout_->popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_part_text_set(picker_layout_->popup, "title,text", title); - -#if BUILDFLAG(IS_TIZEN) - if (EflExtensionHandle) { - void (*webkit_eext_object_event_callback_add)( - Evas_Object *, Eext_Callback_Type , Eext_Event_Cb func, void *); - webkit_eext_object_event_callback_add = (void (*)( - Evas_Object *, - Eext_Callback_Type , - Eext_Event_Cb func, - void *)) dlsym(EflExtensionHandle, "eext_object_event_callback_add"); - (*webkit_eext_object_event_callback_add)( - picker_layout_->popup, EEXT_CALLBACK_BACK, HandleBackKeyDatePicker, this); - } -#endif - evas_object_event_callback_add(picker_layout_->popup, EVAS_CALLBACK_KEY_UP, - DatePickerKeyUpCallback, this); - - base::FilePath edj_dir; - base::FilePath control_edj; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); - control_edj = edj_dir.Append(FILE_PATH_LITERAL("control.edj")); - - - picker_layout_->layout = elm_layout_add(picker_layout_->popup); - elm_layout_file_set( - picker_layout_->layout, - control_edj.AsUTF8Unsafe().c_str(), - "datetime_popup"); - evas_object_size_hint_weight_set( - picker_layout_->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - picker_layout_->time_picker = elm_datetime_add(picker_layout_->layout); - elm_object_part_content_set( - picker_layout_->layout, - "elm.swallow.datetime", - picker_layout_->time_picker); - - picker_layout_->datePicker = elm_datetime_add(picker_layout_->layout); - elm_object_part_content_set( - picker_layout_->layout, - "elm.swallow.datetime2", - picker_layout_->datePicker); - - elm_object_style_set(picker_layout_->time_picker, "time_layout"); - - char* format = datetimeFormat(); - if (format) { - elm_datetime_format_set(picker_layout_->datePicker, format); - elm_datetime_format_set(picker_layout_->time_picker, format); - free(format); - } else { - elm_datetime_format_set(picker_layout_->datePicker, defaultDatetimeFormat); - elm_datetime_format_set(picker_layout_->time_picker, defaultDatetimeFormat); - } - - elm_datetime_value_set(picker_layout_->datePicker, currentTime); - elm_datetime_value_set(picker_layout_->time_picker, currentTime); - -#if BUILDFLAG(IS_TIZEN) - if (IsMobileProfile() || IsWearableProfile()) { - evas_object_smart_callback_add( - picker_layout_->datePicker, "edit,end", endEditingCallback, 0); - } -#endif -} - -void InputPicker::CreateTimePopupLayout(const char* title, struct tm* currentTime) { - picker_layout_->popup = elm_popup_add(picker_layout_->parent); - evas_object_size_hint_weight_set( - picker_layout_->popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_part_text_set(picker_layout_->popup, "title,text", title); - -#if BUILDFLAG(IS_TIZEN) - if (EflExtensionHandle) { - void (*webkit_eext_object_event_callback_add)( - Evas_Object *, Eext_Callback_Type , Eext_Event_Cb func, void *); - webkit_eext_object_event_callback_add = (void (*)( - Evas_Object *, - Eext_Callback_Type , - Eext_Event_Cb func, - void *)) dlsym(EflExtensionHandle, "eext_object_event_callback_add"); - (*webkit_eext_object_event_callback_add)( - picker_layout_->popup, EEXT_CALLBACK_BACK, HandleBackKeyDatePicker, this); - } -#endif - evas_object_event_callback_add(picker_layout_->popup, EVAS_CALLBACK_KEY_UP, - DatePickerKeyUpCallback, this); - - base::FilePath edj_dir; - base::FilePath control_edj; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); - control_edj = edj_dir.Append(FILE_PATH_LITERAL("control.edj")); - - - picker_layout_->layout = elm_layout_add(picker_layout_->popup); - elm_layout_file_set( - picker_layout_->layout, - control_edj.AsUTF8Unsafe().c_str(), - "date_popup"); - evas_object_size_hint_weight_set( - picker_layout_->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - picker_layout_->time_picker = elm_datetime_add(picker_layout_->layout); - elm_object_part_content_set( - picker_layout_->layout, - "elm.swallow.datetime", - picker_layout_->time_picker); - - elm_object_style_set(picker_layout_->time_picker, "time_layout"); - - char* format = datetimeFormat(); - if (format) { - elm_datetime_format_set(picker_layout_->time_picker, format); - free(format); - } else { - elm_datetime_format_set(picker_layout_->time_picker, defaultDatetimeFormat); - } - - elm_datetime_value_set(picker_layout_->time_picker, currentTime); - -#if BUILDFLAG(IS_TIZEN) - if (IsTvProfile()) { - elm_object_signal_emit(picker_layout_->layout,"TV","align,swallow.datetime"); - } else if (IsMobileProfile() || IsWearableProfile()) { - evas_object_smart_callback_add( - picker_layout_->time_picker, "edit,end", endEditingCallback, 0); - } -#endif -} - -void InputPicker::deletePopupLayout() { - if(picker_layout_->popup){ - evas_object_del(picker_layout_->popup); - picker_layout_->popup = 0; - } -} - -void InputPicker::datePopupCallback( - void* data, Evas_Object* obj, void* event_info) { - struct tm currentTime; - memset(¤tTime, 0, sizeof(struct tm)); - - InputPicker* inputPicker = static_cast(data); - - elm_datetime_value_get(inputPicker->picker_layout_->datePicker, ¤tTime); - mktime(¤tTime); - - char dateStr[20] = { 0, }; - strftime(dateStr, 20, "%F" , ¤tTime); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - inputPicker->web_view_.web_contents().DidReplaceDateTime(std::string(dateStr)); -#endif - inputPicker->web_view_.ExecuteEditCommand("Unselect", 0); - - inputPicker->deletePopupLayout(); - delete inputPicker->picker_layout_; - inputPicker->picker_layout_ = 0; -} - -void InputPicker::weekPopupCallback( - void* data, Evas_Object* obj, void* event_info) { - struct tm currentTime; - memset(¤tTime, 0, sizeof(struct tm)); - - InputPicker* inputPicker = static_cast(data); - - elm_datetime_value_get(inputPicker->picker_layout_->datePicker, ¤tTime); - mktime(¤tTime); - - char dateStr[20] = { 0, }; - strftime(dateStr, 20, "%G-W%V", ¤tTime); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - inputPicker->web_view_.web_contents().DidReplaceDateTime(std::string(dateStr)); -#endif - inputPicker->web_view_.ExecuteEditCommand("Unselect", 0); - - inputPicker->deletePopupLayout(); - delete inputPicker->picker_layout_; - inputPicker->picker_layout_ = 0; -} - -void InputPicker::timePopupCallback( - void* data, Evas_Object* obj, void* event_info) { - struct tm currentTime; - memset(¤tTime, 0, sizeof(struct tm)); - - InputPicker* inputPicker = static_cast(data); - - elm_datetime_value_get(inputPicker->picker_layout_->time_picker, ¤tTime); - mktime(¤tTime); - - char dateStr[20] = { 0, }; - strftime(dateStr, 20, "%R", ¤tTime); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - inputPicker->web_view_.web_contents().DidReplaceDateTime(std::string(dateStr)); -#endif - inputPicker->web_view_.ExecuteEditCommand("Unselect", 0); - - inputPicker->deletePopupLayout(); - delete inputPicker->picker_layout_; - inputPicker->picker_layout_ = 0; -} - -void InputPicker::monthPopupCallback( - void* data, Evas_Object* obj, void* event_info) { - struct tm currentTime; - memset(¤tTime, 0, sizeof(struct tm)); - - InputPicker* inputPicker = static_cast(data); - mktime(¤tTime); - - elm_datetime_value_get(inputPicker->picker_layout_->datePicker, ¤tTime); - - char dateStr[20] = { 0, }; - strftime(dateStr, 20, "%Y-%m", ¤tTime); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - inputPicker->web_view_.web_contents().DidReplaceDateTime(std::string(dateStr)); -#endif - inputPicker->web_view_.ExecuteEditCommand("Unselect", 0); - - inputPicker->deletePopupLayout(); - delete inputPicker->picker_layout_; - inputPicker->picker_layout_ = 0; -} - -void InputPicker::datetimePopupCallback( - void* data, Evas_Object* obj, void* event_info) { - struct tm currentTime; - memset(¤tTime, 0, sizeof(struct tm)); - - InputPicker* inputPicker = static_cast(data); - - elm_datetime_value_get(inputPicker->picker_layout_->datePicker, ¤tTime); - mktime(¤tTime); - - char dateStr[50] = { 0, }; - if (inputPicker->picker_layout_->datetime_local) - strftime(dateStr, 50, "%FT%R", ¤tTime); - else - strftime(dateStr, 50, "%FT%RZ", ¤tTime); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - inputPicker->web_view_.web_contents().DidReplaceDateTime(std::string(dateStr)); -#endif - inputPicker->web_view_.ExecuteEditCommand("Unselect", 0); - - inputPicker->deletePopupLayout(); - delete inputPicker->picker_layout_; - inputPicker->picker_layout_ = 0; -} - -void InputPicker::datetimeChangedCallback( - void* data, Evas_Object* obj, void* event_info) { - struct tm currentTime; - memset(¤tTime, 0, sizeof(struct tm)); - - InputPicker* inputPicker = static_cast(data); - if (obj == inputPicker->picker_layout_->datePicker) { - elm_datetime_value_get(inputPicker->picker_layout_->datePicker, ¤tTime); - elm_datetime_value_set(inputPicker->picker_layout_->time_picker, ¤tTime); - } else if (obj == inputPicker->picker_layout_->time_picker) { - elm_datetime_value_get(inputPicker->picker_layout_->time_picker, ¤tTime); - elm_datetime_value_set(inputPicker->picker_layout_->datePicker, ¤tTime); - } -} - -void InputPicker::HandleBackKeyDatePicker( - void* data, Evas_Object* obj, void* event_info) { - removeDatetimePicker(data); -} - -} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.h b/tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.h deleted file mode 100755 index e5b05a1..0000000 --- a/tizen_src/ewk/efl_integration/browser/inputpicker/InputPicker.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2014 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 InputPicker_h -#define InputPicker_h - -#include -#include -#include -#include "ui/base/ime/text_input_type.h" - -class EWebView; - -namespace content { - -class WebContents; -struct ColorPopupUserData; -class WebContentsDelegateEfl; - -class InputPicker { - public: - explicit InputPicker(EWebView& web_view_); - ~InputPicker(); - - void showDatePicker(ui::TextInputType input_type, double input_date); - void ShowColorPicker(int r, int g, int b, int alpha); - void HideColorPicker(); - void SetPopupSize(int width, int height); - - private: - struct Layout; - - void showDatePopup(struct tm* currentTime); - void showTimePopup(struct tm* currentTime); - void showMonthPopup(struct tm* currentTime); - void showWeekPopup(struct tm* currentTime); - void showDatetimePopup(struct tm* currentTime, bool datetime_local); - void removeDatetimePickerDelayed(); - void CreatePopupLayout(const char* title, struct tm* currentTime); - void CreateDateTimePopupLayout(const char* title, struct tm* currentTime); - void CreateTimePopupLayout(const char* title, struct tm* currentTime); - void deletePopupLayout(); - void addColorRect( - const char* part, int r, int g, int b, ColorPopupUserData* color_data); - - static void ColorPickerKeyUpCallback( - void* data, Evas* e, Evas_Object* obj, void* event_info); - static void DatePickerKeyUpCallback( - void* data, Evas* e, Evas_Object* obj, void* event_info); - static void datePopupCallback( - void* data, Evas_Object* obj, void* event_info); - static void timePopupCallback( - void* data, Evas_Object* obj, void* event_info); - static void monthPopupCallback( - void* data, Evas_Object* obj, void* event_info); - static void weekPopupCallback( - void* data, Evas_Object* obj, void* event_info); - static void datetimePopupCallback( - void* data, Evas_Object* obj, void* event_info); - static void datetimeChangedCallback( - void* data, Evas_Object* obj, void* event_info); - static void endEditingCallback( - void* data, Evas_Object* obj, void* event_info); - static Eina_Bool removeDatetimePicker(void* data); - static void ColorPickerCallback( - void* data, Evas_Object* obj, void* event_info); - static void SelectedColorCallback( - void* data, Evas_Object* obj, void* event_info); - static void HandleBackKeyColorPicker( - void* data, Evas_Object* obj, void* event_info); - static void HandleBackKeyDatePicker( - void* data, Evas_Object* obj, void* event_info); - - EWebView& web_view_; - Evas_Object* ewk_view_; - Layout* picker_layout_; - Eina_List* data_list_; -}; - -} // namespace content - -#endif // InputPicker_h diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 7da077e..ec146b6 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -532,8 +532,6 @@ void EWebView::SetOrientation(int orientation) { if (context_menu_) context_menu_->SetPopupSize(width, height); - if (inputPicker_) - inputPicker_->SetPopupSize(width, height); if (popup_controller_) popup_controller_->SetPopupSize(width, height); if (JavaScriptDialogManagerEfl* dialogMG = GetJavaScriptDialogManagerEfl()) @@ -2164,12 +2162,8 @@ void EWebView::ShowContentsDetectedPopup(const char* message) { } void EWebView::RequestColorPicker(int r, int g, int b, int a) { - inputPicker_.reset(new InputPicker(*this)); - inputPicker_->ShowColorPicker(r, g, b, a); -} - -void EWebView::DismissColorPicker() { - inputPicker_->HideColorPicker(); + input_picker_.reset(new InputPicker(this)); + input_picker_->ShowColorPicker(r, g, b, a); } bool EWebView::SetColorPickerColor(int r, int g, int b, int a) { @@ -2181,8 +2175,8 @@ bool EWebView::SetColorPickerColor(int r, int g, int b, int a) { void EWebView::InputPickerShow(ui::TextInputType input_type, double input_value) { - inputPicker_.reset(new InputPicker(*this)); - inputPicker_->showDatePicker(input_type, input_value); + input_picker_.reset(new InputPicker(this)); + input_picker_->ShowDatePicker(input_type, input_value); } void EWebView::LoadNotFoundErrorPage(const std::string& invalidUrl) { diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h old mode 100644 new mode 100755 index 6b09cf1..b2d0037 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -20,7 +20,7 @@ #include "base/callback.h" #include "base/containers/id_map.h" #include "base/synchronization/waitable_event.h" -#include "browser/inputpicker/InputPicker.h" +#include "browser/input_picker/input_picker.h" #include "browser/selectpicker/popup_picker.h" #include "content/browser/renderer_host/event_with_latency_info.h" #include "content/browser/selection/selection_controller_efl.h" @@ -69,6 +69,7 @@ class WebContentsDelegateEfl; class WebContentsViewAura; class ContextMenuControllerEfl; class PopupControllerEfl; +class InputPicker; } class ErrorParams; @@ -436,7 +437,6 @@ class EWebView { bool IsDragging() const; void RequestColorPicker(int r, int g, int b, int a); - void DismissColorPicker(); bool SetColorPickerColor(int r, int g, int b, int a); void InputPickerShow(ui::TextInputType input_type, double input_value); @@ -604,7 +604,7 @@ class EWebView { WebViewCallback authentication_cb_; - std::unique_ptr inputPicker_; + std::unique_ptr input_picker_; base::IDMap web_app_icon_url_get_callback_map_; base::IDMap diff --git a/tizen_src/ewk/efl_integration/resource/BUILD.gn b/tizen_src/ewk/efl_integration/resource/BUILD.gn index 274481b..33f8000 100644 --- a/tizen_src/ewk/efl_integration/resource/BUILD.gn +++ b/tizen_src/ewk/efl_integration/resource/BUILD.gn @@ -15,14 +15,14 @@ template("edje_res_ewk") { args = [ "$edje_compiler", "-id", - rebase_path("../images/"), + rebase_path("./images/"), rebase_path("{{source_file_part}}"), rebase_path("$root_out_dir/resources/{{source_name_part}}.edj"), ] } source_set(target_name) { - data = [ + deps = [ ":$edje_target_name", ] } 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 ac72d7c..097edfe 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -6,7 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "browser/favicon/favicon_database.h" -#include "browser/inputpicker/color_chooser_efl.h" +#include "browser/input_picker/color_chooser_efl.h" #include "browser/javascript_dialog_manager_efl.h" #include "browser/policy_response_delegate_efl.h" #include "common/render_messages_ewk.h" -- 2.7.4 From 920cdf44e736d255a2b1e811d0a7cb969168ff7f Mon Sep 17 00:00:00 2001 From: Chandan Padhi Date: Thu, 12 Jan 2023 18:34:51 +0530 Subject: [PATCH 04/16] [M108 Migration] Enable snapshot feature for EFL port This commit provides support for both asynchronous and synchronous snapshot APIs. This also adds sample code to test async and sync snapshot APIs in ubrowser and efl_webview_app respectively. Legacy IPCs have also been replaced with Mojo calls for software capture. Reference: https://review.tizen.org/gerrit/281757/ Change-Id: I2e03fcffb5cfcf6377a09e7dec97d9533881265c Signed-off-by: Chandan Padhi --- .../renderer_host/render_widget_host_impl.cc | 19 ++ .../renderer_host/render_widget_host_impl.h | 7 + .../renderer_host/render_widget_host_view_aura.cc | 6 + .../renderer_host/render_widget_host_view_aura.h | 1 + .../renderer_host/render_widget_host_view_base.h | 12 +- third_party/blink/public/mojom/BUILD.gn | 3 + .../public/mojom/widget/platform_widget.mojom | 7 + third_party/blink/public/web/web_view.h | 11 + .../blink/renderer/core/exported/web_view_impl.cc | 72 +++++ .../blink/renderer/core/exported/web_view_impl.h | 5 + .../renderer/core/frame/web_frame_widget_impl.cc | 40 +++ .../renderer/core/frame/web_frame_widget_impl.h | 5 + .../blink/renderer/platform/widget/widget_base.cc | 15 + .../blink/renderer/platform/widget/widget_base.h | 5 + .../renderer/platform/widget/widget_base_client.h | 6 + .../rwhv_aura_offscreen_helper_efl.cc | 305 +++++++++++++++++++++ .../renderer_host/rwhv_aura_offscreen_helper_efl.h | 29 ++ tizen_src/ewk/efl_integration/eweb_view.cc | 76 +---- tizen_src/ewk/efl_integration/eweb_view.h | 9 +- tizen_src/ewk/efl_integration/public/ewk_view.cc | 18 +- tizen_src/ewk/ubrowser/window.cc | 20 ++ tizen_src/ewk/ubrowser/window.h | 4 +- tizen_src/ewk/ubrowser/window_ui.cc | 10 + tizen_src/ewk/ubrowser/window_ui.h | 1 + 24 files changed, 598 insertions(+), 88 deletions(-) diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index db4f1c95..e12f71f 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -971,6 +971,25 @@ void RenderWidgetHostImpl::RemoveImeInputEventObserver( } #endif +#if BUILDFLAG(IS_EFL) +void RenderWidgetHostImpl::RequestContentSnapshot( + const gfx::Rect& snapshot_rect, + float page_scale_factor, + int request_id) { + blink_widget_->GetContentSnapshot( + snapshot_rect, page_scale_factor, + base::BindOnce(&RenderWidgetHostImpl::OnGetContentSnapshot, + weak_factory_.GetWeakPtr(), request_id)); +} + +void RenderWidgetHostImpl::OnGetContentSnapshot(int request_id, + const SkBitmap& bitmap) { + if (!view_) + return; + view_->DidGetContentSnapshot(bitmap, request_id); +} +#endif + blink::VisualProperties RenderWidgetHostImpl::GetInitialVisualProperties() { blink::VisualProperties initial_props = GetVisualProperties(); diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index b2df2f8..aa77594 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -439,6 +439,13 @@ class CONTENT_EXPORT RenderWidgetHostImpl RenderWidgetHost::InputEventObserver* observer) override; #endif +#if BUILDFLAG(IS_EFL) + void RequestContentSnapshot(const gfx::Rect& src_subrect, + float page_scale_factor, + int request_id); + void OnGetContentSnapshot(int request_id, const SkBitmap& bitmap); +#endif + // Returns true if the RenderWidget is hidden. bool is_hidden() const { return is_hidden_; } diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index fcee03c..366c8a7 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -563,6 +563,12 @@ void RenderWidgetHostViewAura::NotifySwap(const uint32_t texture_id) { offscreen_helper_->NotifySwap(texture_id); } +void RenderWidgetHostViewAura::DidGetContentSnapshot(const SkBitmap& bitmap, + int request_id) { + if (offscreen_helper_) + offscreen_helper_->DidGetContentSnapshot(bitmap, request_id); +} + void RenderWidgetHostViewAura::DidHandleKeyEvent( blink::WebInputEvent::Type input_event_type, bool processed) { diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index fa5af30..cacda97 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -418,6 +418,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura return offscreen_helper_.get(); } void NotifySwap(const uint32_t texture_id); + void DidGetContentSnapshot(const SkBitmap& bitmap, int request_id) override; void DidHandleKeyEvent(blink::WebInputEvent::Type input_event, bool processed) override; void SelectionChanged(const std::u16string& text, diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index ee2ad3c..0207afa 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h @@ -275,6 +275,13 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { // This method will clear any cached fallback surface. For use in response to // a CommitPending where there is no content for TakeFallbackContentFrom. virtual void ClearFallbackSurfaceForCommitPending() {} + +#if BUILDFLAG(IS_EFL) + virtual void DidHandleKeyEvent(blink::WebInputEvent::Type input_event, + bool processed) {} + virtual void DidGetContentSnapshot(const SkBitmap& bitmap, int request_id) {} +#endif + // This method will reset the fallback to the first surface after navigation. virtual void ResetFallbackToFirstNavigationSurface() = 0; @@ -572,11 +579,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { // RenderWidgetHostView. VisibleTimeRequestTrigger* GetVisibleTimeRequestTrigger(); -#if BUILDFLAG(IS_EFL) - virtual void DidHandleKeyEvent(blink::WebInputEvent::Type input_event, - bool processed) {} -#endif - protected: explicit RenderWidgetHostViewBase(RenderWidgetHost* host); ~RenderWidgetHostViewBase() override; diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 40822a7..4fe3988 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn @@ -332,6 +332,9 @@ mojom("mojom_platform") { if (tizen_product_tv) { enabled_features += [ "is_tizen_tv" ] } + if (use_efl) { + enabled_features += [ "is_efl" ] + } shared_cpp_typemaps = [ { diff --git a/third_party/blink/public/mojom/widget/platform_widget.mojom b/third_party/blink/public/mojom/widget/platform_widget.mojom index aeb55d1..4dfb64b 100644 --- a/third_party/blink/public/mojom/widget/platform_widget.mojom +++ b/third_party/blink/public/mojom/widget/platform_widget.mojom @@ -16,6 +16,9 @@ import "third_party/blink/public/mojom/widget/visual_properties.mojom"; import "third_party/blink/public/mojom/widget/record_content_to_visible_time_request.mojom"; import "ui/base/ime/mojom/text_input_state.mojom"; +[EnableIf=is_efl] +import "skia/public/mojom/bitmap.mojom"; + // This interface is bound on the compositor thread. interface WidgetCompositor { // Requests that the RenderWidget sends back a response after the next main @@ -107,6 +110,10 @@ interface Widget { gfx.mojom.Rect window_screen_rect) => (); + [EnableIf=is_efl] + GetContentSnapshot(gfx.mojom.Rect snapshot_rect, float page_scale_factor) + => (skia.mojom.BitmapN32? bitmap); + // Informs the widget that it was hidden. This allows it to reduce its // resource utilization, and will cancel any pending // RecordContentToVisibleTimeRequest that was set with WasShown or diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index f3b681e..454da39 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h @@ -46,6 +46,10 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/display/mojom/screen_orientation.mojom-shared.h" +#if BUILDFLAG(IS_EFL) +#include "third_party/skia/include/core/SkCanvas.h" +#endif + namespace base { class TimeDelta; } @@ -470,6 +474,13 @@ class BLINK_EXPORT WebView { // Returns the number of live WebView instances in this process. static size_t GetWebViewCount(); +#if BUILDFLAG(IS_EFL) + // Paints the rectangular region within the WebWidget + // onto the specified canvas, when the page is not having any 3D content. + virtual bool PaintSoftBitmap(SkCanvas*, const gfx::Rect&) = 0; + virtual bool HasAcceleratedCanvasWithinViewport() const = 0; +#endif + protected: ~WebView() = default; }; diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 604c0e0..00f7e7f 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc @@ -194,6 +194,11 @@ #include "third_party/blink/public/web/win/web_font_rendering.h" #endif +#if BUILDFLAG(IS_EFL) +#include "third_party/blink/renderer/core/dom/container_node.h" +#include "third_party/blink/renderer/core/dom/static_node_list.h" +#endif + // Get rid of WTF's pow define so we can use std::pow. #undef pow #include // for std::pow @@ -3922,4 +3927,71 @@ void WebViewImpl::CreateRemoteMainFrame( std::move(remote_main_frame_interfaces->main_frame)); } +#if BUILDFLAG(IS_EFL) +bool WebViewImpl::PaintSoftBitmap(SkCanvas* canvas, const gfx::Rect& rect) { + if (rect.IsEmpty()) + return false; + + if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView()) + return false; + + LocalFrameView* view = MainFrameImpl()->GetFrameView(); + view->UpdateAllLifecyclePhases(DocumentUpdateReason::kOverlay); + + gfx::PointF offset = MainFrame()->ToWebLocalFrame()->GetScrollOffset(); + gfx::Rect dirty_rect(rect.x() + offset.x(), rect.y() + offset.y(), + rect.width(), rect.height()); + PaintRecordBuilder builder; + { + // FIXME: scaleFactor should be ideally pagescalefactor * devicescale + // here we are assuming pagescalefactor as 1 always, this needs to + // be taken care with a proper fix for capturing zoomed contents. + LocalFrame& frame = view->GetFrame(); + ChromeClient& chrome_client = frame.GetChromeClient(); + float scale_factor = chrome_client.GetScreenInfo(frame).device_scale_factor; + + GraphicsContext& context = builder.Context(); + context.SetDeviceScaleFactor(scale_factor); + + AffineTransform transform; + transform.Scale(scale_factor); + transform.Translate(static_cast(-dirty_rect.x()), + static_cast(-dirty_rect.y())); + + // FIXME: Use the page-background color to clear instead for half + // loaded pages. + SkColor color = SkColorSetARGB(0xff, 0xff, 0xff, 0xff); + canvas->clear(color); + view->PaintOutsideOfLifecycle(context, PaintFlag::kOmitCompositingInfo, + CullRect(dirty_rect)); + } + builder.EndRecording()->Playback(canvas); + return true; +} + +bool WebViewImpl::HasAcceleratedCanvasWithinViewport() const { + if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView()) + return false; + + Document* document = MainFrameImpl()->GetFrame()->GetDocument(); + if (!document) + return false; + + StaticElementList* canvas_elements = + document->QuerySelectorAll("canvas", ASSERT_NO_EXCEPTION); + if (!canvas_elements) + return false; + + gfx::Rect visible_content_rect = + MainFrameImpl()->GetFrameView()->LayoutViewport()->VisibleContentRect(); + for (unsigned i = 0; i < canvas_elements->length(); ++i) { + if (visible_content_rect.Intersects( + canvas_elements->item(i)->BoundsInWidget())) { + return true; + } + } + return false; +} +#endif + } // namespace blink diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index ac38111..ebf4292 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h @@ -222,6 +222,11 @@ class CORE_EXPORT WebViewImpl final : public WebView, const SessionStorageNamespaceId& GetSessionStorageNamespaceId() override; bool IsFencedFrameRoot() const override; +#if BUILDFLAG(IS_EFL) + bool PaintSoftBitmap(SkCanvas*, const gfx::Rect&) override; + bool HasAcceleratedCanvasWithinViewport() const override; +#endif + // Functions to add and remove observers for this object. void AddObserver(WebViewObserver* observer); void RemoveObserver(WebViewObserver* observer); diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 18c4feb..db9d088 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc @@ -150,6 +150,10 @@ #include "ui/gfx/geometry/point.h" #endif +#if BUILDFLAG(IS_EFL) +#include "skia/ext/image_operations.h" +#endif + namespace WTF { template <> @@ -4115,6 +4119,42 @@ bool WebFrameWidgetImpl::UpdateScreenRects( return true; } +#if BUILDFLAG(IS_EFL) +void WebFrameWidgetImpl::GetContentSnapshot(const gfx::Rect& snapshot_rect, + float page_scale_factor, + SkBitmap* snapshot) { + WebView* view = View(); + if (!view || !view->MainFrame()) { + LOG(ERROR) << "SoftBitmap:Capture Invalid view"; + return; + } + + if (view->HasAcceleratedCanvasWithinViewport()) { + LOG(ERROR) + << "SoftBitmap:Capture avoided for WebGl/Cavas2D content on viewport"; + return; + } + + if (view->MainFrameWidget()->Size().IsEmpty()) { + LOG(ERROR) << "SoftBitmap:Capture Invalid size"; + return; + } + + snapshot->allocPixels(SkImageInfo::MakeN32Premul(snapshot_rect.width(), + snapshot_rect.height())); + SkCanvas canvas(*snapshot); + if (!view->PaintSoftBitmap(&canvas, snapshot_rect)) { + LOG(ERROR) << "SoftBitmap:Capture PaintSoftBitmap failed"; + return; + } + + *snapshot = skia::ImageOperations::Resize( + *snapshot, skia::ImageOperations::RESIZE_GOOD, + page_scale_factor * snapshot->width(), + page_scale_factor * snapshot->height()); +} +#endif + void WebFrameWidgetImpl::OrientationChanged() { local_root_->SendOrientationChangeEvent(); } diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 72528ee..57c0357 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h @@ -702,6 +702,11 @@ class CORE_EXPORT WebFrameWidgetImpl const VisualProperties& visual_properties) override; bool UpdateScreenRects(const gfx::Rect& widget_screen_rect, const gfx::Rect& window_screen_rect) override; +#if BUILDFLAG(IS_EFL) + void GetContentSnapshot(const gfx::Rect& snapshot_rect, + float page_scale_factor, + SkBitmap* snapshot) override; +#endif void OrientationChanged() override; void DidUpdateSurfaceAndScreen( const display::ScreenInfos& previous_original_screen_infos) override; diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index 78bb164..d2fca1a 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc @@ -61,6 +61,10 @@ #include "third_party/blink/renderer/platform/widget/compositing/android_webview/synchronous_layer_tree_frame_sink.h" #endif +#if BUILDFLAG(IS_EFL) +#include "third_party/skia/include/core/SkBitmap.h" +#endif + namespace blink { namespace { @@ -450,6 +454,17 @@ void WidgetBase::UpdateScreenRects(const gfx::Rect& widget_screen_rect, std::move(callback).Run(); } +#if BUILDFLAG(IS_EFL) +void WidgetBase::GetContentSnapshot(const gfx::Rect& snapshot_rect, + float page_scale_factor, + GetContentSnapshotCallback callback) { + SkBitmap content_snapshot; + client_->GetContentSnapshot(snapshot_rect, page_scale_factor, + &content_snapshot); + std::move(callback).Run(content_snapshot); +} +#endif + void WidgetBase::WasHidden() { // A provisional frame widget will never be hidden since that would require it // to be shown first. A frame must be attached to the frame tree before diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h index a26cd3b..1ba4b68 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.h +++ b/third_party/blink/renderer/platform/widget/widget_base.h @@ -136,6 +136,11 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget, void UpdateScreenRects(const gfx::Rect& widget_screen_rect, const gfx::Rect& window_screen_rect, UpdateScreenRectsCallback callback) override; +#if BUILDFLAG(IS_EFL) + void GetContentSnapshot(const gfx::Rect& snapshot_rect, + float page_scale_factor, + GetContentSnapshotCallback callback) override; +#endif void WasHidden() override; void WasShown(bool was_evicted, mojom::blink::RecordContentToVisibleTimeRequestPtr diff --git a/third_party/blink/renderer/platform/widget/widget_base_client.h b/third_party/blink/renderer/platform/widget/widget_base_client.h index 9f8a391..d952389 100644 --- a/third_party/blink/renderer/platform/widget/widget_base_client.h +++ b/third_party/blink/renderer/platform/widget/widget_base_client.h @@ -169,6 +169,12 @@ class WidgetBaseClient { return false; } +#if BUILDFLAG(IS_EFL) + virtual void GetContentSnapshot(const gfx::Rect& snapshot_rect, + float page_scale_factor, + SkBitmap* snapshot) {} +#endif + // Convert screen coordinates to device emulated coordinates (scaled // coordinates when devtools is used). This occurs for popups where their // window bounds are emulated. diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc index 749b0d0..30492b0 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc @@ -40,6 +40,24 @@ namespace content { +// If the first frame is not prepared after load is finished, +// delay getting the snapshot by 100ms. +static const int kSnapshotProcessDelay = 100; + +class ScreenshotCapturedCallback { + public: + ScreenshotCapturedCallback(Screenshot_Captured_Callback func, void* user_data) + : func_(func), user_data_(user_data) {} + void Run(Evas_Object* image) { + if (func_ != NULL) + (func_)(image, user_data_); + } + + private: + Screenshot_Captured_Callback func_; + void* user_data_; +}; + class RenderWidgetHostHelperAura : public RenderWidgetHostHelper { public: explicit RenderWidgetHostHelperAura(RWHVAuraOffscreenHelperEfl* rwhv_helper) @@ -156,6 +174,8 @@ RWHVAuraOffscreenHelperEfl::~RWHVAuraOffscreenHelperEfl() { OnFocusIn); evas_object_event_callback_del(content_image_, EVAS_CALLBACK_FOCUS_OUT, OnFocusOut); + evas_event_callback_del_full(evas_, EVAS_CALLBACK_RENDER_FLUSH_PRE, + OnEvasRenderFlushPre, this); evas_object_del(content_image_elm_host_); evas_object_del(content_image_); @@ -177,6 +197,8 @@ void RWHVAuraOffscreenHelperEfl::Initialize() { device_scale_factor_ = display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); + + snapshot_timer_.reset(new base::OneShotTimer); } void RWHVAuraOffscreenHelperEfl::SetAuraParentWindow( @@ -390,6 +412,9 @@ void RWHVAuraOffscreenHelperEfl::PaintTextureToSurface(GLuint texture_id) { evas_gl_api_->glBindTexture(GL_TEXTURE_2D, 0); evas_gl_make_current(evas_gl_, 0, 0); + + // for snapshot + frame_rendered_ = true; } void RWHVAuraOffscreenHelperEfl::InitEvasGL() { @@ -594,6 +619,286 @@ void RWHVAuraOffscreenHelperEfl::EvasToBlinkCords(int x, } } +void RWHVAuraOffscreenHelperEfl::OnEvasRenderFlushPre(void* data, + Evas* evas, + void* event_info) { + RWHVAuraOffscreenHelperEfl* rwhv_helper = + static_cast(data); + if (rwhv_helper && rwhv_helper->snapshot_task_list_.size() > 0) + rwhv_helper->ProcessSnapshotRequest(); +} + +void RWHVAuraOffscreenHelperEfl::InvalidateForSnapshot() { + evas_object_image_pixels_dirty_set(content_image_, true); +} + +void RWHVAuraOffscreenHelperEfl::ProcessSnapshotRequest() { + if (!frame_rendered_) + return; + + // Process all snapshot requests pending now. + for (auto& task : snapshot_task_list_) { + if (!task.is_null()) + std::move(task).Run(); + } + + if (snapshot_timer_->IsRunning()) + snapshot_timer_->Stop(); + // Stop now and clear task list + snapshot_task_list_.clear(); + // Unregister render post event + evas_event_callback_del_full(evas_, EVAS_CALLBACK_RENDER_FLUSH_PRE, + OnEvasRenderFlushPre, this); +} + +void RWHVAuraOffscreenHelperEfl::RunGetSnapshotOnMainThread( + const gfx::Rect snapshot_area, + int request_id, + float scale_factor) { +#if defined(USE_TTRACE) + TTRACE(TTRACE_TAG_WEB, + "RWHVAuraOffscreenHelperEfl::RunGetSnapshotOnMainThread"); +#endif + ScreenshotCapturedCallback* callback = + screen_capture_cb_map_.Lookup(request_id); + + if (!callback) + return; + + if (rwhv_aura_->IsShowing() && evas_focus_get(evas_)) + callback->Run(GetSnapshot(snapshot_area, scale_factor)); + screen_capture_cb_map_.Remove(request_id); +} + +Evas_Object* RWHVAuraOffscreenHelperEfl::GetSnapshot( + const gfx::Rect& snapshot_area, + float scale_factor, + bool is_magnifier) { +#if defined(USE_TTRACE) + TTRACE(TTRACE_TAG_WEB, "RWHVAuraOffscreenHelperEfl::GetSnapshot"); +#endif + if (scale_factor == 0.0) + return nullptr; + + int rotation = + display::Screen::GetScreen()->GetPrimaryDisplay().RotationAsDegree(); + + bool is_evasgl_direct_landscape = false; + // For EvasGL Direct Rendering in landscape mode + if (!is_magnifier) { + is_evasgl_direct_landscape = ((rotation == 90 || rotation == 270) && + !evas_gl_rotation_get(evas_gl_)); + } + + const gfx::Rect window_rect = gfx::ToEnclosingRect(gfx::ConvertRectToPixels( + rwhv_aura_->GetBoundsInRootWindow(), device_scale_factor_)); + // |view_rect| is absolute coordinate of webview. + gfx::Rect view_rect = GetViewBoundsInPix(); + + // the gl coordinate system is based on screen rect for direct rendering. + // if direct rendering is disabled, the coordinate is based on webview. + // TODO(is46.kim) : Even though evas direct rendering flag is set, direct + // rendering may be disabled in the runtime depend on environment. + // There is no way to get current rendering mode. |is_direct_rendering| + // flag should be changed by current rendering mode. + bool is_direct_rendering = !is_magnifier; + if (!is_direct_rendering) { + view_rect.set_x(0); + view_rect.set_y(0); + } + const gfx::Size surface_size = + (is_direct_rendering) ? window_rect.size() : view_rect.size(); + + // |snapshot_area| is relative coordinate in webview. + int x = snapshot_area.x(); + int y = snapshot_area.y(); + int width = snapshot_area.width(); + int height = snapshot_area.height(); + + // Convert |snapshot_area| to absolute coordinate. + x += view_rect.x(); + y += view_rect.y(); + + // Limit snapshot rect by webview size + if (x + width > view_rect.right()) + width = view_rect.right() - x; + if (y + height > view_rect.bottom()) + height = view_rect.bottom() - y; + + // Convert coordinate system for OpenGL. + // (0,0) is top left corner in webview coordinate system. + if (is_evasgl_direct_landscape) { + if (rotation == 270) { + x = surface_size.width() - x - width; + y = surface_size.height() - y - height; + } + std::swap(x, y); + std::swap(width, height); + } else { + // (0,0) is bottom left corner in opengl coordinate system. + y = surface_size.height() - y - height; + } + + int size = width * height * sizeof(GLuint); + GLuint* data = (GLuint*)malloc(size); + if (!data) { + LOG(ERROR) << "Failed to allocate memory for snapshot"; + return nullptr; + } + + { +#if defined(USE_TTRACE) + TTRACE(TTRACE_TAG_WEB, + "RWHVAuraOffscreenHelperEfl::GetSnapshot(ReadPixels)"); +#endif + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent() failed."; + free(data); + return nullptr; + } + + evas_gl_api_->glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, + data); + ClearCurrent(); + } + + if (!is_evasgl_direct_landscape && (rotation == 90 || rotation == 270)) + std::swap(width, height); + +#if _DUMP_SNAPSHOT_ + static int frame_number = 0; + frame_number++; + { + char filename[150]; + sprintf(filename, "/opt/share/dump/snapshot%02d-%d_%dx%d_rgba8888.raw", + frame_number, rotation, width, height); + FILE* fp = fopen(filename, "w"); + if (fp) { + fwrite(data, width * height * 4, 1, fp); + fflush(fp); + fclose(fp); + } else { + LOG(ERROR) << "Unable to open file"; + } + } +#endif + + // flip the Y axis and change color format from RGBA to BGRA + for (int j = 0; j < height / 2; j++) { + for (int i = 0; i < width; i++) { + GLuint& px1 = data[(j * width) + i]; + GLuint& px2 = data[((height - 1) - j) * width + i]; + px1 = ((px1 & 0xff) << 16) | ((px1 >> 16) & 0xff) | (px1 & 0xff00ff00) | + 0xff000000; + px2 = ((px2 & 0xff) << 16) | ((px2 >> 16) & 0xff) | (px2 & 0xff00ff00) | + 0xff000000; + std::swap(px1, px2); + } + } + + SkBitmap bitmap; + if (scale_factor != 1.0 || rotation) { + bitmap.setInfo(SkImageInfo::MakeN32Premul(width, height)); + bitmap.setPixels(data); + + // scaling bitmap + if (scale_factor != 1.0) { + width = scale_factor * width; + height = scale_factor * height; + bitmap = skia::ImageOperations::Resize( + bitmap, skia::ImageOperations::RESIZE_GOOD, width, height); + } + + if (rotation == 90) { + bitmap = SkBitmapOperations::Rotate(bitmap, + SkBitmapOperations::ROTATION_90_CW); + } else if (rotation == 180) { + bitmap = SkBitmapOperations::Rotate(bitmap, + SkBitmapOperations::ROTATION_180_CW); + } else if (rotation == 270) { + bitmap = SkBitmapOperations::Rotate(bitmap, + SkBitmapOperations::ROTATION_270_CW); + } + } + + if (rotation == 90 || rotation == 270) + std::swap(width, height); + + Evas_Object* image = evas_object_image_filled_add(evas_); + if (image) { + evas_object_image_size_set(image, width, height); + evas_object_image_alpha_set(image, EINA_TRUE); + evas_object_image_data_copy_set(image, + bitmap.empty() ? data : bitmap.getPixels()); + evas_object_resize(image, width, height); +#if _DUMP_SNAPSHOT_ + char filename[150]; + sprintf(filename, "/opt/share/dump/snapshot%02d-%d_%dx%d.png", frame_number, + rotation, width, height); + evas_object_image_save(image, filename, NULL, "quality=100"); +#endif + } + free(data); + + return image; +} + +void RWHVAuraOffscreenHelperEfl::RequestSnapshotAsync( + const gfx::Rect& snapshot_area, + Screenshot_Captured_Callback callback, + void* user_data, + float scale_factor) { +#if defined(USE_TTRACE) + TTRACE(TTRACE_TAG_WEB, "RWHVAuraOffscreenHelperEfl::RequestSnapshotAsync"); +#endif + ScreenshotCapturedCallback* cb = + new ScreenshotCapturedCallback(callback, user_data); + + int request_id = screen_capture_cb_map_.Add(base::WrapUnique(cb)); + + if (rwhv_aura_->IsShowing() && evas_focus_get(evas_)) { + // Create a snapshot task that will be executed after frame + // is generated and drawn to surface. + snapshot_task_list_.push_back(base::BindOnce( + &RWHVAuraOffscreenHelperEfl::RunGetSnapshotOnMainThread, + base::Unretained(this), snapshot_area, request_id, scale_factor)); + + // Delete OnEvasRenderPost callback to prevent registration twice. + evas_event_callback_del_full(evas_, EVAS_CALLBACK_RENDER_FLUSH_PRE, + OnEvasRenderFlushPre, this); + evas_event_callback_add(evas_, EVAS_CALLBACK_RENDER_FLUSH_PRE, + OnEvasRenderFlushPre, this); + + // If there is no EVAS_CALLBACK_RENDER_FLUSH_PRE event sent out in 400ms, + // we trigger one by ourself + snapshot_timer_->Start( + FROM_HERE, base::Milliseconds(4 * kSnapshotProcessDelay), + base::BindOnce(&RWHVAuraOffscreenHelperEfl::InvalidateForSnapshot, + base::Unretained(this))); + } else { + // Sends message to renderer to capture the content snapshot of the view. + rwhv_aura_->host()->RequestContentSnapshot(snapshot_area, scale_factor, + request_id); + } +} + +void RWHVAuraOffscreenHelperEfl::DidGetContentSnapshot(const SkBitmap& bitmap, + const int request_id) { + ScreenshotCapturedCallback* callback = + screen_capture_cb_map_.Lookup(request_id); + if (!callback) + return; + + Evas_Object* image = nullptr; + if (!bitmap.empty()) { + image = evas_object_image_filled_add(evas_); + evas_object_image_size_set(image, bitmap.width(), bitmap.height()); + evas_object_image_data_copy_set(image, bitmap.getPixels()); + } + callback->Run(image); + screen_capture_cb_map_.Remove(request_id); +} + Evas_Object* RWHVAuraOffscreenHelperEfl::ewk_view() const { auto wci = static_cast(web_contents_); if (!wci) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h index c4c91f6..a4264d1 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h @@ -38,9 +38,14 @@ class IMContextEfl; namespace content { +typedef void (*Screenshot_Captured_Callback)(Evas_Object* image, + void* user_data); +typedef base::OnceCallback SnapshotTask; + class RenderWidgetHostHelper; class RenderWidgetHostImpl; class RenderWidgetHostViewAura; +class ScreenshotCapturedCallback; class WebContents; class WebContentsDelegate; @@ -80,6 +85,17 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { #endif ); + // |snapshot_area| is relative coordinate system based on Webview. + // (0,0) is top left corner. + Evas_Object* GetSnapshot(const gfx::Rect& snapshot_area, + float scale_factor, + bool is_magnifier = false); + void RequestSnapshotAsync(const gfx::Rect& snapshot_area, + Screenshot_Captured_Callback callback, + void* user_data, + float scale_factor = 1.0); + void DidGetContentSnapshot(const SkBitmap& bitmap, int request_id); + RenderWidgetHostViewAura* rwhva() { return rwhv_aura_; } void OnMouseOrTouchEvent(ui::Event* event); void DidHandleKeyEvent(blink::WebInputEvent::Type input_event_type, @@ -106,6 +122,7 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { static void OnFocusOut(void* data, Evas*, Evas_Object*, void*); static void OnHostFocusIn(void* data, Evas_Object*, void*); static void OnHostFocusOut(void* data, Evas_Object*, void*); + static void OnEvasRenderFlushPre(void* data, Evas* evas, void* event_info); void Initialize(); void InitializeProgram(); @@ -118,6 +135,12 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { bool MakeCurrent(); void ClearBrowserFrame(); + void InvalidateForSnapshot(); + void ProcessSnapshotRequest(); + void RunGetSnapshotOnMainThread(const gfx::Rect snapshot_area, + int request_id, + float scale_factor); + ui::EflEventHandler* GetEventHandler(); ui::IMContextEfl* GetIMContextEfl(); @@ -159,6 +182,12 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { WebContents* web_contents_ = nullptr; std::unique_ptr rwh_helper_; + + bool frame_rendered_ = false; + std::list snapshot_task_list_; + std::unique_ptr snapshot_timer_; + base::IDMap> + screen_capture_cb_map_; }; } // namespace content diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index ec146b6..11e805b 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -1619,75 +1619,23 @@ void EWebView::SetLinkMagnifierEnabled(bool enabled) { bool EWebView::GetSnapshotAsync( Eina_Rectangle rect, Ewk_Web_App_Screenshot_Captured_Callback callback, - void* user_data) { -#if !defined(USE_AURA) - if (!rwhv()) + void* user_data, + float scale_factor) { + if (!rwhva() || !rwhva()->offscreen_helper()) return false; - return rwhv()->RequestSnapshotAsync(rect, callback, user_data); -#else - return false; -#endif + rwhva()->offscreen_helper()->RequestSnapshotAsync( + gfx::Rect(rect.x, rect.y, rect.w, rect.h), callback, user_data, + scale_factor); + return true; } -Evas_Object* EWebView::GetSnapshot(Eina_Rectangle rect) { - Evas_Object* image = NULL; -#if !defined(USE_AURA) -#if BUILDFLAG(IS_TIZEN) - if (!rwhv() || !rwhv()->MakeCurrent()) - return NULL; - - int width = rect.w; - int height = rect.h; - - if (width > rwhv()->GetViewBoundsInPix().width() - rect.x) - width = rwhv()->GetViewBoundsInPix().width() - rect.x; - if (height > rwhv()->GetViewBoundsInPix().height() - rect.y) - height = rwhv()->GetViewBoundsInPix().height() - rect.y; - - int x = rect.x; - int y = rwhv()->GetViewBoundsInPix().height() - height + rect.y; +Evas_Object* EWebView::GetSnapshot(Eina_Rectangle rect, float scale_factor) { + if (!rwhva() || !rwhva()->offscreen_helper()) + return nullptr; - Evas_GL_API* gl_api = rwhv()->evasGlApi(); - DCHECK(gl_api); - int size = width * height * sizeof(GLuint); - - GLuint* tmp = (GLuint*)malloc(size); - if (!tmp) - return NULL; - - GLuint* bits = (GLuint*)malloc(size); - if (!bits) { - free(tmp); - return NULL; - } - - gl_api->glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, - (GLubyte*)bits); - - // flip the Y axis and change color format from RGBA to BGRA - int i, j, idx1, idx2; - GLuint d; - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - idx1 = (j * width) + i; - idx2 = ((height - 1) - j) * width + i; - d = bits[idx1]; - tmp[idx2] = ((d & 0x000000ff) << 16) + ((d & 0x00ff0000) >> 16) + - ((d & 0xff00ff00)); - } - } - - image = evas_object_image_filled_add(rwhv()->evas()); - if (image) { - evas_object_image_size_set(image, width, height); - evas_object_image_alpha_set(image, EINA_TRUE); - evas_object_image_data_copy_set(image, tmp); - evas_object_resize(image, width, height); - } -#endif -#endif - return image; + return rwhva()->offscreen_helper()->GetSnapshot( + gfx::Rect(rect.x, rect.y, rect.w, rect.h), scale_factor); } void EWebView::BackForwardListClear() { diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index b2d0037..f76d97b 100755 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -320,15 +320,16 @@ class EWebView { * Creates a snapshot of given rectangle from EWebView * * @param rect rectangle of EWebView which will be taken into snapshot - * + * @param scale_factor scale factor * @return created snapshot or NULL if error occured. * @note ownership of snapshot is passed to caller - */ - Evas_Object* GetSnapshot(Eina_Rectangle rect); + */ + Evas_Object* GetSnapshot(Eina_Rectangle rect, float scale_factor); bool GetSnapshotAsync(Eina_Rectangle rect, Ewk_Web_App_Screenshot_Captured_Callback callback, - void* user_data); + void* user_data, + float scale_factor); void InvokePolicyResponseCallback(_Ewk_Policy_Decision* policy_decision, bool* defer); void InvokePolicyNavigationCallback(const NavigationPolicyParams& params, diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 05864b8..40d8e79 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -440,13 +440,7 @@ Evas_Object* ewk_view_screenshot_contents_get(const Evas_Object* view, Eina_Rect { EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, NULL); EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, NULL); - // Zoom level equality (<=0.001) is sufficient compared to high precision std::numeric_value::epsilon. - if (!blink::PageZoomValuesEqual(scale_factor, 1.0)) { - LOG(ERROR) << "We only support scale factor of 1.0." - << "Scaling option will be supported after hardware acceleration is enabled."; - return NULL; - } - return impl->GetSnapshot(view_area); + return impl->GetSnapshot(view_area, scale_factor); } Eina_Bool ewk_view_screenshot_contents_get_async(const Evas_Object* view, Eina_Rectangle view_area, @@ -454,13 +448,9 @@ Eina_Bool ewk_view_screenshot_contents_get_async(const Evas_Object* view, Eina_R { EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE); EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, EINA_FALSE); - // Zoom level equality (<=0.001) is sufficient compared to high precision std::numeric_value::epsilon. - if (!blink::PageZoomValuesEqual(scale_factor, 1.0)) { - LOG(ERROR) << "We only support scale factor of 1.0." - << "Scaling option will be supported after hardware acceleration is enabled."; - return EINA_FALSE; - } - return impl->GetSnapshotAsync(view_area, callback, user_data) ? EINA_TRUE : EINA_FALSE; + return impl->GetSnapshotAsync(view_area, callback, user_data, scale_factor) + ? EINA_TRUE + : EINA_FALSE; } unsigned int ewk_view_inspector_server_start(Evas_Object* ewkView, unsigned int port) diff --git a/tizen_src/ewk/ubrowser/window.cc b/tizen_src/ewk/ubrowser/window.cc index 8e17761..f34e706 100644 --- a/tizen_src/ewk/ubrowser/window.cc +++ b/tizen_src/ewk/ubrowser/window.cc @@ -408,6 +408,15 @@ void Window::SetAutoRotate() { (sizeof(rots) / sizeof(int))); } +void Window::TakeScreenshotAsync() { + log_trace("%s", __PRETTY_FUNCTION__); + Eina_Rectangle rect; + EINA_RECTANGLE_SET(&rect, 0, 0, 400, 400); + ewk_view_screenshot_contents_get_async(web_view_, rect, 1.0, + evas_object_evas_get(web_view_), + &Window::OnScreenshotCaptured, NULL); +} + #if BUILDFLAG(IS_TIZEN_TV) void Window::On_Video_Playback_Load(void* data, Evas_Object*, @@ -824,6 +833,17 @@ void Window::SetGoogleDataProxyHeaders() const { ewk_view_custom_header_add(web_view_, "accept", "image/webp,*/*;q=0.8"); } +void Window::OnScreenshotCaptured(Evas_Object* image, void* user_data) { + log_trace("%s", __PRETTY_FUNCTION__); + static int c = 1; + char buf[250]; + sprintf(buf, "screenshot%d.png", c++); + if (evas_object_image_save(image, buf, 0, 0)) + log_info("Screenshot image saved in %s", buf); + else + log_info("Screenshot image could not be saved"); +} + void Window::Exit() const { browser_.Exit(); } diff --git a/tizen_src/ewk/ubrowser/window.h b/tizen_src/ewk/ubrowser/window.h index eaff40a..9289c70 100644 --- a/tizen_src/ewk/ubrowser/window.h +++ b/tizen_src/ewk/ubrowser/window.h @@ -22,7 +22,7 @@ class Window { Window(Browser&, int width, int height, bool incognito); ~Window(); - Evas_Object* GetEvasObject() const { return window_; }; + Evas_Object* GetEvasObject() const { return window_; } Ewk_Settings* GetEwkSettings() const; void LoadURL(std::string url); @@ -51,6 +51,7 @@ class Window { void ShowInspectorURL(const char* url); void SetGoogleDataProxyHeaders() const; void SetAutoRotate(); + void TakeScreenshotAsync(); void Exit() const; IdType Id() const; @@ -67,6 +68,7 @@ class Window { static void OnNewWindowPolicyDecide(void*, Evas_Object*, void*); static void OnBackForwardListChanged(void*, Evas_Object*, void*); static void OnQuotaPermissionRequest(Evas_Object*, const Ewk_Quota_Permission_Request*, void*); + static void OnScreenshotCaptured(Evas_Object*, void*); static void OnUserMediaPermissionRequest(void* data, Evas_Object*, void* event_info); static void OnUserMediaPermissionDecisionTaken(bool decision, void* data); static void OnEnterFullScreenRequest(void*, Evas_Object*, void*); diff --git a/tizen_src/ewk/ubrowser/window_ui.cc b/tizen_src/ewk/ubrowser/window_ui.cc index d2145f7..dd30408 100644 --- a/tizen_src/ewk/ubrowser/window_ui.cc +++ b/tizen_src/ewk/ubrowser/window_ui.cc @@ -312,6 +312,9 @@ Evas_Object* WindowUI::CreateExtraActionsMenu(Evas_Object* parent) { elm_ctxpopup_item_append(menu_, "Change page zoom level", NULL, &WindowUI::OnShowZoomPopup, this); + elm_ctxpopup_item_append(menu_, "Take screenshot async", NULL, + &WindowUI::OnTakeScreenshotAsync, this); + elm_ctxpopup_item_append(menu_, "Quit", NULL, &WindowUI::Exit, this); return menu_; @@ -669,6 +672,13 @@ void WindowUI::OnShowZoomPopup(void* data, Evas_Object* obj, void*) { thiz->CloseMenu(); } +void WindowUI::OnTakeScreenshotAsync(void* data, Evas_Object* obj, void*) { + log_trace("%s", __PRETTY_FUNCTION__); + WindowUI* thiz = static_cast(data); + thiz->window_.TakeScreenshotAsync(); + thiz->CloseMenu(); +} + void WindowUI::OnZoomChanged(void* data, Evas_Object* obj, void*) { log_trace("%s", __PRETTY_FUNCTION__); WindowUI* thiz = static_cast(data); diff --git a/tizen_src/ewk/ubrowser/window_ui.h b/tizen_src/ewk/ubrowser/window_ui.h index 0a05495..b7a4ebf9 100644 --- a/tizen_src/ewk/ubrowser/window_ui.h +++ b/tizen_src/ewk/ubrowser/window_ui.h @@ -89,6 +89,7 @@ class WindowUI { static void ClosePopup(void* data, Evas_Object*, void*); static void OnShowZoomPopup(void* data, Evas_Object*, void*); + static void OnTakeScreenshotAsync(void* data, Evas_Object*, void*); static void OnZoomChanged(void* data, Evas_Object*, void*); static void OnRememberFormDataChange(void* data, Evas_Object*, void*); static void OnRememberPasswordChange(void* data, Evas_Object*, void*); -- 2.7.4 From 0a0f0759b0cd7b55d35b42537895db2461452bbc Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Thu, 19 Jan 2023 16:19:23 +0530 Subject: [PATCH 05/16] fixup! [M108 Migration] Remove EWK_BRINGUP from EWebView::ExecuteJavaScript This patch fixes the error[1] that occurs during starting of efl_webview_app on both desktop and tv [1] RAW: Bad variant access, Aborted (core dumped) Reference: https://review.tizen.org/gerrit/c/273935 Change-Id: I1617011377bedf37ab9142b0efa3012fd89e147a Signed-off-by: Bakka Uday Kiran --- tizen_src/ewk/efl_integration/eweb_view.cc | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 11e805b..821c731 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -4,8 +4,13 @@ #include "eweb_view.h" +#include +#include +#include + #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/json/json_string_value_serializer.h" #include "base/logging.h" #include "base/pickle.h" #include "base/strings/utf_string_conversions.h" @@ -65,10 +70,6 @@ #include "web_contents_delegate_efl.h" #include "web_contents_efl_delegate_ewk.h" -#include -#include -#include - #include using namespace content; @@ -705,7 +706,19 @@ void JavaScriptComplete(JavaScriptCallbackDetails* script_callback_data, if (!script_callback_data->callback_func_) return; - std::string return_string = result.GetString(); + std::string return_string; + if (result.is_string()) { + // We don't want to serialize strings with JSONStringValueSerializer + // to avoid quotation marks. + return_string = result.GetString(); + } else if (result.is_none()) { + // Value::TYPE_NULL is for lack of value, undefined, null + return_string = ""; + } else { + JSONStringValueSerializer serializer(&return_string); + serializer.Serialize(result); + } + script_callback_data->callback_func_(script_callback_data->view_, return_string.c_str(), script_callback_data->user_data_); -- 2.7.4 From ceb51cd64c8bbcfc5a461e5043746722925f6322 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Thu, 19 Jan 2023 09:06:35 +0530 Subject: [PATCH 06/16] [M108 Migration] Bringup Native DateTime InputPicker Add the missed implementations for Native Date Time Input Picker. Add support for datetime input type. (Datetime input type is deprecated.) Add changes get/setenv to vconf_get_str/vconf_set_str for security issue in input picker It also fixes error of InputPicker. Reference: https://review.tizen.org/gerrit/274427/ Change-Id: I9c3f0b76521cdfa972e3a0bb4a42e97f196f3997 Signed-off-by: Ayush Kumar --- content/browser/browser_interface_binders.cc | 19 +- content/browser/web_contents/web_contents_impl.cc | 7 + content/child/runtime_features.cc | 5 + third_party/blink/public/blink_resources.grd | 1 + .../public/mojom/choosers/date_time_chooser.mojom | 2 +- .../blink/public/platform/web_runtime_features.h | 3 + third_party/blink/renderer/core/BUILD.gn | 12 ++ .../core/html/forms/date_time_local_input_type.cc | 69 +++++-- .../core/html/forms/date_time_local_input_type.h | 12 ++ .../core/html/forms/external_date_time_chooser.cc | 20 ++ .../core/html/forms/external_date_time_chooser.h | 8 + .../blink/renderer/core/html/forms/input_type.cc | 6 + third_party/blink/renderer/core/layout/build.gni | 2 +- .../blink/renderer/core/style/computed_style.h | 6 + .../platform/exported/web_runtime_features.cc | 6 + .../renderer/platform/text/date_components.cc | 177 ++++++++++++++++ .../blink/renderer/platform/text/date_components.h | 14 ++ .../renderer/platform/text/platform_locale.cc | 3 + .../chromium_impl/content/browser/browser_efl.gni | 2 + .../content/browser/date_time_chooser_efl.cc | 59 ++++++ .../content/browser/date_time_chooser_efl.h | 52 +++++ .../public/browser/web_contents_efl_delegate.h | 6 + .../core/rendering/RenderThemeChromiumTizen.cpp | 34 ---- .../core/rendering/RenderThemeChromiumTizen.h | 32 --- .../third_party/blink/renderer/core/core_efl.gni | 21 ++ .../renderer/core/css}/themeChromiumTizen.css | 0 .../core/layout/layout_theme_chromium_tizen.cc | 67 ++++++ .../core/layout/layout_theme_chromium_tizen.h | 25 +++ .../browser/input_picker/color_chooser_efl.h | 2 +- .../browser/input_picker/input_picker.cc | 225 ++++++++++++--------- .../browser/input_picker/input_picker.h | 53 ++--- tizen_src/ewk/efl_integration/eweb_view.cc | 9 +- tizen_src/ewk/efl_integration/eweb_view.h | 11 +- .../web_contents_efl_delegate_ewk.cc | 7 + .../web_contents_efl_delegate_ewk.h | 4 + 35 files changed, 773 insertions(+), 208 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/date_time_chooser_efl.cc create mode 100644 tizen_src/chromium_impl/content/browser/date_time_chooser_efl.h delete mode 100644 tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.cpp delete mode 100644 tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.h create mode 100644 tizen_src/chromium_impl/third_party/blink/renderer/core/core_efl.gni rename tizen_src/chromium_impl/third_party/{WebKit/Source/core/rendering => blink/renderer/core/css}/themeChromiumTizen.css (100%) create mode 100644 tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.cc create mode 100644 tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.h diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index ba1ffe3..adac0a4 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc @@ -206,6 +206,10 @@ #include "media/fuchsia/mojom/fuchsia_media_resource_provider.mojom.h" #endif +#if BUILDFLAG(IS_EFL) +#include "content/browser/date_time_chooser_efl.h" +#endif + namespace blink { class StorageKey; } // namespace blink @@ -299,6 +303,16 @@ void BindSharedWorkerConnector( SharedWorkerConnectorImpl::Create(host->GetGlobalId(), std::move(receiver)); } +#if BUILDFLAG(IS_EFL) +void BindDateTimeChooserForFrame( + content::RenderFrameHost* host, + mojo::PendingReceiver receiver) { + auto* date_time_chooser = DateTimeChooserEfl::FromWebContents( + WebContents::FromRenderFrameHost(host)); + date_time_chooser->OnDateTimeChooserReceiver(std::move(receiver)); +} +#endif + #if BUILDFLAG(IS_ANDROID) void BindDateTimeChooserForFrame( RenderFrameHost* host, @@ -1065,7 +1079,10 @@ void PopulateBinderMapWithContext( map->Add(base::BindRepeating( &EmptyBinderForFrame)); #endif // BUILDFLAG(IS_ANDROID) - +#if BUILDFLAG(IS_EFL) + map->Add( + base::BindRepeating(&BindDateTimeChooserForFrame)); +#endif map->Add( base::BindRepeating(&ClipboardHostImpl::Create)); map->Add( diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 2fc5272..0f16da0 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -187,6 +187,10 @@ #include "ui/gfx/geometry/dip_util.h" #endif +#if BUILDFLAG(IS_EFL) +#include "content/browser/date_time_chooser_efl.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "content/browser/android/date_time_chooser_android.h" #include "content/browser/android/java_interfaces_impl.h" @@ -3129,6 +3133,9 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params, #if BUILDFLAG(IS_ANDROID) DateTimeChooserAndroid::CreateForWebContents(this); #endif +#if BUILDFLAG(IS_EFL) + DateTimeChooserEfl::CreateForWebContents(this); +#endif // BrowserPluginGuest::Init needs to be called after this WebContents has // a RenderWidgetHostViewChildFrame. That is, |view_->CreateView| above. diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 49473c7..208ace0 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc @@ -118,6 +118,11 @@ void SetRuntimeFeatureDefaultsForPlatform( WebRuntimeFeatures::EnableMediaControlsExpandGesture( base::FeatureList::IsEnabled(media::kMediaControlsExpandGesture)); #endif + +#if BUILDFLAG(IS_EFL) + // No plan to support complex UI for date/time INPUT types. + WebRuntimeFeatures::EnableInputMultipleFieldsUI(false); +#endif } enum RuntimeFeatureEnableOptions { diff --git a/third_party/blink/public/blink_resources.grd b/third_party/blink/public/blink_resources.grd index a06d71e..44f8953 100644 --- a/third_party/blink/public/blink_resources.grd +++ b/third_party/blink/public/blink_resources.grd @@ -16,6 +16,7 @@ + diff --git a/third_party/blink/public/mojom/choosers/date_time_chooser.mojom b/third_party/blink/public/mojom/choosers/date_time_chooser.mojom index 75c80e2..9867a51 100644 --- a/third_party/blink/public/mojom/choosers/date_time_chooser.mojom +++ b/third_party/blink/public/mojom/choosers/date_time_chooser.mojom @@ -32,7 +32,7 @@ interface DateTimeChooser { // Requires for opening a date/time dialog, and then |dialog_value| is // returned to replace a date/time input field. OpenDateTimeDialog(DateTimeDialogValue value) => - (bool success, double dialog_value); + (bool success, string dialog_value); // Dismiss the date/time dialog. CloseDateTimeDialog(); diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index e282c6e..5897b64b 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h @@ -67,6 +67,9 @@ class BLINK_PLATFORM_EXPORT WebRuntimeFeatures : public WebRuntimeFeaturesBase { static void EnableOverlayScrollbars(bool); static void EnableFluentScrollbars(bool); +#if BUILDFLAG(IS_EFL) + static void EnableInputMultipleFieldsUI(bool); +#endif WebRuntimeFeatures() = delete; }; diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index f6dff62..afb80e2 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn @@ -2,6 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +if (use_efl) { + import( + "//tizen_src/chromium_impl/third_party/blink/renderer/core/core_efl.gni") +} + import("//build/config/chromecast_build.gni") import("//build/config/compiler/compiler.gni") import("//build/config/dcheck_always_on.gni") @@ -342,6 +347,13 @@ component("core") { "//ui/gfx/geometry:geometry_skia", ] + if (use_efl) { + sources -= + rebase_path(external_exclude_webkit_core_layout_sources, "", "layout") + sources += external_webkit_core_layout_sources + deps += external_webkit_core_generated_deps + } + if (is_mac) { deps += [ "//ui/base/mojom" ] } diff --git a/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc b/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc index 3e0a3c2..44f141f 100644 --- a/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc @@ -47,12 +47,23 @@ static const int kDateTimeLocalDefaultStep = 60; static const int kDateTimeLocalDefaultStepBase = 0; static const int kDateTimeLocalStepScaleFactor = 1000; +#if BUILDFLAG(IS_EFL) +InputType* DateTimeLocalInputType::CreateDateTime(HTMLInputElement& element) { + return MakeGarbageCollected(element, true); +} +#endif + void DateTimeLocalInputType::CountUsage() { CountUsageIfVisible(WebFeature::kInputTypeDateTimeLocal); } const AtomicString& DateTimeLocalInputType::FormControlType() const { +#if BUILDFLAG(IS_EFL) + return is_date_time_ ? input_type_names::kDatetime + : input_type_names::kDatetimeLocal; +#else return input_type_names::kDatetimeLocal; +#endif } double DateTimeLocalInputType::ValueAsDate() const { @@ -87,6 +98,10 @@ bool DateTimeLocalInputType::ParseToDateComponentsInternal( DateComponents* out) const { DCHECK(out); unsigned end; +#if BUILDFLAG(IS_EFL) + if (is_date_time_) + return out->ParseDateTime(string, 0, end) && end == string.length(); +#endif return out->ParseDateTimeLocal(string, 0, end) && end == string.length(); } @@ -104,6 +119,9 @@ String DateTimeLocalInputType::LocalizeValue( return proposed_value; Locale::FormatType format_type = ShouldHaveSecondField(date) +#if BUILDFLAG(IS_EFL) + || is_date_time_ +#endif ? Locale::kFormatTypeMedium : Locale::kFormatTypeShort; String localized = GetElement().GetLocale().FormatDateTime(date, format_type); @@ -127,6 +145,12 @@ String DateTimeLocalInputType::FormatDateTimeFieldsState( !date_time_fields_state.HasMinute() || !date_time_fields_state.HasAMPM()) return g_empty_string; +#if BUILDFLAG(IS_EFL) + String additional_format = is_date_time_ ? "Z" : ""; +#else + String additional_format = ""; +#endif + if (date_time_fields_state.HasMillisecond() && date_time_fields_state.Millisecond()) { // According to WPTs and other browsers, we should remove trailing zeros @@ -138,39 +162,54 @@ String DateTimeLocalInputType::FormatDateTimeFieldsState( milliseconds.Truncate(milliseconds.length() - 1); } return String::Format( - "%04u-%02u-%02uT%02u:%02u:%02u.%s", date_time_fields_state.Year(), - date_time_fields_state.Month(), date_time_fields_state.DayOfMonth(), - date_time_fields_state.Hour24(), date_time_fields_state.Minute(), - date_time_fields_state.HasSecond() ? date_time_fields_state.Second() - : 0, - milliseconds.Ascii().c_str()); + "%04u-%02u-%02uT%02u:%02u:%02u.%s", + date_time_fields_state.Year(), date_time_fields_state.Month(), + date_time_fields_state.DayOfMonth(), + date_time_fields_state.Hour24(), date_time_fields_state.Minute(), + date_time_fields_state.HasSecond() + ? date_time_fields_state.Second() + : 0, + milliseconds.Ascii().c_str()) + + additional_format; } if (date_time_fields_state.HasSecond() && date_time_fields_state.Second()) { return String::Format( - "%04u-%02u-%02uT%02u:%02u:%02u", date_time_fields_state.Year(), - date_time_fields_state.Month(), date_time_fields_state.DayOfMonth(), - date_time_fields_state.Hour24(), date_time_fields_state.Minute(), - date_time_fields_state.Second()); + "%04u-%02u-%02uT%02u:%02u:%02u", date_time_fields_state.Year(), + date_time_fields_state.Month(), + date_time_fields_state.DayOfMonth(), + date_time_fields_state.Hour24(), date_time_fields_state.Minute(), + date_time_fields_state.Second()) + + additional_format; } return String::Format( - "%04u-%02u-%02uT%02u:%02u", date_time_fields_state.Year(), - date_time_fields_state.Month(), date_time_fields_state.DayOfMonth(), - date_time_fields_state.Hour24(), date_time_fields_state.Minute()); + "%04u-%02u-%02uT%02u:%02u", date_time_fields_state.Year(), + date_time_fields_state.Month(), + date_time_fields_state.DayOfMonth(), + date_time_fields_state.Hour24(), date_time_fields_state.Minute()) + + additional_format; } void DateTimeLocalInputType::SetupLayoutParameters( DateTimeEditElement::LayoutParameters& layout_parameters, const DateComponents& date) const { +#if BUILDFLAG(IS_EFL) + String additional_format = is_date_time_ ? "'Z'" : ""; +#else + String additional_format = ""; +#endif + if (ShouldHaveSecondField(date)) { layout_parameters.date_time_format = layout_parameters.locale.DateTimeFormatWithSeconds(); - layout_parameters.fallback_date_time_format = "yyyy-MM-dd'T'HH:mm:ss"; + layout_parameters.fallback_date_time_format = + "yyyy-MM-dd'T'HH:mm:ss" + additional_format; } else { layout_parameters.date_time_format = layout_parameters.locale.DateTimeFormatWithoutSeconds(); - layout_parameters.fallback_date_time_format = "yyyy-MM-dd'T'HH:mm"; + layout_parameters.fallback_date_time_format = + "yyyy-MM-dd'T'HH:mm" + additional_format; } if (!ParseToDateComponents( GetElement().FastGetAttribute(html_names::kMinAttr), diff --git a/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h b/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h index b0aa26a..1736146 100644 --- a/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h +++ b/third_party/blink/renderer/core/html/forms/date_time_local_input_type.h @@ -39,8 +39,16 @@ class ExceptionState; class DateTimeLocalInputType final : public BaseTemporalInputType { public: +#if BUILDFLAG(IS_EFL) + explicit DateTimeLocalInputType(HTMLInputElement& element, + bool is_date_time = false) + : BaseTemporalInputType(Type::kDateTimeLocal, element), + is_date_time_(is_date_time) {} + static InputType* CreateDateTime(HTMLInputElement&); +#else explicit DateTimeLocalInputType(HTMLInputElement& element) : BaseTemporalInputType(Type::kDateTimeLocal, element) {} +#endif private: void CountUsage() override; @@ -70,6 +78,10 @@ class DateTimeLocalInputType final : public BaseTemporalInputType { bool has_minute, bool has_second) const override; String AriaLabelForPickerIndicator() const override; + +#if BUILDFLAG(IS_EFL) + bool is_date_time_; +#endif }; template <> diff --git a/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc b/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc index f87fccd..8a22ed5 100644 --- a/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc +++ b/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc @@ -45,7 +45,11 @@ static ui::TextInputType ToTextInputType(const AtomicString& source) { if (source == input_type_names::kDate) return ui::TextInputType::TEXT_INPUT_TYPE_DATE; if (source == input_type_names::kDatetime) +#if BUILDFLAG(IS_EFL) + return ui::TextInputType::TEXT_INPUT_TYPE_DATE_TIME; +#else return ui::TextInputType::TEXT_INPUT_TYPE_TIME; +#endif if (source == input_type_names::kDatetimeLocal) return ui::TextInputType::TEXT_INPUT_TYPE_DATE_TIME_LOCAL; if (source == input_type_names::kMonth) @@ -92,7 +96,11 @@ void ExternalDateTimeChooser::OpenDateTimeChooser( } void ExternalDateTimeChooser::ResponseHandler(bool success, +#if BUILDFLAG(IS_EFL) + const String& dialog_value) { +#else double dialog_value) { +#endif if (success) DidChooseValue(dialog_value); else @@ -118,6 +126,17 @@ mojom::blink::DateTimeChooser& ExternalDateTimeChooser::GetDateTimeChooser( return *date_time_chooser_.get(); } +#if BUILDFLAG(IS_EFL) +void ExternalDateTimeChooser::DidChooseValue(const String& value) { + if (client_) + client_->DidChooseValue(value); + // didChooseValue might run JavaScript code, and endChooser() might be + // called. However DateTimeChooserCompletionImpl still has one reference to + // this object. + if (client_) + client_->DidEndChooser(); +} +#else void ExternalDateTimeChooser::DidChooseValue(double value) { // Cache the owner element first, because DidChooseValue might run // JavaScript code and destroy |client|. @@ -138,6 +157,7 @@ void ExternalDateTimeChooser::DidChooseValue(double value) { if (client_) client_->DidEndChooser(); } +#endif void ExternalDateTimeChooser::DidCancelChooser() { if (client_) diff --git a/third_party/blink/renderer/core/html/forms/external_date_time_chooser.h b/third_party/blink/renderer/core/html/forms/external_date_time_chooser.h index a071089..57961f8 100644 --- a/third_party/blink/renderer/core/html/forms/external_date_time_chooser.h +++ b/third_party/blink/renderer/core/html/forms/external_date_time_chooser.h @@ -45,12 +45,20 @@ class CORE_EXPORT ExternalDateTimeChooser final : public DateTimeChooser { // |frame| must not be null. void OpenDateTimeChooser(LocalFrame* frame, const DateTimeChooserParameters&); +#if BUILDFLAG(IS_EFL) + void ResponseHandler(bool success, const String& dialog_value); +#else void ResponseHandler(bool success, double dialog_value); +#endif bool IsShowingDateTimeChooserUI() const; private: +#if BUILDFLAG(IS_EFL) + void DidChooseValue(const String& value); +#else void DidChooseValue(double); +#endif void DidCancelChooser(); // DateTimeChooser function: diff --git a/third_party/blink/renderer/core/html/forms/input_type.cc b/third_party/blink/renderer/core/html/forms/input_type.cc index c8fd38b..a22687c 100644 --- a/third_party/blink/renderer/core/html/forms/input_type.cc +++ b/third_party/blink/renderer/core/html/forms/input_type.cc @@ -86,6 +86,7 @@ namespace blink { INPUT_TYPE(kCheckbox, CheckboxInputType) \ INPUT_TYPE(kColor, ColorInputType) \ INPUT_TYPE(kDate, DateInputType) \ + INPUT_TYPE(kDatetime, DateTimeLocalInputType) \ INPUT_TYPE(kDatetimeLocal, DateTimeLocalInputType) \ INPUT_TYPE(kEmail, EmailInputType) \ INPUT_TYPE(kFile, FileInputType) \ @@ -109,6 +110,11 @@ InputType* InputType::Create(HTMLInputElement& element, if (type_name.empty()) return MakeGarbageCollected(element); +#if BUILDFLAG(IS_EFL) + if (type_name == input_type_names::kDatetime) + return MakeGarbageCollected(element, true); +#endif + #define INPUT_TYPE_FACTORY(input_type, class_name) \ if (type_name == input_type_names::input_type) \ return MakeGarbageCollected(element); diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni index 8c806e3..2780062 100644 --- a/third_party/blink/renderer/core/layout/build.gni +++ b/third_party/blink/renderer/core/layout/build.gni @@ -819,7 +819,7 @@ if (is_win) { blink_core_sources_layout += [ "layout_theme_font_provider_default.cc" ] } -if (is_linux || is_chromeos || is_tizen) { +if (is_linux || is_chromeos) { blink_core_sources_layout += [ "layout_theme_linux.cc", "layout_theme_linux.h", diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 90f5a5b..d9e8aae 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h @@ -100,6 +100,9 @@ class StyleInitialData; class StyleResolver; class StyleSelfAlignmentData; class TransformationMatrix; +#if BUILDFLAG(IS_EFL) +class LayoutThemeChromiumTizen; +#endif namespace css_longhand { @@ -289,6 +292,9 @@ class ComputedStyle : public ComputedStyleBase, friend class StyleResolver; // Access to UserModify(). friend class MatchedPropertiesCache; +#if BUILDFLAG(IS_EFL) + friend class LayoutThemeChromiumTizen; +#endif protected: mutable std::unique_ptr cached_data_; diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 424852d..5dd2b16 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc @@ -65,4 +65,10 @@ void WebRuntimeFeatures::EnableFluentScrollbars(bool enable) { ScrollbarThemeSettings::SetFluentScrollbarsEnabled(enable); } +#if BUILDFLAG(IS_EFL) +void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) { + RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable); +} +#endif + } // namespace blink diff --git a/third_party/blink/renderer/platform/text/date_components.cc b/third_party/blink/renderer/platform/text/date_components.cc index 54950b2..1d267b7 100644 --- a/third_party/blink/renderer/platform/text/date_components.cc +++ b/third_party/blink/renderer/platform/text/date_components.cc @@ -337,6 +337,183 @@ bool DateComponents::ParseDateTimeLocal(const String& src, return true; } +#if BUILDFLAG(IS_EFL) +bool DateComponents::AddDay(int day_diff) { + DCHECK(month_day_); + + int day = month_day_ + day_diff; + if (day > MaxDayOfMonth(year_, month_)) { + day = month_day_; + int year = year_; + int month = month_; + int max_day = MaxDayOfMonth(year, month); + for (; day_diff > 0; --day_diff) { + ++day; + if (day > max_day) { + day = 1; + ++month; + if (month >= 12) { // month is 0-origin. + month = 0; + ++year; + } + max_day = MaxDayOfMonth(year, month); + } + } + if (!WithinHTMLDateLimits(year, month, day)) + return false; + year_ = year; + month_ = month; + } else if (day < 1) { + int month = month_; + int year = year_; + day = month_day_; + for (; day_diff < 0; ++day_diff) { + --day; + if (day < 1) { + --month; + if (month < 0) { + month = 11; + --year; + } + day = MaxDayOfMonth(year, month); + } + } + if (!WithinHTMLDateLimits(year, month, day)) + return false; + year_ = year; + month_ = month; + } else { + if (!WithinHTMLDateLimits(year_, month_, day)) + return false; + } + month_day_ = day; + return true; +} + +bool DateComponents::AddMinute(int minute) { + // This function is used to adjust timezone offset. So year_, month_, + // month_day_ have values between the lower and higher limits. + DCHECK(WithinHTMLDateLimits(year_, month_, month_day_)); + + int carry; + // minute can be negative or greater than 59. + minute += minute_; + if (minute > 59) { + carry = minute / 60; + minute = minute % 60; + } else if (minute < 0) { + carry = (59 - minute) / 60; + minute += carry * 60; + carry = -carry; + DCHECK_GE(minute, 0); + DCHECK_LE(minute, 59); + } else { + if (!WithinHTMLDateLimits(year_, month_, month_day_, hour_, minute, second_, + millisecond_)) + return false; + minute_ = minute; + return true; + } + + int hour = hour_ + carry; + if (hour > 23) { + carry = hour / 24; + hour = hour % 24; + } else if (hour < 0) { + carry = (23 - hour) / 24; + hour += carry * 24; + carry = -carry; + DCHECK_GE(hour, 0); + DCHECK_LE(hour, 23); + } else { + if (!WithinHTMLDateLimits(year_, month_, month_day_, hour, minute, second_, + millisecond_)) + return false; + minute_ = minute; + hour_ = hour; + return true; + } + if (!AddDay(carry)) + return false; + if (!WithinHTMLDateLimits(year_, month_, month_day_, hour, minute, second_, + millisecond_)) + return false; + minute_ = minute; + hour_ = hour; + return true; +} + +// Parses a timezone part, and adjust year_, month_, month_day_, hour_, minute_, +// second_, and millisecond_. +bool DateComponents::ParseTimeZone(const String& src, + unsigned start, + unsigned& end) { + if (start >= src.length()) + return false; + unsigned index = start; + if (src[index] == 'Z') { + end = index + 1; + return true; + } + + bool minus; + if (src[index] == '+') + minus = false; + else if (src[index] == '-') + minus = true; + else + return false; + ++index; + + int hour; + int minute; + if (!ToInt(src, index, 2, hour) || hour < 0 || hour > 23) + return false; + index += 2; + + if (index >= src.length() || src[index] != ':') + return false; + ++index; + + if (!ToInt(src, index, 2, minute) || minute < 0 || minute > 59) + return false; + index += 2; + + if (minus) { + hour = -hour; + minute = -minute; + } + + // Subtract the timezone offset. + if (!AddMinute(-(hour * 60 + minute))) + return false; + end = index; + return true; +} + +bool DateComponents::ParseDateTime(const String& src, + unsigned start, + unsigned& end) { + unsigned index; + if (!ParseDate(src, start, index)) + return false; + if (index >= src.length()) + return false; + if (src[index] != 'T') + return false; + ++index; + if (!ParseTime(src, index, index)) + return false; + if (!ParseTimeZone(src, index, end)) + return false; + if (!WithinHTMLDateLimits(year_, month_, month_day_, hour_, minute_, second_, + millisecond_)) + return false; + type_ = kDateTime; + return true; +} +#endif + static inline double PositiveFmod(double value, double divider) { double remainder = fmod(value, divider); return remainder < 0 ? remainder + divider : remainder; diff --git a/third_party/blink/renderer/platform/text/date_components.h b/third_party/blink/renderer/platform/text/date_components.h index 90ceadd..e0eeef2 100644 --- a/third_party/blink/renderer/platform/text/date_components.h +++ b/third_party/blink/renderer/platform/text/date_components.h @@ -64,6 +64,9 @@ class PLATFORM_EXPORT DateComponents { enum Type { kInvalid, kDate, +#if BUILDFLAG(IS_EFL) + kDateTime, +#endif kDateTimeLocal, kMonth, kTime, @@ -113,6 +116,17 @@ class PLATFORM_EXPORT DateComponents { bool ParseTime(const String& src, unsigned start, unsigned& end); // Sets FullYear, Month, MonthDay, Hour, Minute, Second and Millisecond. bool ParseDateTimeLocal(const String&, unsigned start, unsigned& end); +#if BUILDFLAG(IS_EFL) + // Sets year, month, monthDay, hour, minute, second and millisecond, and + // adjusts timezone. + // For kDateTime type. Updates FullYear, Month, MonthDay, Hour, Minute, + // Second and Millisecond. + bool ParseDateTime(const String&, unsigned start, unsigned& end); + bool SetMillisecondsSinceEpochForDateTime(double ms); + bool ParseTimeZone(const String&, unsigned start, unsigned& end); + bool AddDay(int); + bool AddMinute(int); +#endif // The following SetMillisecondsSinceEpochFor*() functions take // the number of milliseconds since 1970-01-01 00:00:00.000 UTC as diff --git a/third_party/blink/renderer/platform/text/platform_locale.cc b/third_party/blink/renderer/platform/text/platform_locale.cc index 9bac9f2..351da70 100644 --- a/third_party/blink/renderer/platform/text/platform_locale.cc +++ b/third_party/blink/renderer/platform/text/platform_locale.cc @@ -572,6 +572,9 @@ String Locale::FormatDateTime(const DateComponents& date, case DateComponents::kWeek: builder.Build(WeekFormatInLDML()); break; +#if BUILDFLAG(IS_EFL) + case DateComponents::kDateTime: +#endif case DateComponents::kDateTimeLocal: builder.Build(format_type == kFormatTypeShort ? DateTimeFormatWithoutSeconds() diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index 4a1548a..b6a1022 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -66,6 +66,8 @@ external_content_browser_efl_deps = [ # Source ############################################################################## external_content_browser_efl_sources = [ + "//tizen_src/chromium_impl/content/browser/date_time_chooser_efl.cc", + "//tizen_src/chromium_impl/content/browser/date_time_chooser_efl.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/public/browser/web_contents_efl_delegate.h", diff --git a/tizen_src/chromium_impl/content/browser/date_time_chooser_efl.cc b/tizen_src/chromium_impl/content/browser/date_time_chooser_efl.cc new file mode 100644 index 0000000..372ca2b --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/date_time_chooser_efl.cc @@ -0,0 +1,59 @@ +// 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 "content/browser/date_time_chooser_efl.h" +#include "chromium_impl/content/browser/web_contents/web_contents_impl_efl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "ewk/efl_integration/web_contents_efl_delegate_ewk.h" + +namespace content { + +// DateTimeChooserEfl implementation +DateTimeChooserEfl::DateTimeChooserEfl(WebContents* web_contents) + : web_contents_(web_contents), + date_time_chooser_receiver_(this), + WebContentsUserData(*web_contents) {} + +void DateTimeChooserEfl::OnDateTimeChooserReceiver( + mojo::PendingReceiver receiver) { + // Disconnect the previous picker first. + date_time_chooser_receiver_.reset(); + date_time_chooser_receiver_.Bind(std::move(receiver)); +} + +DateTimeChooserEfl::~DateTimeChooserEfl() {} + +void DateTimeChooserEfl::OpenDateTimeDialog( + blink::mojom::DateTimeDialogValuePtr value, + OpenDateTimeDialogCallback callback) { + if (open_date_time_response_callback_) { + date_time_chooser_receiver_.ReportBadMessage( + "DateTimeChooserAndroid: Previous picker's binding isn't closed."); + return; + } + open_date_time_response_callback_ = std::move(callback); + + WebContentsImplEfl* wcie = static_cast(web_contents_); + if (wcie->GetEflDelegate()) + wcie->GetEflDelegate()->OpenDateTimeDialog(value->dialog_type, + value->dialog_value, this); + else + std::move(open_date_time_response_callback_).Run(false, ""); +} + +void DateTimeChooserEfl::CloseDateTimeDialog() {} + +void DateTimeChooserEfl::ReplaceDateTime(const std::string& value) { + if (open_date_time_response_callback_) + std::move(open_date_time_response_callback_).Run(true, value); +} + +void DateTimeChooserEfl::CancelDialog() { + if (open_date_time_response_callback_) + std::move(open_date_time_response_callback_).Run(false, ""); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(DateTimeChooserEfl); + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/date_time_chooser_efl.h b/tizen_src/chromium_impl/content/browser/date_time_chooser_efl.h new file mode 100644 index 0000000..f6abda5 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/date_time_chooser_efl.h @@ -0,0 +1,52 @@ +// 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_EFL_DATE_TIME_CHOOSER_EFL_H_ +#define CONTENT_BROWSER_EFL_DATE_TIME_CHOOSER_EFL_H_ + +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/mojom/choosers/date_time_chooser.mojom.h" + +#include "ui/base/ime/text_input_type.h" +#include "ui/gfx/native_widget_types.h" + +namespace content { + +class WebContents; +// Efl implementation for DateTimeChooser dialogs. +class DateTimeChooserEfl : public blink::mojom::DateTimeChooser, + public WebContentsUserData { + public: + explicit DateTimeChooserEfl(WebContents* web_contents); + ~DateTimeChooserEfl() override; + + DateTimeChooserEfl(const DateTimeChooserEfl&) = delete; + DateTimeChooserEfl& operator=(const DateTimeChooserEfl&) = delete; + + void OnDateTimeChooserReceiver( + mojo::PendingReceiver receiver); + + // blink::mojom::DateTimeChooser implementation: + // Shows the dialog. |value| is the date/time value converted to a + // number as defined in HTML. (See blink::InputType::parseToNumber()) + void OpenDateTimeDialog(blink::mojom::DateTimeDialogValuePtr value, + OpenDateTimeDialogCallback callback) override; + void CloseDateTimeDialog() override; + + void ReplaceDateTime(const std::string& value); + void CancelDialog(); + + private: + friend class WebContentsUserData; + WebContents* web_contents_; + + mojo::Receiver date_time_chooser_receiver_; + + OpenDateTimeDialogCallback open_date_time_response_callback_; + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace content +#endif // CONTENT_BROWSER_EFL_DATE_TIME_CHOOSER_EFL_H_ 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 75d3cc5..dcbe9d2 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 @@ -8,12 +8,14 @@ #include #include "base/callback.h" +#include "content/browser/date_time_chooser_efl.h" #include "content/common/content_export.h" #include "content/public/browser/context_menu_params.h" #include "services/device/public/mojom/screen_orientation_lock_types.mojom.h" #include "third_party/blink/public/common/context_menu_data/menu_item_info.h" #include "third_party/blink/public/common/input/web_gesture_event.h" #include "third_party/blink/public/common/input/web_input_event.h" +#include "ui/base/ime/text_input_type.h" #include "ui/gfx/geometry/rect.h" class GURL; @@ -69,6 +71,10 @@ class CONTENT_EXPORT WebContentsEflDelegate { virtual void OrientationLock(device::mojom::ScreenOrientationLockType) = 0; virtual void OrientationUnlock() = 0; + virtual void OpenDateTimeDialog( + ui::TextInputType dialog_type, + double dialog_value, + content::DateTimeChooserEfl* date_chooser) = 0; }; } // namespace content diff --git a/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.cpp b/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.cpp deleted file mode 100644 index 834c387..0000000 --- a/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 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 "RenderThemeChromiumTizen.h" - -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -// FIXME: EWK_BRINGUP definition should be removed. -#include "TizenUserAgentStyleSheets.h" -#endif - -namespace blink { - -scoped_refptr RenderThemeChromiumTizen::Create() { - return base::AdoptRef(new RenderThemeChromiumTizen()); -} - -LayoutTheme& LayoutTheme::NativeTheme() { - DEFINE_STATIC_REF(LayoutTheme, layout_theme, - (RenderThemeChromiumTizen::Create())); - return *layout_theme; -} - -RenderThemeChromiumTizen::~RenderThemeChromiumTizen() {} - -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -// FIXME: EWK_BRINGUP definition should be removed. -String RenderThemeChromiumTizen::ExtraDefaultStyleSheet() { - return LayoutThemeDefault::extraDefaultStyleSheet() + - String(themeChromiumTizenCss, sizeof(themeChromiumTizenCss)); -} -#endif - -} // namespace blink diff --git a/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.h b/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.h deleted file mode 100644 index 25339c4..0000000 --- a/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/RenderThemeChromiumTizen.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 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 RenderThemeChromiumTizen_h -#define RenderThemeChromiumTizen_h - -#include "third_party/blink/renderer/core/layout/layout_theme_default.h" - -namespace blink { - -class RenderThemeChromiumTizen final : public LayoutThemeDefault { - public: - static scoped_refptr Create(); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - // FIXME: EWK_BRINGUP definition should be removed. - String ExtraDefaultStyleSheet() override; -#endif - bool DelegatesMenuListRendering() const override { return true; } - - Color PlatformTapHighlightColor() const override { - return RenderThemeChromiumTizen::defaultTapHighlightColor; - } - - private: - ~RenderThemeChromiumTizen() override; - static const RGBA32 defaultTapHighlightColor = 0x2eee6e1a; // light orange. -}; - -} // namespace blink - -#endif // RenderThemeChromiumTizen_h diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/core/core_efl.gni b/tizen_src/chromium_impl/third_party/blink/renderer/core/core_efl.gni new file mode 100644 index 0000000..bacbb9c --- /dev/null +++ b/tizen_src/chromium_impl/third_party/blink/renderer/core/core_efl.gni @@ -0,0 +1,21 @@ +# Copyright (c) 2015 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. + +external_exclude_webkit_core_layout_sources = [] + +if (!is_tizen) { + external_exclude_webkit_core_layout_sources += [ + "layout_theme_linux.cc", + "layout_theme_linux.h", + ] +} + +external_webkit_core_layout_sources = [ + "//tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.cc", + "//tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.h", +] + +# For //third_party/blink/renderer/core:core_generated target +external_webkit_core_generated_deps = + [ "//tizen_src/chromium_impl/tizen:system-info" ] diff --git a/tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/themeChromiumTizen.css b/tizen_src/chromium_impl/third_party/blink/renderer/core/css/themeChromiumTizen.css similarity index 100% rename from tizen_src/chromium_impl/third_party/WebKit/Source/core/rendering/themeChromiumTizen.css rename to tizen_src/chromium_impl/third_party/blink/renderer/core/css/themeChromiumTizen.css diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.cc b/tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.cc new file mode 100644 index 0000000..bd7edce --- /dev/null +++ b/tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.cc @@ -0,0 +1,67 @@ +// Copyright 2014, 2016 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 "layout_theme_chromium_tizen.h" + +#include "core/style/computed_style.h" +#include "platform/web_test_support.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/web_theme_engine.h" +#include "third_party/blink/public/resources/grit/blink_resources.h" +#include "third_party/blink/renderer/platform/data_resource_helper.h" +#include "tizen/system_info.h" + +namespace blink { + +static const RGBA32 kDefaultTapHighlightColorTizen = + 0x2eee6e1a; // Light orange +static const RGBA32 kDefaultFocusOutlineColorTizen = + 0xff00dae5; // (255,0,218,229) +static const RGBA32 kFocusOutlineColorTizenTv = 0xff0077f6; // (255,0,119,246) + +scoped_refptr LayoutThemeChromiumTizen::Create() { + return base::AdoptRef(new LayoutThemeChromiumTizen()); +} + +LayoutTheme& LayoutTheme::NativeTheme() { + DEFINE_STATIC_REF(LayoutTheme, layout_theme, + LayoutThemeChromiumTizen::Create()); + return *layout_theme; +} + +String LayoutThemeChromiumTizen::ExtraDefaultStyleSheet() { + return LayoutThemeDefault::ExtraDefaultStyleSheet() + + UncompressResourceAsASCIIString(IDR_UASTYLE_THEME_CHROMIUM_TIZEN_CSS); +} + +bool LayoutThemeChromiumTizen::DelegatesMenuListRendering() const { + return IsTvProfile() ? false : true; +} + +Color LayoutThemeChromiumTizen::PlatformTapHighlightColor() const { + return ColorFromPremultipliedARGB(kDefaultTapHighlightColorTizen); +} + +Color LayoutThemeChromiumTizen::PlatformFocusRingColor() const { + return IsTvProfile() + ? ColorFromPremultipliedARGB(kFocusOutlineColorTizenTv) + : ColorFromPremultipliedARGB(kDefaultFocusOutlineColorTizen); +} + +void LayoutThemeChromiumTizen::AdjustInnerSpinButtonStyle( + ComputedStyle& style) const { + if (!IsMobileProfile()) { + LayoutThemeDefault::AdjustInnerSpinButtonStyle(style); + return; + } + if (WebTestSupport::IsRunningWebTest()) { + gfx::Size size = Platform::Current()->ThemeEngine()->GetSize( + WebThemeEngine::kPartInnerSpinButton); + + style.SetWidth(Length::Fixed(size.width())); + style.SetMinWidth(Length::Fixed(size.width())); + } +} + +} // namespace blink diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.h b/tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.h new file mode 100644 index 0000000..8098069 --- /dev/null +++ b/tizen_src/chromium_impl/third_party/blink/renderer/core/layout/layout_theme_chromium_tizen.h @@ -0,0 +1,25 @@ +// Copyright 2014, 2016 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 LayoutThemeChromiumTizen_h +#define LayoutThemeChromiumTizen_h + +#include "core/layout/layout_theme_default.h" + +namespace blink { + +class LayoutThemeChromiumTizen final : public LayoutThemeDefault { + public: + static scoped_refptr Create(); + + String ExtraDefaultStyleSheet() override; + bool DelegatesMenuListRendering() const override; + Color PlatformTapHighlightColor() const override; + Color PlatformFocusRingColor() const override; + void AdjustInnerSpinButtonStyle(ComputedStyle&) const override; +}; + +} // namespace blink + +#endif // LayoutThemeChromiumTizen_h diff --git a/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h b/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h index 9091a33..a383af1 100644 --- a/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h +++ b/tizen_src/ewk/efl_integration/browser/input_picker/color_chooser_efl.h @@ -18,7 +18,7 @@ class WebContents; class ColorChooserEfl : public ColorChooser { public: ColorChooserEfl(WebContents& web_contents); - ~ColorChooserEfl(); + ~ColorChooserEfl() override; ColorChooserEfl(const ColorChooserEfl&) = delete; ColorChooserEfl& operator=(const ColorChooserEfl&) = delete; diff --git a/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc index af7b8ff..ed4fa9d 100644 --- a/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc +++ b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.cc @@ -16,11 +16,8 @@ #include "common/web_contents_utils.h" #include "content/common/paths_efl.h" #include "content/public/browser/web_contents.h" -#include "eweb_view.h" -#include "tizen/system_info.h" #if BUILDFLAG(IS_TIZEN) -#include #include #endif @@ -29,7 +26,6 @@ namespace content { static const char* kDefaultDatetimeFormat = "%Y/%m/%d %H:%M"; InputPicker::Layout::Layout(InputPicker* parent) : parent_(parent) { - CHECK(parent_); evas_object_focus_set(parent_->web_view_->evas_object(), false); // FIXME: Workaround. OSP requirement. OSP want to block own touch event // while webkit internal picker is running. @@ -57,17 +53,19 @@ InputPicker::Layout::~Layout() { } // static -std::unique_ptr -InputPicker::Layout::CreateAndShowColorPickerLayout(InputPicker* parent, - int r, - int g, - int b) { +InputPicker::Layout* InputPicker::Layout::CreateAndShowColorPickerLayout( + InputPicker* parent, + int r, + int g, + int b) { std::unique_ptr picker_layout(new Layout(parent)); picker_layout->is_color_picker_ = true; - if (!picker_layout->AddBaseLayout("Select color", - "colorselector_popup_layout")) + if (!picker_layout->AddBaseLayout( + dgettext("WebKit", "IDS_WEBVIEW_HEADER_SELECT_COLOUR"), + "colorselector_popup_layout")) { return nullptr; + } picker_layout->color_rect_ = evas_object_rectangle_add(evas_object_evas_get(picker_layout->layout_)); @@ -84,33 +82,32 @@ InputPicker::Layout::CreateAndShowColorPickerLayout(InputPicker* parent, if (!picker_layout->AddColorSelector(r, g, b)) return nullptr; - if (!picker_layout->AddOKButton()) + if (!picker_layout->AddButtons()) return nullptr; - evas_object_show(picker_layout->layout_); - elm_object_content_set(picker_layout->popup_, picker_layout->layout_); - evas_object_show(picker_layout->popup_); - picker_layout->red_ = r; picker_layout->green_ = g; picker_layout->blue_ = b; picker_layout->AddColorPickerCallbacks(); - - return picker_layout; + evas_object_show(picker_layout->popup_); + return picker_layout.release(); } static char* GetDateTimeFormat() { #if BUILDFLAG(IS_TIZEN) - char* language = getenv("LANGUAGE"); - setenv("LANGUAGE", "en_US", 1); + char* language = vconf_get_str(VCONFKEY_LANGSET); + if (!vconf_set_str(VCONFKEY_LANGSET, "en_US")) + LOG(ERROR) << "vconf_set_str failed "; char* region_format = vconf_get_str(VCONFKEY_REGIONFORMAT); if (!region_format) return nullptr; int time_value = 0; - char buf[256] = {0}; + char buf[256] = { + 0, + }; vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &time_value); if (time_value == VCONFKEY_TIME_FORMAT_24) snprintf(buf, sizeof(buf), "%s_DTFMT_24HR", region_format); @@ -142,17 +139,16 @@ static char* GetDateTimeFormat() { } } - if (!language || !strcmp(language, "")) - unsetenv("LANGUAGE"); - else - setenv("LANGUAGE", language, 1); - char* date_time_format = dgettext("dt_fmt", buf); + if (language && !vconf_set_str(VCONFKEY_LANGSET, language)) + LOG(ERROR) << "vconf_set_str failed "; + // FIXME: Workaround fix for not supported dt_fmt. // Use default format if dt_fmt string is not exist. if (strlen(date_time_format) == strlen(buf) && - !strncmp(date_time_format, buf, strlen(buf))) + !strncmp(date_time_format, buf, strlen(buf))) { return nullptr; + } return strdup(date_time_format); #else @@ -161,10 +157,10 @@ static char* GetDateTimeFormat() { } // static -std::unique_ptr -InputPicker::Layout::CreateAndShowDateLayout(InputPicker* parent, - struct tm* current_time, - ui::TextInputType type) { +InputPicker::Layout* InputPicker::Layout::CreateAndShowDateLayout( + InputPicker* parent, + struct tm* current_time, + ui::TextInputType type) { std::unique_ptr picker_layout(new Layout(parent)); picker_layout->input_type_ = type; @@ -189,8 +185,9 @@ InputPicker::Layout::CreateAndShowDateLayout(InputPicker* parent, } if (!picker_layout->AddBaseLayout(dgettext("WebKit", title.c_str()), - "date_popup")) + "date_popup")) { return nullptr; + } picker_layout->date_picker_ = elm_datetime_add(picker_layout->layout_); if (!picker_layout->date_picker_) @@ -210,7 +207,7 @@ InputPicker::Layout::CreateAndShowDateLayout(InputPicker* parent, elm_datetime_value_set(picker_layout->date_picker_, current_time); - if (!picker_layout->AddOKButton()) + if (!picker_layout->AddButtons()) return nullptr; if (type == ui::TEXT_INPUT_TYPE_MONTH) { @@ -224,17 +221,16 @@ InputPicker::Layout::CreateAndShowDateLayout(InputPicker* parent, picker_layout->AddDatePickerCallbacks(); - elm_object_content_set(picker_layout->popup_, picker_layout->layout_); evas_object_show(picker_layout->popup_); - return picker_layout; + return picker_layout.release(); } // static -std::unique_ptr -InputPicker::Layout::CreateAndShowDateTimeLayout(InputPicker* parent, - struct tm* current_time, - ui::TextInputType type) { +InputPicker::Layout* InputPicker::Layout::CreateAndShowDateTimeLayout( + InputPicker* parent, + struct tm* current_time, + ui::TextInputType type) { std::unique_ptr picker_layout(new Layout(parent)); picker_layout->input_type_ = type; @@ -242,8 +238,9 @@ InputPicker::Layout::CreateAndShowDateTimeLayout(InputPicker* parent, elm_object_scale_set(picker_layout->popup_, 0.7); if (!picker_layout->AddBaseLayout( dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_DATE_AND_TIME"), - "datetime_popup")) + "datetime_popup")) { return nullptr; + } picker_layout->time_picker_ = elm_datetime_add(picker_layout->layout_); picker_layout->date_picker_ = elm_datetime_add(picker_layout->layout_); @@ -270,38 +267,38 @@ InputPicker::Layout::CreateAndShowDateTimeLayout(InputPicker* parent, elm_datetime_value_set(picker_layout->date_picker_, current_time); elm_datetime_value_set(picker_layout->time_picker_, current_time); - - if (!picker_layout->AddOKButton()) + if (!picker_layout->AddButtons()) return nullptr; picker_layout->AddDatePickerCallbacks(); - - elm_object_content_set(picker_layout->popup_, picker_layout->layout_); evas_object_show(picker_layout->popup_); - return picker_layout; + return picker_layout.release(); +} + +bool InputPicker::Layout::SetDatetimePicker(Evas_Object* picker, + const char* style) { + return false; } // static -std::unique_ptr -InputPicker::Layout::CreateAndShowTimeLayout(InputPicker* parent, - struct tm* current_time) { +InputPicker::Layout* InputPicker::Layout::CreateAndShowTimeLayout( + InputPicker* parent, + struct tm* current_time) { std::unique_ptr picker_layout(new Layout(parent)); picker_layout->input_type_ = ui::TEXT_INPUT_TYPE_TIME; if (!picker_layout->AddBaseLayout( - dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_TIME"), "date_popup")) + dgettext("WebKit", "IDS_WEBVIEW_HEADER_SET_TIME"), "date_popup")) { return nullptr; + } picker_layout->time_picker_ = elm_datetime_add(picker_layout->layout_); if (!picker_layout->time_picker_) return nullptr; - elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime", - picker_layout->time_picker_); elm_object_style_set(picker_layout->time_picker_, "time_layout"); - elm_object_part_content_set(picker_layout->layout_, "elm.swallow.datetime", picker_layout->time_picker_); @@ -316,7 +313,7 @@ InputPicker::Layout::CreateAndShowTimeLayout(InputPicker* parent, elm_datetime_value_set(picker_layout->time_picker_, current_time); - if (!picker_layout->AddOKButton()) + if (!picker_layout->AddButtons()) return nullptr; elm_datetime_field_visible_set(picker_layout->time_picker_, ELM_DATETIME_YEAR, @@ -328,18 +325,14 @@ InputPicker::Layout::CreateAndShowTimeLayout(InputPicker* parent, picker_layout->AddDatePickerCallbacks(); - elm_object_content_set(picker_layout->popup_, picker_layout->layout_); evas_object_show(picker_layout->popup_); - return picker_layout; + return picker_layout.release(); } bool InputPicker::Layout::AddBaseLayout(const char* title, const char* layout_group) { - Evas_Object* top_widget = elm_object_top_widget_get( - elm_object_parent_widget_get(parent_->web_view_->evas_object())); - if (!top_widget) - return false; + Evas_Object* top_widget = parent_->web_view_->GetElmWindow(); conformant_ = elm_conformant_add(top_widget); if (!conformant_) @@ -364,6 +357,7 @@ bool InputPicker::Layout::AddBaseLayout(const char* title, return false; elm_popup_align_set(popup_, ELM_NOTIFY_ALIGN_FILL, 1.0); + elm_object_part_text_set(popup_, "title,text", title); evas_object_size_hint_weight_set(popup_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); @@ -371,28 +365,38 @@ bool InputPicker::Layout::AddBaseLayout(const char* title, if (!layout_) return false; + elm_object_content_set(popup_, layout_); base::FilePath edj_dir; - base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); base::FilePath control_path; + base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir); control_path = edj_dir.Append(FILE_PATH_LITERAL("control.edj")); elm_layout_file_set(layout_, control_path.AsUTF8Unsafe().c_str(), layout_group); - - 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_size_hint_weight_set(layout_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); return true; } -bool InputPicker::Layout::AddOKButton() { - ok_button_ = elm_button_add(popup_); - if (!ok_button_) +bool InputPicker::Layout::AddButtons() { + set_button_ = elm_button_add(popup_); + cancel_button_ = elm_button_add(popup_); + if (!cancel_button_) + return false; + elm_object_domain_translatable_part_text_set( + cancel_button_, NULL, "WebKit", "IDS_WEBVIEW_BUTTON_CANCEL_ABB4"); + + if (!set_button_) return false; - elm_object_style_set(ok_button_, "popup"); - elm_object_text_set(ok_button_, "OK"); - elm_object_part_content_set(popup_, "button1", ok_button_); - evas_object_focus_set(ok_button_, true); + elm_object_domain_translatable_part_text_set(set_button_, NULL, "WebKit", + "IDS_WEBVIEW_BUTTON_SET_ABB2"); + elm_object_style_set(set_button_, "popup"); + elm_object_style_set(cancel_button_, "popup"); + elm_object_part_content_set(popup_, "button2", set_button_); + elm_object_part_content_set(popup_, "button1", cancel_button_); + evas_object_focus_set(cancel_button_, true); + evas_object_focus_set(set_button_, true); return true; } @@ -415,7 +419,10 @@ bool InputPicker::Layout::AddColorSelector(int r, int g, int b) { Eina_List* list = nullptr; Elm_Object_Item* it = nullptr; void* item = nullptr; - int red = 0, green = 0, blue = 0, alpha = 0; + int red = 0; + int green = 0; + int blue = 0; + int alpha = 0; EINA_LIST_FOREACH(color_list, list, item) { if (item) { @@ -443,11 +450,10 @@ bool InputPicker::Layout::AddColorSelector(int r, int g, int b) { void InputPicker::Layout::AddColorPickerCallbacks() { evas_object_smart_callback_add(color_picker_, "color,item,selected", ColorPickerItemSelectedCallback, color_rect_); - - evas_object_smart_callback_add(ok_button_, "clicked", + evas_object_smart_callback_add(set_button_, "clicked", ColorPickerSelectFinishedCallback, this); #if BUILDFLAG(IS_TIZEN) - eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, + eext_object_event_callback_add(layout_, EEXT_CALLBACK_BACK, ColorPickerBackKeyCallback, this); #endif } @@ -458,22 +464,28 @@ void InputPicker::Layout::DeleteColorPickerCallbacks() { ColorPickerItemSelectedCallback); } - if (ok_button_) { - evas_object_smart_callback_del(ok_button_, "clicked", + if (set_button_) { + evas_object_smart_callback_del(set_button_, "clicked", ColorPickerSelectFinishedCallback); } + if (cancel_button_) { + evas_object_smart_callback_del(cancel_button_, "clicked", + ColorPickerBackKeyCallback); + } #if BUILDFLAG(IS_TIZEN) if (popup_) { - eext_object_event_callback_del(popup_, EEXT_CALLBACK_BACK, + eext_object_event_callback_del(layout_, EEXT_CALLBACK_BACK, ColorPickerBackKeyCallback); } #endif } void InputPicker::Layout::AddDatePickerCallbacks() { - evas_object_smart_callback_add(ok_button_, "clicked", + evas_object_smart_callback_add(set_button_, "clicked", DatePickerSelectFinishedCallback, this); + evas_object_smart_callback_add(cancel_button_, "clicked", + DatePickerBackKeyCallback, this); if (input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD || input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME || @@ -489,16 +501,20 @@ void InputPicker::Layout::AddDatePickerCallbacks() { } #if BUILDFLAG(IS_TIZEN) - eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, + eext_object_event_callback_add(layout_, EEXT_CALLBACK_BACK, DatePickerBackKeyCallback, this); #endif } void InputPicker::Layout::DeleteDatePickerCallbacks() { - if (ok_button_) { - evas_object_smart_callback_del(ok_button_, "clicked", + if (set_button_) { + evas_object_smart_callback_del(set_button_, "clicked", DatePickerSelectFinishedCallback); } + if (cancel_button_) { + evas_object_smart_callback_del(cancel_button_, "clicked", + DatePickerBackKeyCallback); + } if (input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD || input_type_ == ui::TEXT_INPUT_TYPE_DATE_TIME || @@ -515,7 +531,7 @@ void InputPicker::Layout::DeleteDatePickerCallbacks() { #if BUILDFLAG(IS_TIZEN) if (popup_) { - eext_object_event_callback_del(popup_, EEXT_CALLBACK_BACK, + eext_object_event_callback_del(layout_, EEXT_CALLBACK_BACK, DatePickerBackKeyCallback); } #endif @@ -525,7 +541,7 @@ void InputPicker::Layout::DeleteDatePickerCallbacks() { void InputPicker::Layout::ColorPickerItemSelectedCallback(void* data, Evas_Object* obj, void* event_info) { - int r = 0, g = 0, b = 0, a = 0; + int r(0), g(0), b(0), a(0); Elm_Object_Item* color_it = static_cast(event_info); elm_colorselector_palette_item_color_get(color_it, &r, &g, &b, &a); evas_object_color_set(static_cast(data), r, g, b, a); @@ -537,7 +553,7 @@ void InputPicker::Layout::ColorPickerSelectFinishedCallback(void* data, void* event_info) { Layout* picker_layout = static_cast(data); - int r = 0, g = 0, b = 0, a = 0; + int r(0), g(0), b(0), a(0); evas_object_color_get(picker_layout->color_rect_, &r, &g, &b, &a); picker_layout->parent_->web_view_->web_contents() @@ -596,7 +612,10 @@ void InputPicker::Layout::DatePickerSelectFinishedCallback(void* data, break; } - picker_layout->parent_->RemoveDatePicker(); + // call the callback + picker_layout->parent_->web_view_->GetDateTimeChooser()->ReplaceDateTime( + std::string(dateStr)); + picker_layout->parent_->RemoveDatePicker(false); } // static @@ -616,7 +635,6 @@ void InputPicker::Layout::DatePickerItemChangedCallback(void* data, } } -#if BUILDFLAG(IS_TIZEN) // static void InputPicker::Layout::ColorPickerBackKeyCallback(void* data, Evas_Object* obj, @@ -635,15 +653,20 @@ void InputPicker::Layout::DatePickerBackKeyCallback(void* data, Evas_Object* obj, void* event_info) { Layout* picker_layout = static_cast(data); - if (picker_layout) - picker_layout->parent_->RemoveDatePicker(); + if (picker_layout) { + picker_layout->parent_->web_view_->GetDateTimeChooser()->CancelDialog(); + // pass true to RemoveDatePicker to cancelDateTimeDialog + picker_layout->parent_->RemoveDatePicker(true); + } } -#endif -InputPicker::InputPicker(EWebView* view) : web_view_(view) {} +InputPicker::InputPicker(EWebView* view) + : web_view_(view), picker_layout_(nullptr) {} + +InputPicker::~InputPicker() {} void InputPicker::ShowColorPicker(int r, int g, int b, int a) { - picker_layout_ = Layout::CreateAndShowColorPickerLayout(this, r, g, b); + picker_layout_.reset(Layout::CreateAndShowColorPickerLayout(this, r, g, b)); if (!picker_layout_) { LOG(ERROR) << "Failed to create color picker."; // We need to notify engine that default color is chosen @@ -678,24 +701,23 @@ void InputPicker::ShowDatePicker(ui::TextInputType input_type, gmtime_r(&timep, &tm); } struct tm* current_time = &tm; - switch (input_type) { case ui::TEXT_INPUT_TYPE_DATE: case ui::TEXT_INPUT_TYPE_WEEK: case ui::TEXT_INPUT_TYPE_MONTH: { - picker_layout_ = - Layout::CreateAndShowDateLayout(this, current_time, input_type); + picker_layout_.reset( + Layout::CreateAndShowDateLayout(this, current_time, input_type)); break; } case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: case ui::TEXT_INPUT_TYPE_DATE_TIME: case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: { - picker_layout_ = - Layout::CreateAndShowDateTimeLayout(this, current_time, input_type); + picker_layout_.reset( + Layout::CreateAndShowDateTimeLayout(this, current_time, input_type)); break; } case ui::TEXT_INPUT_TYPE_TIME: { - picker_layout_ = Layout::CreateAndShowTimeLayout(this, current_time); + picker_layout_.reset(Layout::CreateAndShowTimeLayout(this, current_time)); break; } default: @@ -705,6 +727,11 @@ void InputPicker::ShowDatePicker(ui::TextInputType input_type, if (!picker_layout_) { LOG(ERROR) << "Failed to create date picker."; + // We need to notify engine that empty string is chosen + // otherwise selecting will never be finished. + + // Call the callback + web_view_->GetDateTimeChooser()->ReplaceDateTime(std::string()); } } @@ -716,11 +743,13 @@ void InputPicker::RemoveColorPicker() { web_view_->web_contents().DidEndColorChooser(); } -void InputPicker::RemoveDatePicker() { +void InputPicker::RemoveDatePicker(bool cancel) { if (!picker_layout_) return; + if (cancel) + web_view_->GetDateTimeChooser()->CancelDialog(); picker_layout_.reset(); } -} // namespace content +} // namespace content \ No newline at end of file diff --git a/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h index ab2737ef..2733bcd6 100644 --- a/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h +++ b/tizen_src/ewk/efl_integration/browser/input_picker/input_picker.h @@ -12,13 +12,18 @@ #include "ewk/efl_integration/eweb_view.h" #include "ui/base/ime/text_input_type.h" +#if BUILDFLAG(IS_TIZEN) +#include +#endif + class EWebView; namespace content { class InputPicker { public: - explicit InputPicker(EWebView* web_view); + explicit InputPicker(EWebView* view); + ~InputPicker(); InputPicker(const InputPicker&) = delete; InputPicker& operator=(const InputPicker&) = delete; @@ -29,19 +34,18 @@ class InputPicker { private: class Layout { public: - static std::unique_ptr - CreateAndShowColorPickerLayout(InputPicker* parent, int r, int g, int b); - static std::unique_ptr CreateAndShowDateLayout( - InputPicker* parent, - struct tm* currentTime, - ui::TextInputType type); - static std::unique_ptr CreateAndShowDateTimeLayout( - InputPicker* parent, - struct tm* currentTime, - ui::TextInputType type); - static std::unique_ptr CreateAndShowTimeLayout( - InputPicker* parent, - struct tm* currentTime); + static Layout* CreateAndShowColorPickerLayout(InputPicker* parent, + int r, + int g, + int b); + static Layout* CreateAndShowDateLayout(InputPicker* parent, + struct tm* currentTime, + ui::TextInputType type); + static Layout* CreateAndShowDateTimeLayout(InputPicker* parent, + struct tm* currentTime, + ui::TextInputType type); + static Layout* CreateAndShowTimeLayout(InputPicker* parent, + struct tm* currentTime); ~Layout(); @@ -52,13 +56,15 @@ class InputPicker { Layout& operator=(const Layout&) = delete; bool AddBaseLayout(const char* title, const char* layout_group); - bool AddOKButton(); + bool AddButtons(); bool AddColorSelector(int r, int g, int b); void AddColorPickerCallbacks(); void DeleteColorPickerCallbacks(); void AddDatePickerCallbacks(); void DeleteDatePickerCallbacks(); + bool SetDatetimePicker(Evas_Object* picker, const char* style); + static void ColorPickerSelectFinishedCallback(void* data, Evas_Object* obj, void* event_info); @@ -72,27 +78,28 @@ class InputPicker { Evas_Object* obj, void* event_info); -#if BUILDFLAG(IS_TIZEN) static void ColorPickerBackKeyCallback(void* data, Evas_Object* obj, void* event_info); static void DatePickerBackKeyCallback(void* data, Evas_Object* obj, void* event_info); -#endif - InputPicker* parent_ = nullptr; + InputPicker* parent_; Evas_Object* conformant_ = nullptr; Evas_Object* popup_ = nullptr; Evas_Object* layout_ = nullptr; - Evas_Object* ok_button_ = nullptr; + Evas_Object* set_button_ = nullptr; + Evas_Object* cancel_button_ = nullptr; Evas_Object* color_picker_ = nullptr; Evas_Object* color_rect_ = nullptr; Evas_Object* date_picker_ = nullptr; Evas_Object* time_picker_ = nullptr; - - ui::TextInputType input_type_; +#if BUILDFLAG(IS_TIZEN) && !BUILDFLAG(IS_TIZEN_TV) + Eext_Circle_Surface* circle_surface_ = nullptr; +#endif + ui::TextInputType input_type_ = ui::TEXT_INPUT_TYPE_NONE; bool is_color_picker_ = false; int red_ = 0; int green_ = 0; @@ -100,7 +107,7 @@ class InputPicker { }; void RemoveColorPicker(); - void RemoveDatePicker(); + void RemoveDatePicker(bool cancel); EWebView* web_view_; std::unique_ptr picker_layout_; @@ -108,4 +115,4 @@ class InputPicker { } // namespace content -#endif // EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_INPUT_PICKER_H_ +#endif // EWK_EFL_INTEGRATION_BROWSER_INPUT_PICKER_INPUT_PICKER_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 821c731..fcad346 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -363,6 +363,11 @@ Evas_Object* EWebView::GetHostWindowDelegate(const content::WebContents* wc) { return thiz->evas_object_; } +Evas_Object* EWebView::GetElmWindow() const { + Evas_Object* parent = elm_object_parent_widget_get(evas_object_); + return parent ? elm_object_top_widget_get(parent) : nullptr; +} + void EWebView::SetURL(const GURL& url) { NavigationController::LoadURLParams params(url); params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE; @@ -2135,8 +2140,10 @@ bool EWebView::SetColorPickerColor(int r, int g, int b, int a) { } void EWebView::InputPickerShow(ui::TextInputType input_type, - double input_value) { + double input_value, + content::DateTimeChooserEfl* date_time_chooser) { input_picker_.reset(new InputPicker(this)); + date_time_chooser_ = date_time_chooser; input_picker_->ShowDatePicker(input_type, input_value); } diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index f76d97b..93a0b53 100755 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -22,6 +22,7 @@ #include "base/synchronization/waitable_event.h" #include "browser/input_picker/input_picker.h" #include "browser/selectpicker/popup_picker.h" +#include "content/browser/date_time_chooser_efl.h" #include "content/browser/renderer_host/event_with_latency_info.h" #include "content/browser/selection/selection_controller_efl.h" #include "content/public/browser/context_menu_params.h" @@ -191,6 +192,7 @@ class EWebView { Ewk_Context* context() const { return context_.get(); } Evas_Object* evas_object() const { return evas_object_; } Evas_Object* native_view() const { return native_view_; } + Evas_Object* GetElmWindow() const; Evas* GetEvas() const { return evas_object_evas_get(evas_object_); } PermissionPopupManager* GetPermissionPopupManager() const { return permission_popup_manager_.get(); @@ -439,7 +441,9 @@ class EWebView { void RequestColorPicker(int r, int g, int b, int a); bool SetColorPickerColor(int r, int g, int b, int a); - void InputPickerShow(ui::TextInputType input_type, double input_value); + void InputPickerShow(ui::TextInputType input_type, + double input_value, + content::DateTimeChooserEfl* date_time_chooser); void ShowContentsDetectedPopup(const char*); @@ -498,6 +502,10 @@ class EWebView { void OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, const gfx::Vector2dF& latest_overscroll_delta); + content::DateTimeChooserEfl* GetDateTimeChooser() { + return date_time_chooser_; + } + private: void InitializeContent(); void InitializeWindowTreeHost(); @@ -644,6 +652,7 @@ class EWebView { std::unique_ptr host_; std::unique_ptr focus_client_; std::unique_ptr window_parenting_client_; + content::DateTimeChooserEfl* date_time_chooser_ = nullptr; }; const unsigned int g_default_tilt_motion_sensitivity = 3; diff --git a/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.cc b/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.cc index d010dc8..31e1496 100644 --- a/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.cc +++ b/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.cc @@ -89,4 +89,11 @@ void WebContentsEflDelegateEwk::OrientationLock( void WebContentsEflDelegateEwk::OrientationUnlock() { WebViewDelegateEwk::GetInstance().RequestHandleOrientationUnlock(web_view_); +} + +void WebContentsEflDelegateEwk::OpenDateTimeDialog( + ui::TextInputType dialog_type, + double dialog_value, + content::DateTimeChooserEfl* date_time_chooser) { + web_view_->InputPickerShow(dialog_type, dialog_value, date_time_chooser); } \ No newline at end of file diff --git a/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.h b/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.h index 98065a1..38f8222 100644 --- a/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.h +++ b/tizen_src/ewk/efl_integration/web_contents_efl_delegate_ewk.h @@ -44,6 +44,10 @@ class WebContentsEflDelegateEwk : public content::WebContentsEflDelegate { virtual void OrientationLock( device::mojom::ScreenOrientationLockType) override; virtual void OrientationUnlock() override; + void OpenDateTimeDialog( + ui::TextInputType dialog_type, + double dialog_value, + content::DateTimeChooserEfl* date_time_chooser) override; private: EWebView* web_view_; -- 2.7.4 From 98f11ec6b5abdba1b5fb22a59da3a9f1ccf7d6a8 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Thu, 19 Jan 2023 11:00:29 +0530 Subject: [PATCH 07/16] [M108 Migration][API] Migrate favicon related patches This change adds modification related to favicon. References: https://review.tizen.org/gerrit/273261/ Change-Id: I0e72acea7c54565aef4eeb76194e73e8320b3d94 Signed-off-by: Ayush Kumar --- tizen_src/ewk/efl_integration/BUILD.gn | 2 + .../browser/favicon/favicon_commands.cc | 70 +++++++++++++++------- .../browser/favicon/favicon_commands.h | 30 +--------- .../browser/favicon/favicon_database.cc | 23 ++++--- .../browser/favicon/favicon_database_p.cc | 30 +++++----- .../browser/favicon/favicon_database_p.h | 8 ++- .../efl_integration/common/skia_bitmap_utils.cc | 23 +++++++ .../ewk/efl_integration/common/skia_bitmap_utils.h | 16 +++++ tizen_src/ewk/efl_integration/eweb_context.cc | 9 +-- .../private/ewk_notification_private.cc | 9 +-- .../ewk/efl_integration/public/ewk_context.cc | 4 +- .../efl_integration/web_contents_delegate_efl.cc | 49 +++++++-------- 12 files changed, 149 insertions(+), 124 deletions(-) create mode 100644 tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc create mode 100644 tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index 8965db0..c04d0c6 100755 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -353,6 +353,8 @@ shared_library("chromium-ewk") { "common/print_pages_params.cc", "common/print_pages_params.h", "common/render_messages_ewk.h", + "common/skia_bitmap_utils.cc", + "common/skia_bitmap_utils.h", "common/version_info.cc", "common/version_info.h", "common/version_info_efl.h", diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc index a636ca4..29cee94 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc @@ -3,9 +3,13 @@ // found in the LICENSE file. #include "browser/favicon/favicon_commands.h" -#include "browser/favicon/favicon_database_p.h" -#include "third_party/sqlite/sqlite3.h" + #include +#include + +#include "browser/favicon/favicon_database_p.h" +#include "common/skia_bitmap_utils.h" +#include "url/gurl.h" #define CHECK_RESULT(qry, var, res, st, ret) if (var != res) {\ sqlite3_finalize(st);\ @@ -28,21 +32,31 @@ return ret;\ } +namespace { -std::string Command::lastError() const { - return std::string("[") + m_name + "] :: " + m_lastError; -} +struct SerializedBitmap { + SerializedBitmap() : data(0), size(0) {} + ~SerializedBitmap() { free(); } -std::string Command::name() const { - return m_name; -} + void alloc(size_t n) { + data = ::operator new(n); + size = n; + } -void Command::setError(const std::string &err) { - m_lastError = err; -} + void free() { + if (data) { + ::operator delete(data); + data = nullptr; + size = 0; + } + } -scoped_refptr Command::serialize(const SkBitmap &bitmap) { - scoped_refptr res(new SerializedBitmap); + void* data; + size_t size; +}; + +std::unique_ptr serialize(const SkBitmap& bitmap) { + std::unique_ptr res(new SerializedBitmap); if (bitmap.isNull()) { return res; } @@ -51,15 +65,14 @@ scoped_refptr Command::serialize(const SkBitmap &bitmap) { static_cast(res->data)[1] = static_cast(bitmap.alphaType()); static_cast(res->data)[2] = bitmap.width(); static_cast(res->data)[3] = bitmap.height(); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - if (!bitmap.copyPixelsTo(static_cast(res->data) + 4, bitmap.getSize())) { + if (!skia_bitmap_utils::CopyPixels(static_cast(res->data) + 4, + bitmap.getPixels(), bitmap.info())) { res->free(); } -#endif return res; } -SkBitmap Command::deserialize(const void *data) { +SkBitmap deserialize(const void* data) { if (!data) { return SkBitmap(); } @@ -77,12 +90,25 @@ SkBitmap Command::deserialize(const void *data) { // the deserialized SkBitmap owns and holds it's internal image data // for it's whole lifetime, we create a deep copy of the |bitmap|. SkBitmap copy; -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - bitmap.copyTo(©, colorType); -#endif + if (copy.tryAllocPixels(bitmap.info())) + bitmap.readPixels(copy.info(), copy.getPixels(), copy.rowBytes(), 0, 0); return copy; } +} // namespace + +std::string Command::lastError() const { + return std::string("[") + m_name + "] :: " + m_lastError; +} + +std::string Command::name() const { + return m_name; +} + +void Command::setError(const std::string& err) { + m_lastError = err; +} + const char *Command::sqlite3ErrStr(int rc) { static const char* const aMsg[] = { /* SQLITE_OK */ "not an error", @@ -322,7 +348,7 @@ bool InsertBitmapCommand::sqlExecute() { result = sqlite3_bind_text(stmt, 1, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC); CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false); - scoped_refptr serializedBitmap = serialize(m_bitmap); + std::unique_ptr serializedBitmap = serialize(m_bitmap); if (!serializedBitmap->data) { sqlite3_finalize(stmt); sqlite3_free(query); @@ -363,7 +389,7 @@ bool UpdateBitmapCommand::sqlExecute() { int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0); CHECK_PREP_MSG(query, result, SQLITE_OK, false); - scoped_refptr serializedBitmap = serialize(m_bitmap); + std::unique_ptr serializedBitmap = serialize(m_bitmap); if (!serializedBitmap->data) { sqlite3_finalize(stmt); return false; diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h index b6c5bfd..509c859 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h @@ -5,36 +5,12 @@ #ifndef FAVICON_COMMANDS_H #define FAVICON_COMMANDS_H -#include "url/gurl.h" -#include "base/memory/ref_counted.h" +#include #include "third_party/skia/include/core/SkBitmap.h" +class GURL; class FaviconDatabasePrivate; -struct SerializedBitmap : public base::RefCounted { - SerializedBitmap() : data(0), size(0) {} - ~SerializedBitmap() { - free(); - } - - void alloc(size_t n) { - free(); - data = ::operator new(n); - size = n; - } - - void free() { - if (data) { - ::operator delete(data); - data = 0; - size = 0; - } - } - - void *data; - size_t size; -}; - class Command { public: Command(const std::string &cmdName, FaviconDatabasePrivate *db) @@ -47,8 +23,6 @@ class Command { std::string name() const; protected: - static scoped_refptr serialize(const SkBitmap &bitmap); - static SkBitmap deserialize(const void *data); static const char *sqlite3ErrStr(int rc); FaviconDatabasePrivate *db() const { diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc index 3e52dbf..e35d7c8 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc @@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/task/bind_post_task.h" #include "base/task/thread_pool.h" -#include "content/public/browser/browser_task_traits.h" #include "favicon_commands.h" #include "favicon_database_p.h" @@ -201,6 +200,14 @@ bool FaviconDatabase::Open() { } g_sqlite3_initialized = true; } + + if (d->path.empty()) + return false; + + base::FilePath dir = d->path.DirName(); + if (!base::DirectoryExists(dir) && !base::CreateDirectory(dir)) + return false; + result_code = sqlite3_open(d->path.value().c_str(), &d->sqlite); if (result_code != SQLITE_OK) { LOG(ERROR) << "[FaviconDatabase] :: Error opening SQLite database (" @@ -225,17 +232,9 @@ void FaviconDatabase::Close() { } void FaviconDatabase::SyncSQLite() { -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - scoped_refptr ptr = - content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::DB); -#else - scoped_refptr ptr = - base::ThreadPool::CreateSingleThreadTaskRunner( - {content::BrowserThread::UI}); -#endif - ptr->PostTask(FROM_HERE, base::BindOnce(&FaviconDatabasePrivate::performSync, - d->weakPtrFactory.GetWeakPtr())); + d->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&FaviconDatabasePrivate::performSync, + d->weakPtrFactory.GetWeakPtr())); } void FaviconDatabase::ScheduleSync() { diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc index 55d72c5..3c7faf1 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc @@ -3,10 +3,14 @@ // found in the LICENSE file. #include "favicon_database_p.h" + #include + +#include "base/logging.h" +#include "base/path_service.h" #include "base/task/bind_post_task.h" #include "base/task/thread_pool.h" -#include "content/public/browser/browser_task_traits.h" +#include "content/common/paths_efl.h" #include "favicon_commands.h" const char * const FaviconDatabasePrivate::pageUrlToFaviconUrlTable = "url_to_favicon_url"; @@ -18,11 +22,17 @@ const char * const FaviconDatabasePrivate::defaultDirSuffix = ".config/chromium- const char * const FaviconDatabasePrivate::defaultFilename = "WebpageIcons.db"; FaviconDatabasePrivate::FaviconDatabasePrivate() - : path(ewk_home_directory_get()), + : task_runner_(base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), privateBrowsing(false), sqlite(0), weakPtrFactory(this) { - path.Append(defaultDirSuffix).Append(defaultFilename); + base::FilePath db_path; + if (base::PathService::Get(PathsEfl::WEB_DATABASE_DIR, &db_path)) + path = db_path.Append(FILE_PATH_LITERAL(defaultFilename)); + else + LOG(ERROR) << "[favicon] Could not get web database directory"; } GURL FaviconDatabasePrivate::faviconUrlForPageUrl(const GURL &pageUrl) const { @@ -47,24 +57,14 @@ bool FaviconDatabasePrivate::existsForFaviconURL(const GURL &faviconUrl) const { return it != faviconUrlToBitmap.end(); } -scoped_refptr FaviconDatabasePrivate::taskRunner() const { -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - return content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::DB); -#else - return base::ThreadPool::CreateSingleThreadTaskRunner( - {content::BrowserThread::UI}); -#endif -} - void FaviconDatabasePrivate::performSync() { - std::cerr << "[FaviconDatabasePrivate::performSync()]" << std::endl; base::AutoLock locker(mutex); timer.Stop(); while (!commands.empty()) { Command *cmd = commands.front(); if (!cmd->sqlExecute()) { - std::cerr << "[FaviconDatabasePrivate::performSync] :: " << "Error while executing command:\n\t" << cmd->lastError() << std::endl; + LOG(ERROR) << "[FaviconDatabasePrivate::performSync] :: " + << "Error while executing command: " << cmd->lastError(); // abort or what? } commands.pop(); diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h index a9dd774..01c2de4 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h @@ -10,7 +10,7 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" -#include "base/task/single_thread_task_runner.h" +#include "base/task/sequenced_task_runner.h" #include "base/timer/timer.h" #include "content/public/browser/browser_thread.h" #include "favicon_database.h" @@ -29,12 +29,16 @@ struct FaviconDatabasePrivate : public base::RefCountedThreadSafe taskRunner() const; + scoped_refptr task_runner() const { + return task_runner_; + } + void performSync(); std::map pageToFaviconUrl; std::map faviconUrlToBitmap; base::FilePath path; + scoped_refptr task_runner_; bool privateBrowsing; sqlite3 *sqlite; diff --git a/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc new file mode 100644 index 0000000..11b33bf --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc @@ -0,0 +1,23 @@ +// Copyright 2018 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 "skia_bitmap_utils.h" + +namespace skia_bitmap_utils { + +bool CopyPixels(void* dst_addr, const void* src_addr, const SkImageInfo& info) { + if (!dst_addr || !src_addr) + return false; + + size_t row_bytes = info.bytesPerPixel() * info.width(); + for (int y = 0; y < info.height(); ++y) { + memcpy(dst_addr, src_addr, row_bytes); + src_addr = static_cast(src_addr) + row_bytes; + dst_addr = static_cast(dst_addr) + row_bytes; + } + + return true; +} + +} // namespace skia_bitmap_utils diff --git a/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h new file mode 100644 index 0000000..08bd3fb --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h @@ -0,0 +1,16 @@ +// Copyright 2018 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 TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_SKIA_BITMAP_UTILS_H +#define TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_SKIA_BITMAP_UTILS_H + +#include "third_party/skia/include/core/SkBitmap.h" + +namespace skia_bitmap_utils { + +bool CopyPixels(void* dst_addr, const void* src_addr, const SkImageInfo& info); + +} // namespace skia_bitmap_utils + +#endif // TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_SKIA_BITMAP_UTILS_H diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index fca6eeb..8951e30 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -717,14 +717,7 @@ Evas_Object* EWebContext::AddFaviconObject(const char* uri, evas_object_image_fill_set(favicon, 0, 0, bitmap.width(), bitmap.height()); evas_object_image_filled_set(favicon, EINA_TRUE); evas_object_image_alpha_set(favicon, EINA_TRUE); - -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - void* pixels = evas_object_image_data_get(favicon, EINA_TRUE); - if (pixels) { - bitmap.copyPixelsTo(pixels, bitmap.getSize()); - evas_object_image_data_set(favicon, pixels); - } -#endif + evas_object_image_data_copy_set(favicon, bitmap.getPixels()); return favicon; } 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 1378ac6..cf3aec0 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc @@ -46,14 +46,7 @@ Evas_Object* Ewk_Notification::GetIcon(Evas* evas) const { evas_object_image_size_set(icon, icon_.width(), icon_.height()); evas_object_image_colorspace_set(icon, EVAS_COLORSPACE_ARGB8888); evas_object_image_alpha_set(icon, EINA_TRUE); - void* pixels = evas_object_image_data_get(icon, EINA_TRUE); - -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - if (pixels) { - icon_.copyPixelsTo(pixels, icon_.getSize()); - evas_object_image_data_set(icon, pixels); - } -#endif + evas_object_image_data_copy_set(icon, icon_.getPixels()); return icon; } diff --git a/tizen_src/ewk/efl_integration/public/ewk_context.cc b/tizen_src/ewk/efl_integration/public/ewk_context.cc index 8fa3ea0..3e3d06f 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_context.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_context.cc @@ -627,8 +627,8 @@ Eina_Bool ewk_context_favicon_database_directory_set(Ewk_Context* ewkContext, co EINA_SAFETY_ON_NULL_RETURN_VAL(ewkContext, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(directoryPath, EINA_FALSE); base::FilePath path(directoryPath); - path.Append(FaviconDatabasePrivate::defaultFilename); - return ewkContext->SetFaviconDatabasePath(path) ? EINA_TRUE : EINA_FALSE; + path = path.Append(FaviconDatabasePrivate::defaultFilename); + return ewkContext->SetFaviconDatabasePath(path); } void ewk_context_preferred_languages_set(Eina_List* languages) 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 097edfe..2d6149d 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -401,31 +401,6 @@ void WebContentsDelegateEfl::DidFinishLoad(RenderFrameHost* render_frame_host, return; web_view_->SmartCallback().call(); - NavigationEntry* entry = web_contents().GetController().GetVisibleEntry(); - if (!entry) - return; - - FaviconStatus& favicon = entry->GetFavicon(); - - if (favicon.valid) { - // check/update the url and favicon url in favicon database - FaviconDatabase::Instance()->SetFaviconURLForPageURL(favicon.url, - validated_url); - - // download favicon if there is no such in database - if (!FaviconDatabase::Instance()->ExistsForFaviconURL(favicon.url)) { - LOG(ERROR) << "[DidFinishLoad] :: no favicon in database for URL: " - << favicon.url.spec(); - favicon_downloader_.reset(new FaviconDownloader( - &web_contents_, favicon.url, - base::BindOnce(&WebContentsDelegateEfl::DidDownloadFavicon, - weak_ptr_factory_.GetWeakPtr()))); - favicon_downloader_->Start(); - } else { - web_view_->SmartCallback().call(); - } - } - web_contents_.Focus(); } @@ -444,13 +419,33 @@ void WebContentsDelegateEfl::DidUpdateFaviconURL( const std::vector& candidates) { // select and set proper favicon for (const auto& favicon : candidates) { - if (favicon->icon_type == blink::mojom::FaviconIconType::kFavicon && - !favicon->icon_url.is_valid()) { + if (!favicon->icon_url.is_valid()) + continue; + + if (favicon->icon_type == blink::mojom::FaviconIconType::kFavicon) { NavigationEntry* entry = web_contents_.GetController().GetVisibleEntry(); if (!entry) return; entry->GetFavicon().url = favicon->icon_url; entry->GetFavicon().valid = true; + + // check/update the url and favicon url in favicon database + FaviconDatabase::Instance()->SetFaviconURLForPageURL(favicon->icon_url, + entry->GetURL()); + + // download favicon if there is no such in database + if (!FaviconDatabase::Instance()->ExistsForFaviconURL( + favicon->icon_url)) { + LOG(INFO) << "No favicon in database for URL: " + << favicon->icon_url.spec(); + favicon_downloader_.reset(new FaviconDownloader( + &web_contents_, favicon->icon_url, + base::BindOnce(&WebContentsDelegateEfl::DidDownloadFavicon, + weak_ptr_factory_.GetWeakPtr()))); + favicon_downloader_->Start(); + } else { + web_view_->SmartCallback().call(); + } return; } } -- 2.7.4 From 3e70c4ff2e01bf9f0112e83c79fdbdfdd9a9bd50 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Mon, 23 Jan 2023 11:09:52 +0530 Subject: [PATCH 08/16] [M108 Migration] Enable proper functionality for ewk_view_text_selection_clear API This patch enables proper functionality of ewk_view_text_selection_clear api. Reference: https://review.tizen.org/gerrit/c/274274/ Change-Id: Idbcdc8e50fbde018aefb3ca576597508a3978a97 Signed-off-by: Ayush Kumar --- .../browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc | 8 ++++++++ .../browser/renderer_host/rwhv_aura_offscreen_helper_efl.h | 5 +++++ tizen_src/ewk/efl_integration/eweb_view.cc | 11 ++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc index 30492b0..edf0ed4 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc @@ -602,6 +602,14 @@ void RWHVAuraOffscreenHelperEfl::SelectionChanged(const std::u16string& text, const gfx::Range& range) { if (range.start() == range.end() && GetIMContextEfl()) GetIMContextEfl()->SetCaretPosition(range.start()); + + if (!GetSelectionController()) + return; + + std::u16string selectedText; + if (!text.empty() && !range.is_empty()) + selectedText = rwhv_aura_->GetSelectedText(); + GetSelectionController()->UpdateSelectionData(selectedText); } void RWHVAuraOffscreenHelperEfl::EvasToBlinkCords(int x, diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h index a4264d1..1f24974 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h @@ -19,6 +19,7 @@ #include "base/callback.h" #include "base/containers/id_map.h" #include "base/timer/timer.h" +#include "content/browser/selection/selection_controller_efl.h" #include "content/common/cursors/webcursor.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "ui/base/ime/mojom/text_input_state.mojom-forward.h" @@ -103,6 +104,9 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { void SelectionChanged(const std::u16string& text, size_t offset, const gfx::Range& range); + SelectionControllerEfl* GetSelectionController() const { + return selection_controller_.get(); + } void EvasToBlinkCords(int x, int y, int* view_x, int* view_y); Evas_Object* ewk_view() const; @@ -180,6 +184,7 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { ui::IMContextEfl* im_context_efl_ = nullptr; RenderWidgetHostViewAura* rwhv_aura_ = nullptr; WebContents* web_contents_ = nullptr; + std::unique_ptr selection_controller_; std::unique_ptr rwh_helper_; diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index fcad346..015f775 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -1366,14 +1366,10 @@ void EWebView::OnQuerySelectionStyleReply(const SelectionStylePrams& params) { } SelectionControllerEfl* EWebView::GetSelectionController() const { -#if !defined(USE_AURA) RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); - RenderWidgetHostViewEfl* view = static_cast( + RenderWidgetHostViewAura* view = static_cast( render_view_host->GetWidget()->GetView()); - return view ? view->GetSelectionController() : 0; -#else - return nullptr; -#endif + return view ? view->offscreen_helper()->GetSelectionController() : 0; } void EWebView::SelectLinkText(const gfx::Point& touch_point) { @@ -1407,7 +1403,8 @@ Eina_Bool EWebView::ClearSelection() { return EINA_FALSE; ResetContextMenuController(); - rwhva()->SelectionChanged(std::u16string(), 0, gfx::Range()); + rwhva()->offscreen_helper()->SelectionChanged(std::u16string(), 0, + gfx::Range()); if (GetSelectionController()) return GetSelectionController()->ClearSelectionViaEWebView(); -- 2.7.4 From 831fe49d8a7ee0a975936d22ac73f3550c454e65 Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Sun, 22 Jan 2023 23:24:02 +0530 Subject: [PATCH 09/16] [M108 Migration] Implement ewk_settings_use_system_font_set API Added needed to support to control the font setting for browser. Reference: https://review.tizen.org/gerrit/c/277844 Change-Id: I051d586183dadfa928f97415dfb246e4b32b361a Signed-off-by: Bakka Uday Kiran --- third_party/blink/renderer/platform/fonts/font_cache.h | 9 +++++++++ .../blink/renderer/platform/fonts/skia/font_cache_skia.cc | 11 +++++++++++ tizen_src/ewk/efl_integration/eweb_view.cc | 12 +++++++++--- tizen_src/ewk/efl_integration/public/ewk_settings.cc | 13 +++++++++++-- 4 files changed, 40 insertions(+), 5 deletions(-) mode change 100644 => 100755 third_party/blink/renderer/platform/fonts/font_cache.h diff --git a/third_party/blink/renderer/platform/fonts/font_cache.h b/third_party/blink/renderer/platform/fonts/font_cache.h old mode 100644 new mode 100755 index af9f3af..1d64d43 --- a/third_party/blink/renderer/platform/fonts/font_cache.h +++ b/third_party/blink/renderer/platform/fonts/font_cache.h @@ -290,6 +290,11 @@ class PLATFORM_EXPORT FontCache final { FontCache& operator=(const FontCache&) = delete; ~FontCache(); +#if BUILDFLAG(IS_EFL) + void SetFontFamilyTizenBrowser() { tizen_browser_font_family = true; } + bool IsFontFamilyTizenBrowser() const { return tizen_browser_font_family; } +#endif + private: // BCP47 list used when requesting fallback font for a character. // inlineCapacity is set to 4: the array vector not need to hold more than 4 @@ -404,6 +409,10 @@ class PLATFORM_EXPORT FontCache final { void PurgePlatformFontDataCache(); void PurgeFallbackListShaperCache(); +#if BUILDFLAG(IS_EFL) + bool tizen_browser_font_family = false; +#endif + friend class SimpleFontData; // For fontDataFromFontPlatformData friend class FontFallbackList; friend class FontPlatformDataCache; diff --git a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc index 9a458ca..3bcff7b 100644 --- a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc +++ b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc @@ -53,6 +53,9 @@ #include "third_party/skia/include/core/SkFontMgr.h" #include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/core/SkTypeface.h" +#if BUILDFLAG(IS_TIZEN) +#include "tizen_src/chromium_impl/tizen/system_info.h" +#endif namespace blink { @@ -226,6 +229,14 @@ sk_sp FontCache::CreateTypeface( } #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_TIZEN) + if (IsMobileProfile() && Get().IsFontFamilyTizenBrowser()) + name = "SamsungOneUI"; + else if (!name.length() || (DeprecatedEqualIgnoringCase( + String(name.data()), "standardFontFamily"))) + name = "Tizen"; +#endif + #if BUILDFLAG(IS_WIN) // TODO(vmpstr): Deal with paint typeface here. if (sideloaded_fonts_) { diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 015f775..a9f9686 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -2057,9 +2057,15 @@ bool EWebView::RestoreFromSessionData(const char* data, unsigned length) { void EWebView::SetBrowserFont() { #if !defined(EWK_BRINGUP) // FIXME: m94 bringup RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); - if (render_view_host) - render_view_host->Send( - new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID())); + if (render_view_host) { + IPC::Message* message = + new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID()); + + if (render_view_host->IsRenderViewLive()) + render_view_host->Send(message); + else + delayed_messages_.push_back(message); + } #endif } diff --git a/tizen_src/ewk/efl_integration/public/ewk_settings.cc b/tizen_src/ewk/efl_integration/public/ewk_settings.cc index 8ce40cd..1a8b3e8 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_settings.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_settings.cc @@ -865,8 +865,17 @@ Eina_Bool ewk_settings_legacy_font_size_enabled_get(Ewk_Settings* settings) Eina_Bool ewk_settings_use_system_font_set(Ewk_Settings* settings, Eina_Bool use) { - LOG_EWK_API_MOCKUP(); - return false; + if (IsMobileProfile()) { + EWebView* impl = EWebView::FromEvasObject(settings->getEvasObject()); + if (impl) { + if (use) + impl->UseSettingsFont(); + else + impl->SetBrowserFont(); + return EINA_TRUE; + } + } + return EINA_FALSE; } Eina_Bool ewk_settings_use_system_font_get(Ewk_Settings* settings) -- 2.7.4 From 9fd673f36281ac23d6a0122c19ce7ad37606f82f Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Tue, 17 Jan 2023 13:53:20 +0530 Subject: [PATCH 10/16] [M108 Migration] Patch migration for BrowsingDataRemoverEfl This patch -Migrates Session storage related changes from M94. -Fixes build error caused by accessing StoragePartition -Migrates the below patch for BrowsingDataRemoverEfl. -Removes EWK_BRINGUP caused by M94 upversion by changing to use QuotaManager instead of AppCacheService References: https://review.tizen.org/gerrit/c/273503 https://review.tizen.org/gerrit/c/283349 Change-Id: Ibaa832abd99f41f2bbb1f6ec98fe26dab4ba3fc7 Signed-off-by: Bakka Uday Kiran --- .../browser/browsing_data_remover_efl.cc | 340 ++++++--------------- .../browser/browsing_data_remover_efl.h | 116 ++++--- tizen_src/ewk/efl_integration/eweb_context.cc | 9 +- 3 files changed, 146 insertions(+), 319 deletions(-) diff --git a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc index 5f14fec..17b2a62 100644 --- a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc @@ -18,39 +18,39 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/session_storage_usage_info.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_usage_info.h" -#include "net/base/completion_repeating_callback.h" -#include "net/base/net_errors.h" -#include "net/disk_cache/disk_cache.h" -#include "net/http/http_cache.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" #include "storage/browser/quota/quota_manager.h" using content::BrowserThread; -// Static. -BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForUnboundedRange(content::BrowserContext* profile) { - return new BrowsingDataRemoverEfl(profile, base::Time(), base::Time::Max()); +// static +BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForUnboundedRange( + content::BrowserContext* browser_context) { + return new BrowsingDataRemoverEfl(browser_context, base::Time(), + base::Time::Max()); } -BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForRange(content::BrowserContext* browser_context, - base::Time start, base::Time end) { +// static +BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForRange( + content::BrowserContext* browser_context, + base::Time start, + base::Time end) { return new BrowsingDataRemoverEfl(browser_context, start, end); } -int BrowsingDataRemoverEfl::GenerateQuotaClientMask(int remove_mask) { - int quota_client_mask = 0; -#if !defined(EWK_BRINGUP) // FIXME: m85 bringup +// static +storage::QuotaClientTypes BrowsingDataRemoverEfl::GenerateQuotaClientTypes( + int remove_mask) { + storage::QuotaClientTypes quota_client_types; if (remove_mask & BrowsingDataRemoverEfl::REMOVE_FILE_SYSTEMS) - quota_client_mask |= storage::QuotaClient::kFileSystem; + quota_client_types.insert(storage::QuotaClientType::kFileSystem); if (remove_mask & BrowsingDataRemoverEfl::REMOVE_WEBSQL) - quota_client_mask |= storage::QuotaClient::kDatabase; + quota_client_types.insert(storage::QuotaClientType::kDatabase); if (remove_mask & BrowsingDataRemoverEfl::REMOVE_INDEXEDDB) - quota_client_mask |= storage::QuotaClient::kIndexedDatabase; -#endif - return quota_client_mask; + quota_client_types.insert(storage::QuotaClientType::kIndexedDatabase); + return quota_client_types; } BrowsingDataRemoverEfl::BrowsingDataRemoverEfl( @@ -58,144 +58,22 @@ BrowsingDataRemoverEfl::BrowsingDataRemoverEfl( base::Time delete_begin, base::Time delete_end) : browser_context_(browser_context), - app_cache_service_(nullptr), - quota_manager_(nullptr), - dom_storage_context_(nullptr), delete_begin_(delete_begin), - delete_end_(delete_end), - next_cache_state_(STATE_NONE), - cache_(nullptr), - main_context_getter_(nullptr), - media_context_getter_(nullptr), - waiting_for_clear_cache_(false), - waiting_for_clear_local_storage_(false), - waiting_for_clear_quota_managed_data_(false), - quota_managed_origins_to_delete_count_(0), - quota_managed_storage_types_to_delete_count_(0), - remove_mask_(0) { -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - if (browser_context_) { - app_cache_service_ = browser_context->GetStoragePartition(browser_context_, NULL)->GetAppCacheService(); - main_context_getter_ = - content::BrowserContext::GetDefaultStoragePartition(browser_context_)->GetURLRequestContext(); - media_context_getter_ = browser_context->CreateMediaRequestContext(); - } -#endif -} + delete_end_(delete_end) {} BrowsingDataRemoverEfl::~BrowsingDataRemoverEfl() { DCHECK(AllDone()); } void BrowsingDataRemoverEfl::ClearNetworkCache() { - waiting_for_clear_cache_ = true; DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&BrowsingDataRemoverEfl::ClearNetworkCacheOnIOThread, - base::Unretained(this))); -} - -void BrowsingDataRemoverEfl::ClearNetworkCacheOnIOThread() { - // This function should be called on the IO thread. - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - DCHECK_EQ(STATE_NONE, next_cache_state_); - DCHECK(main_context_getter_.get()); - DCHECK(media_context_getter_.get()); - - next_cache_state_ = STATE_CREATE_MAIN; - DoClearCache(net::OK); -} - -// The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN --> -// STATE_DELETE_MAIN --> STATE_CREATE_MEDIA --> STATE_DELETE_MEDIA --> -// STATE_DONE, and any errors are ignored. -void BrowsingDataRemoverEfl::DoClearCache(int rv) { - DCHECK_NE(STATE_NONE, next_cache_state_); - - while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) { - switch (next_cache_state_) { - case STATE_CREATE_MAIN: - case STATE_CREATE_MEDIA: { - // Get a pointer to the cache. - net::URLRequestContextGetter* getter = nullptr; - if (next_cache_state_ == STATE_CREATE_MAIN) { - if (main_context_getter_) - getter = main_context_getter_.get(); - } else { - if (media_context_getter_) - getter = media_context_getter_.get(); - } - if (getter && getter->GetURLRequestContext()) { - net::HttpTransactionFactory* factory = - getter->GetURLRequestContext()->http_transaction_factory(); - if (factory) { - next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) - ? STATE_DELETE_MAIN - : STATE_DELETE_MEDIA; - rv = factory->GetCache()->GetBackend( - &cache_, base::BindOnce(&BrowsingDataRemoverEfl::DoClearCache, - base::Unretained(this))); - } else { - LOG(ERROR) << "Could not get HttpTransactionFactory."; - next_cache_state_ = STATE_NONE; - } - } else { - LOG(ERROR) << "Could not get URLRequestContext."; - next_cache_state_ = STATE_NONE; - } - break; - } - case STATE_DELETE_MAIN: - case STATE_DELETE_MEDIA: { - next_cache_state_ = (next_cache_state_ == STATE_DELETE_MAIN) ? - STATE_CREATE_MEDIA : STATE_DONE; - - // |cache_| can be null if it cannot be initialized. - if (cache_) { - if (delete_begin_.is_null()) { - rv = cache_->DoomAllEntries(base::BindOnce( - &BrowsingDataRemoverEfl::DoClearCache, base::Unretained(this))); - } else { - rv = cache_->DoomEntriesBetween( - delete_begin_, delete_end_, - base::BindOnce(&BrowsingDataRemoverEfl::DoClearCache, - base::Unretained(this))); - } - cache_ = NULL; - } - break; - } - case STATE_DONE: { - cache_ = NULL; - next_cache_state_ = STATE_NONE; - - // Notify the UI thread that we are done. - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&BrowsingDataRemoverEfl::ClearedCache, - base::Unretained(this))); - return; - } - default: { - NOTREACHED() << "bad state"; - next_cache_state_ = STATE_NONE; // Stop looping. - return; - } - } - } -} - -void BrowsingDataRemoverEfl::ClearedCache() { - waiting_for_clear_cache_ = false; DeleteIfDone(); } // just to keep same overall structure of Chrome::BrowsingDataRemover bool BrowsingDataRemoverEfl::AllDone() { - return !waiting_for_clear_cache_ && - !waiting_for_clear_local_storage_ && + return !waiting_for_clear_local_storage_ && + !waiting_for_clear_session_storage_ && !waiting_for_clear_quota_managed_data_; } @@ -207,90 +85,42 @@ void BrowsingDataRemoverEfl::DeleteIfDone() { base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); } -typedef void (*Application_Cache_Origins_Get_Callback)(void* origins, void* user_data); -#if !defined(EWK_BRINGUP) // FIXME: m108 bringup -void OnGotOriginsWithApplicationCache(Application_Cache_Origins_Get_Callback callback, - void* user_data, - scoped_refptr collection, - int result){ - BrowsingDataRemoverEfl* bdre = - static_cast(user_data); - // information about end of process is not needed so cb left empty - net::CompletionRepeatingCallback cb; - if (collection.get()) { - for (const auto& origin : collection->infos_by_origin) - bdre->DeleteAppCachesForOrigin(origin.first); - } -} -#endif void BrowsingDataRemoverEfl::RemoveImpl(int remove_mask, const GURL& origin) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); remove_mask_ = remove_mask; - remove_origin_ = origin; + remove_origin_ = url::Origin::Create(origin); if (remove_mask & REMOVE_LOCAL_STORAGE) { waiting_for_clear_local_storage_ = true; -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup if (!dom_storage_context_) { - dom_storage_context_ = content::BrowserContext::GetStoragePartition(browser_context_, NULL)->GetDOMStorageContext(); + dom_storage_context_ = + browser_context_->GetStoragePartition(NULL)->GetDOMStorageContext(); } -#endif ClearLocalStorageOnUIThread(); } + if (remove_mask & REMOVE_SESSION_STORAGE) { + waiting_for_clear_session_storage_ = true; + if (!dom_storage_context_) { + dom_storage_context_ = + browser_context_->GetStoragePartition(NULL)->GetDOMStorageContext(); + } + ClearSessionStorageOnUIThread(); + } + if (remove_mask & REMOVE_INDEXEDDB || remove_mask & REMOVE_WEBSQL || - remove_mask & REMOVE_FILE_SYSTEMS) { -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup + remove_mask & REMOVE_FILE_SYSTEMS || remove_mask & REMOVE_APPCACHE) { if (!quota_manager_) { - quota_manager_ = content::BrowserContext::GetStoragePartition(browser_context_, NULL)->GetQuotaManager(); + quota_manager_ = + browser_context_->GetStoragePartition(NULL)->GetQuotaManager(); } -#endif waiting_for_clear_quota_managed_data_ = true; base::ThreadPool::PostTask( FROM_HERE, {BrowserThread::IO}, base::BindOnce(&BrowsingDataRemoverEfl::ClearQuotaManagedDataOnIOThread, base::Unretained(this))); } - if (remove_mask & REMOVE_APPCACHE) { - DCHECK(app_cache_service_); - if (!app_cache_service_) { - return; - } - - if (origin.is_valid()) { - DeleteAppCachesForOrigin(url::Origin::Create(origin)); - } - else { -#if !defined(EWK_BRINGUP) // FIXME: m108 bringup - //if origin is empty delete all app cache (actual deletion in OnGotOriginsWithApplicationCache) - Application_Cache_Origins_Get_Callback cb = NULL; - scoped_refptr collection(new content::AppCacheInfoCollection()); - app_cache_service_->GetAllAppCacheInfo( - collection.get(), base::BindOnce(&OnGotOriginsWithApplicationCache, - cb, this, collection)); -#endif - } - } -} - -void BrowsingDataRemoverEfl::DeleteAppCachesForOrigin( - const url::Origin& origin) { - if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { - // TODO: Using base::Unretained is not thread safe - // It may happen that on IO thread this ptr will be already deleted - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&BrowsingDataRemoverEfl::DeleteAppCachesForOrigin, - base::Unretained(this), origin)); - return; - } - - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); -#if !defined(EWK_BRINGUP) // FIXME: m108 bringup - net::CompletionRepeatingCallback rm_app_catche_cb; - static_cast(app_cache_service_)->DeleteAppCachesForOrigin(origin, rm_app_catche_cb); -#endif } void BrowsingDataRemoverEfl::ClearLocalStorageOnUIThread() { @@ -316,78 +146,92 @@ void BrowsingDataRemoverEfl::OnGotLocalStorageUsageInfo( DeleteIfDone(); } +void BrowsingDataRemoverEfl::ClearSessionStorageOnUIThread() { + DCHECK(waiting_for_clear_session_storage_); + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + dom_storage_context_->GetSessionStorageUsage( + base::BindOnce(&BrowsingDataRemoverEfl::OnGotSessionStorageUsageInfo, + base::Unretained(this))); +} + +void BrowsingDataRemoverEfl::OnGotSessionStorageUsageInfo( + const std::vector& infos) { + DCHECK(waiting_for_clear_session_storage_); + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + for (size_t i = 0; i < infos.size(); ++i) + dom_storage_context_->DeleteSessionStorage(infos[i], base::DoNothing()); + waiting_for_clear_session_storage_ = false; + DeleteIfDone(); +} + void BrowsingDataRemoverEfl::ClearQuotaManagedDataOnIOThread() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup // Ask the QuotaManager for all origins with temporary quota modified within // the user-specified timeframe, and deal with the resulting set in // OnGotQuotaManagedOrigins(). quota_managed_origins_to_delete_count_ = 0; quota_managed_storage_types_to_delete_count_ = 0; - if (delete_begin_ == base::Time()) { - ++quota_managed_storage_types_to_delete_count_; - quota_manager_->GetOriginsModifiedSince( - storage::kStorageTypePersistent, delete_begin_, - base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins, - base::Unretained(this))); - } + if (delete_begin_.is_null()) + ClearQuotaManagedDataInternal(blink::mojom::StorageType::kPersistent); // Do the same for temporary quota. - ++quota_managed_storage_types_to_delete_count_; - quota_manager_->GetOriginsModifiedSince( - storage::kStorageTypeTemporary, delete_begin_, - base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins, - base::Unretained(this))); + ClearQuotaManagedDataInternal(blink::mojom::StorageType::kTemporary); // Do the same for syncable quota. + ClearQuotaManagedDataInternal(blink::mojom::StorageType::kSyncable); +} + +void BrowsingDataRemoverEfl::ClearQuotaManagedDataInternal( + blink::mojom::StorageType type) { ++quota_managed_storage_types_to_delete_count_; - quota_manager_->GetOriginsModifiedSince( - storage::kStorageTypeSyncable, delete_begin_, - base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins, + quota_manager_->GetBucketsModifiedBetween( + type, delete_begin_, delete_end_, + base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedBuckets, base::Unretained(this))); -#endif } -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -void BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins( - const std::set& origins, storage::StorageType type) { +void BrowsingDataRemoverEfl::OnGotQuotaManagedBuckets( + const std::set& buckets, + blink::mojom::StorageType type) { DCHECK_GT(quota_managed_storage_types_to_delete_count_, 0); - // Walk through the origins passed in, delete quota of |type| from each that - // matches the |origin_set_mask_|. - std::set::const_iterator origin; - for (origin = origins.begin(); origin != origins.end(); ++origin) { - if (!remove_origin_.is_empty()) { // delete all origins if remove_origin is empty - if (remove_origin_ != origin->GetOrigin()) - continue; - } + storage::QuotaClientTypes quota_client_types = + BrowsingDataRemoverEfl::GenerateQuotaClientTypes(remove_mask_); + + for (const auto& bucket : buckets) { + // delete all origins if |remove_origin_| is opaque. + if (!remove_origin_.opaque() && + remove_origin_ != bucket.storage_key.origin()) + continue; ++quota_managed_origins_to_delete_count_; - quota_manager_->DeleteOriginData( - origin->GetOrigin(), type, - BrowsingDataRemoverEfl::GenerateQuotaClientMask(remove_mask_), - base::BindOnce(&BrowsingDataRemoverEfl::OnQuotaManagedOriginDeletion, - base::Unretained(this), origin->GetOrigin(), type)); + quota_manager_->DeleteBucketData( + bucket, quota_client_types, + base::BindOnce(&BrowsingDataRemoverEfl::OnQuotaManagedBucketDeleted, + base::Unretained(this), bucket)); } --quota_managed_storage_types_to_delete_count_; CheckQuotaManagedDataDeletionStatus(); } -void BrowsingDataRemoverEfl::OnQuotaManagedOriginDeletion( - const GURL& origin, - storage::StorageType type, - storage::QuotaStatusCode status) { +void BrowsingDataRemoverEfl::OnQuotaManagedBucketDeleted( // LCOV_EXCL_LINE + const storage::BucketLocator& bucket, + blink::mojom::QuotaStatusCode status) { DCHECK_GT(quota_managed_origins_to_delete_count_, 0); - if (status != storage::kQuotaStatusOk) - DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin " - << origin << ". Status: " << status; + if (status != blink::mojom::QuotaStatusCode::kOk) { + DLOG(ERROR) << "Couldn't remove data type " << static_cast(bucket.type) + << " with storage key " << bucket.storage_key.GetDebugString() + << " and bucket id " << bucket.id + << ". Status: " << static_cast(status); + } --quota_managed_origins_to_delete_count_; CheckQuotaManagedDataDeletionStatus(); } -#endif void BrowsingDataRemoverEfl::CheckQuotaManagedDataDeletionStatus() { if (quota_managed_storage_types_to_delete_count_ != 0 || diff --git a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h index c30d2be..6c8885a 100644 --- a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h +++ b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h @@ -10,81 +10,89 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "storage/browser/quota/quota_client_type.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" #include "url/origin.h" -namespace net { -class URLRequestContextGetter; -} namespace content { -class AppCacheService; class BrowserContext; class DOMStorageContext; +struct SessionStorageUsageInfo; struct StorageUsageInfo; -class StoragePartition; -} -namespace disk_cache { -class Backend; -} +} // namespace content + namespace storage { class QuotaManager; +struct BucketLocator; } class BrowsingDataRemoverEfl { public: // Mask used for Remove. enum RemoveDataMask { - REMOVE_LOCAL_STORAGE = 1 << 0, - REMOVE_INDEXEDDB = 1 << 1, - REMOVE_WEBSQL = 1 << 2, - REMOVE_FILE_SYSTEMS = 1 << 3, - REMOVE_APPCACHE = 1 << 4, + REMOVE_LOCAL_STORAGE = 1 << 0, + REMOVE_INDEXEDDB = 1 << 1, + REMOVE_WEBSQL = 1 << 2, + REMOVE_FILE_SYSTEMS = 1 << 3, + REMOVE_APPCACHE = 1 << 4, + REMOVE_SESSION_STORAGE = 1 << 5, }; - static BrowsingDataRemoverEfl* CreateForUnboundedRange(content::BrowserContext*); - static BrowsingDataRemoverEfl* CreateForRange(content::BrowserContext*, base::Time, base::Time); - void RemoveImpl(int, const GURL&); + static BrowsingDataRemoverEfl* CreateForUnboundedRange( + content::BrowserContext* browser_context); + static BrowsingDataRemoverEfl* CreateForRange( + content::BrowserContext* browser_context, + base::Time start, + base::Time end); + void RemoveImpl(int remove_mask, const GURL& origin); virtual ~BrowsingDataRemoverEfl(); void ClearNetworkCache(); - // deletes app cache for given origin - void DeleteAppCachesForOrigin(const url::Origin& origin); + BrowsingDataRemoverEfl(const BrowsingDataRemoverEfl&) = delete; + BrowsingDataRemoverEfl& operator=(const BrowsingDataRemoverEfl&) = delete; protected: - BrowsingDataRemoverEfl(content::BrowserContext*, base::Time start, base::Time end); + BrowsingDataRemoverEfl(content::BrowserContext* browser_context, + base::Time start, + base::Time end); - // Quota managed data uses a different bitmask for types than - // BrowsingDataRemover uses. This method generates that mask. - static int GenerateQuotaClientMask(int); + // Quota managed data uses a different representation for storage types than + // BrowsingDataRemover uses. This method generates that representation. + static storage::QuotaClientTypes GenerateQuotaClientTypes(int remove_mask); private: - void ClearNetworkCacheOnIOThread(); - - // Callback when the cache has been cleared. - void DoClearCache(int); - // Invoked on the UI thread to delete local storage. void ClearLocalStorageOnUIThread(); // Callback to deal with the list gathered in ClearLocalStorageOnUIThread. void OnGotLocalStorageUsageInfo( - const std::vector&); + const std::vector& infos); + + // Invoked on the UI thread to delete session storage. + void ClearSessionStorageOnUIThread(); + + // Callback to deal with the list gathered in ClearSessionStorageOnUIThread. + void OnGotSessionStorageUsageInfo( + const std::vector& infos); // Invoked on the IO thread to delete all storage types managed by the quota // system: AppCache, Databases, FileSystems. void ClearQuotaManagedDataOnIOThread(); - // Callback to respond to QuotaManager::GetOriginsModifiedSince, which is the - // core of 'ClearQuotaManagedDataOnIOThread'. -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - void OnGotQuotaManagedOrigins(const std::set&, storage::StorageType); + void ClearQuotaManagedDataInternal(blink::mojom::StorageType type); + // Callback to respond to QuotaManager::GetBucketsModifiedBetween, + // which is the core of 'ClearQuotaManagedDataOnIOThread'. + void OnGotQuotaManagedBuckets(const std::set& buckets, + blink::mojom::StorageType type); // Callback responding to deletion of a single quota managed origin's // persistent data - void OnQuotaManagedOriginDeletion(const GURL&, storage::StorageType, storage::QuotaStatusCode); -#endif + void OnQuotaManagedBucketDeleted(const storage::BucketLocator& bucket, + blink::mojom::QuotaStatusCode status); // Called to check whether all temporary and persistent origin data that // should be deleted has been deleted. If everything's good to go, invokes // OnQuotaManagedDataDeleted on the UI thread. @@ -94,19 +102,17 @@ class BrowsingDataRemoverEfl { // deleted. Updates the waiting flag and invokes NotifyAndDeleteIfDone. void OnQuotaManagedDataDeleted(); - void ClearedCache(); bool AllDone(); void DeleteIfDone(); content::BrowserContext* browser_context_; - content::AppCacheService* app_cache_service_; // The QuotaManager is owned by the profile; we can use a raw pointer here, // and rely on the profile to destroy the object whenever it's reasonable. - storage::QuotaManager* quota_manager_; + storage::QuotaManager* quota_manager_ = nullptr; // The DOMStorageContext is owned by the profile; we'll store a raw pointer. - content::DOMStorageContext* dom_storage_context_; + content::DOMStorageContext* dom_storage_context_ = nullptr; // Start time to delete from. base::Time delete_begin_; @@ -114,37 +120,19 @@ class BrowsingDataRemoverEfl { // End time to delete to. base::Time delete_end_; - enum CacheState { - STATE_NONE, - STATE_CREATE_MAIN, - STATE_CREATE_MEDIA, - STATE_DELETE_MAIN, - STATE_DELETE_MEDIA, - STATE_DONE - }; - CacheState next_cache_state_; - disk_cache::Backend* cache_; - - content::NotificationRegistrar registrar_; - std::set renderers_; - - // Used to delete data from HTTP cache. - scoped_refptr main_context_getter_; - scoped_refptr media_context_getter_; - - bool waiting_for_clear_cache_; - bool waiting_for_clear_local_storage_; - bool waiting_for_clear_quota_managed_data_; + bool waiting_for_clear_local_storage_ = false; + bool waiting_for_clear_session_storage_ = false; + bool waiting_for_clear_quota_managed_data_ = false; // Tracking how many origins need to be deleted, and whether we're finished // gathering origins. - int quota_managed_origins_to_delete_count_; - int quota_managed_storage_types_to_delete_count_; + int quota_managed_origins_to_delete_count_ = 0; + int quota_managed_storage_types_to_delete_count_ = 0; // The removal mask for the current removal operation. - int remove_mask_; + int remove_mask_ = 0; // The origin for the current removal operation. - GURL remove_origin_; + url::Origin remove_origin_; }; #endif diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index 8951e30..e74e8a3 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -519,16 +519,11 @@ Ewk_Cookie_Manager* EWebContext::ewkCookieManager() { } void EWebContext::DeleteAllApplicationCache() { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&EWebContext::DeleteAllApplicationCache, - base::Unretained(this))); - return; - } + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get()); remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_APPCACHE, GURL()); + remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_SESSION_STORAGE, GURL()); } void EWebContext::DeleteApplicationCacheForSite(const GURL& site) { -- 2.7.4 From ec2996083e51a9e3874fe71eaae59e2b2a7ab4c3 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Mon, 23 Jan 2023 15:46:57 +0530 Subject: [PATCH 11/16] [M108 Migration] Enable ScreenOrientationDelegate for EFL ScreenOrientationDelegate is needed for fixing tct-screenorientation-w3c-tests failures on M108. Reference: https://review.tizen.org/gerrit/c/274262/ Change-Id: I08d37b9c5c40a551971a79df6b0938300d38d25e Signed-off-by: Ayush Kumar --- content/browser/browser_main_loop.cc | 14 ++++++++++++++ content/browser/browser_main_loop.h | 6 +++--- content/public/common/content_switches.cc | 5 +++++ content/public/common/content_switches.h | 4 ++++ .../screen_orientation/screen_orientation_delegate_efl.cc | 8 +++----- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 28a7e2b..eedf4ba 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -242,6 +242,10 @@ #include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h" #endif +#if BUILDFLAG(IS_EFL) +#include "content/browser/screen_orientation/screen_orientation_delegate_efl.h" +#endif + // One of the linux specific headers defines this as a macro. #ifdef DestroyAll #undef DestroyAll @@ -713,6 +717,16 @@ void BrowserMainLoop::PostCreateMainMessageLoop() { base::trace_event::CPUFreqMonitor::GetInstance()); #endif +#if BUILDFLAG(IS_EFL) + if (!parsed_command_line_.HasSwitch( + switches::kDisableScreenOrientationLock)) { + TRACE_EVENT0("startup", + "BrowserMainLoop::Subsystem:ScreenOrientationProvider"); + screen_orientation_delegate_ = + std::make_unique(); + } +#endif + if (UsingInProcessGpu()) { // Make sure to limits for skia font cache are applied for in process // gpu setup (crbug.com/1183230). diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index b2660cd..5e2ef10 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h @@ -102,7 +102,7 @@ namespace responsiveness { class Watcher; } // namespace responsiveness -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_EFL) class ScreenOrientationDelegate; #endif @@ -326,8 +326,8 @@ class CONTENT_EXPORT BrowserMainLoop { std::unique_ptr screenlock_monitor_; // Per-process listener for online state changes. std::unique_ptr online_state_observer_; -#if BUILDFLAG(IS_ANDROID) - // Android implementation of ScreenOrientationDelegate +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_EFL) + // Android/EFL implementation of ScreenOrientationDelegate std::unique_ptr screen_orientation_delegate_; #endif diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index f42b7c2..310961b 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -985,6 +985,11 @@ const char kRendererWaitForJavaDebugger[] = "renderer-wait-for-java-debugger"; const char kDisableOoprDebugCrashDump[] = "disable-oopr-debug-crash-dump"; #endif +#if BUILDFLAG(IS_EFL) +// Disable the locking feature of the screen orientation API. +const char kDisableScreenOrientationLock[] = "disable-screen-orientation-lock"; +#endif + // Enable the aggressive flushing of DOM Storage to minimize data loss. const char kEnableAggressiveDOMStorageFlushing[] = "enable-aggressive-domstorage-flushing"; diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 6f44b6a..e3e3ddf 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -267,6 +267,10 @@ CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[]; CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[]; #endif +#if BUILDFLAG(IS_EFL) +CONTENT_EXPORT extern const char kDisableScreenOrientationLock[]; +#endif + // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) diff --git a/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc b/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc index 4fcddbf..a1dabf7 100644 --- a/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc +++ b/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc @@ -5,18 +5,16 @@ #include "content/browser/screen_orientation/screen_orientation_delegate_efl.h" -#include "chromium_impl/content/browser/web_contents/web_contents_impl_efl.h" +#include "content/browser/web_contents/web_contents_impl_efl.h" +#include "content/browser/screen_orientation/screen_orientation_provider.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "ewk/efl_integration/web_contents_efl_delegate_ewk.h" namespace content { -ScreenOrientationDelegate* CreateScreenOrientationDelegateEfl() { - return new ScreenOrientationDelegateEfl(); -} - ScreenOrientationDelegateEfl::ScreenOrientationDelegateEfl() { + ScreenOrientationProvider::SetDelegate(this); } ScreenOrientationDelegateEfl::~ScreenOrientationDelegateEfl() { -- 2.7.4 From 01df9be73211ec524e18da880199503f7411a1eb Mon Sep 17 00:00:00 2001 From: v-saha Date: Mon, 23 Jan 2023 19:37:42 +0530 Subject: [PATCH 12/16] [M108 Migration][Canvas2D][TCT] Do not accelerate small size canvas. Accelerating canvas with smaller size causes TCT issues since M76, it is known in upstream and reported too. Hence disabling acceleration for smaller canvases for EFL port. References: https://review.tizen.org/gerrit/274897 https://bugs.chromium.org/p/chromium/issues/detail?id=1051392 Change-Id: Ie7642016d3d66b8290c9e3a0d170b5f8e16311fa Signed-off-by: v-saha --- content/child/runtime_features.cc | 4 ++++ third_party/blink/public/platform/web_runtime_features.h | 1 + third_party/blink/renderer/platform/exported/web_runtime_features.cc | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 208ace0..3afa697 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc @@ -122,6 +122,10 @@ void SetRuntimeFeatureDefaultsForPlatform( #if BUILDFLAG(IS_EFL) // No plan to support complex UI for date/time INPUT types. WebRuntimeFeatures::EnableInputMultipleFieldsUI(false); + + // Small accelerated 2d canvas has tct issues, which are known in + // upstream version also. + WebRuntimeFeatures::EnableAcceleratedSmallCanvases(false); #endif } diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 5897b64b..62b3f1f 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h @@ -69,6 +69,7 @@ class BLINK_PLATFORM_EXPORT WebRuntimeFeatures : public WebRuntimeFeaturesBase { static void EnableFluentScrollbars(bool); #if BUILDFLAG(IS_EFL) static void EnableInputMultipleFieldsUI(bool); + static void EnableAcceleratedSmallCanvases(bool); #endif WebRuntimeFeatures() = delete; diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 5dd2b16..263302a 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc @@ -69,6 +69,10 @@ void WebRuntimeFeatures::EnableFluentScrollbars(bool enable) { void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) { RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable); } + +void WebRuntimeFeatures::EnableAcceleratedSmallCanvases(bool enable) { + RuntimeEnabledFeatures::SetAcceleratedSmallCanvasesEnabled(enable); +} #endif } // namespace blink -- 2.7.4 From d3644c0193273f708634389d6b47e18c1c8a0c24 Mon Sep 17 00:00:00 2001 From: uzair Date: Thu, 5 Jan 2023 13:31:55 +0530 Subject: [PATCH 13/16] [PDNCF] Backport ImageManager class and its dependencies Zero copy video rendering path is dependent on chromium GL_CHROMIUM_image extension but open source plans to deprecate it in future and hence some part of code is removed before 108 branch was forked for tizen and the new CHROMIUM_shared_image extension path is not completely present in 108 version. For now we partially backport [1] and [2] to bringup TBM path. [1] https://chromium-review.googlesource.com/c/chromium/src/+/3582497 [2] https://chromium-review.googlesource.com/c/chromium/src/+/3743320 Change-Id: If3d8eff200650113bd5b4893bb1636cd9895cb03 Signed-off-by: uzair --- gpu/GLES2/gl2chromium_autogen.h | 4 + gpu/GLES2/gl2extchromium.h | 37 +++++++ gpu/command_buffer/build_gles2_cmd_buffer.py | 15 +++ gpu/command_buffer/client/gles2_c_lib_autogen.h | 26 +++++ .../client/gles2_cmd_helper_autogen.h | 26 +++++ .../client/gles2_implementation_autogen.h | 8 ++ .../client/gles2_implementation_impl_autogen.h | 34 ++++++ .../client/gles2_implementation_unittest_autogen.h | 33 ++++++ .../client/gles2_interface_autogen.h | 5 + .../client/gles2_interface_stub_autogen.h | 5 + .../client/gles2_interface_stub_impl_autogen.h | 8 ++ .../client/gles2_trace_implementation_autogen.h | 5 + .../gles2_trace_implementation_impl_autogen.h | 22 ++++ .../common/gles2_cmd_format_autogen.h | 120 ++++++++++++++++++++ .../common/gles2_cmd_format_test_autogen.h | 41 +++++++ gpu/command_buffer/common/gles2_cmd_ids_autogen.h | 73 ++++++------ gpu/command_buffer/gles2_cmd_buffer_functions.txt | 3 + gpu/command_buffer/service/BUILD.gn | 2 + .../service/command_buffer_task_executor.h | 4 + gpu/command_buffer/service/context_group.cc | 2 + gpu/command_buffer/service/context_group.h | 6 + gpu/command_buffer/service/gles2_cmd_decoder.cc | 122 +++++++++++++++++++++ gpu/command_buffer/service/gles2_cmd_decoder.h | 1 + .../service/gles2_cmd_decoder_autogen.h | 58 ++++++++++ .../service/gles2_cmd_decoder_passthrough.cc | 46 ++++++++ .../service/gles2_cmd_decoder_passthrough.h | 5 + ...gles2_cmd_decoder_passthrough_doer_prototypes.h | 5 + .../service/gles2_cmd_decoder_passthrough_doers.cc | 49 +++++++++ ...es2_cmd_decoder_passthrough_handlers_autogen.cc | 48 ++++++++ gpu/command_buffer/service/image_manager.cc | 38 +++++++ gpu/command_buffer/service/image_manager.h | 42 +++++++ gpu/gles2_conform_support/egl/context.cc | 4 +- gpu/gles2_conform_support/egl/context.h | 2 + gpu/ipc/common/gpu_channel.mojom | 20 ++++ gpu/ipc/in_process_command_buffer.cc | 6 +- gpu/ipc/service/command_buffer_stub.cc | 8 ++ gpu/ipc/service/command_buffer_stub.h | 2 + gpu/ipc/service/gles2_command_buffer_stub.cc | 65 ++++++++++- gpu/ipc/service/gles2_command_buffer_stub.h | 3 + gpu/ipc/service/gpu_channel.cc | 21 ++++ gpu/ipc/service/gpu_channel.h | 11 ++ ui/gl/gl_image.cc | 6 + ui/gl/gl_image.h | 7 ++ 43 files changed, 1007 insertions(+), 41 deletions(-) create mode 100644 gpu/command_buffer/service/image_manager.cc create mode 100644 gpu/command_buffer/service/image_manager.h diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index f0b3a3d..efcb0d37 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -330,6 +330,10 @@ #define glCreateAndConsumeTextureCHROMIUM \ GLES2_GET_FUN(CreateAndConsumeTextureCHROMIUM) #define glBindUniformLocationCHROMIUM GLES2_GET_FUN(BindUniformLocationCHROMIUM) +#define glBindTexImage2DCHROMIUM GLES2_GET_FUN(BindTexImage2DCHROMIUM) +#define glBindTexImage2DWithInternalformatCHROMIUM \ + GLES2_GET_FUN(BindTexImage2DWithInternalformatCHROMIUM) +#define glReleaseTexImage2DCHROMIUM GLES2_GET_FUN(ReleaseTexImage2DCHROMIUM) #define glTraceBeginCHROMIUM GLES2_GET_FUN(TraceBeginCHROMIUM) #define glTraceEndCHROMIUM GLES2_GET_FUN(TraceEndCHROMIUM) #define glDiscardFramebufferEXT GLES2_GET_FUN(DiscardFramebufferEXT) diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index da4583a..44036b8 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h @@ -63,6 +63,43 @@ typedef GLboolean (GL_APIENTRY PFNGLUNMAPBUFFERCHROMIUM) (GLuint target); #endif #endif /* GL_CHROMIUM_pixel_transfer_buffer_object */ +/* GL_CHROMIUM_image */ +#ifndef GL_CHROMIUM_image +#define GL_CHROMIUM_image 1 + +typedef struct _ClientBuffer* ClientBuffer; + +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM(ClientBuffer buffer, + GLsizei width, + GLsizei height, + GLenum internalformat); +GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM(GLuint image_id); +GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM(GLenum target, + GLint imageId); +GL_APICALL void GL_APIENTRY +glBindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId); +GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM(GLenum target, + GLint imageId); +#endif +typedef GLuint(GL_APIENTRYP PFNGLCREATEIMAGECHROMIUMPROC)( + ClientBuffer buffer, + GLsizei width, + GLsizei height, + GLenum internalformat); +typedef void(GL_APIENTRYP PFNGLDESTROYIMAGECHROMIUMPROC)(GLuint image_id); +typedef void(GL_APIENTRYP PFNGLBINDTEXIMAGE2DCHROMIUMPROC)(GLenum target, + GLint imageId); +typedef void(GL_APIENTRYP PFNGLBINDTEXIMAGE2DWITHINTERNALFORMATCHROMIUMPROC)( + GLenum target, + GLenum internalformat, + GLint imageId); +typedef void(GL_APIENTRYP PFNGLRELEASETEXIMAGE2DCHROMIUMPROC)(GLenum target, + GLint imageId); +#endif /* GL_CHROMIUM_image */ + #ifndef GL_RGB_YCRCB_420_CHROMIUM #define GL_RGB_YCRCB_420_CHROMIUM 0x78FA #endif diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 453d713..b8bef5e 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3885,6 +3885,21 @@ _FUNCTION_INFO = { 'unit_test': False, 'pepper_interface': 'VertexArrayObject', }, + 'BindTexImage2DCHROMIUM': { + 'decoder_func': 'DoBindTexImage2DCHROMIUM', + 'unit_test': False, + 'extension': "CHROMIUM_image", + }, + 'BindTexImage2DWithInternalformatCHROMIUM': { + 'decoder_func': 'DoBindTexImage2DWithInternalformatCHROMIUM', + 'unit_test': False, + 'extension': "CHROMIUM_image", + }, + 'ReleaseTexImage2DCHROMIUM': { + 'decoder_func': 'DoReleaseTexImage2DCHROMIUM', + 'unit_test': False, + 'extension': "CHROMIUM_image", + }, 'IsVertexArrayOES': { 'type': 'Is', 'extension': 'OES_vertex_array_object', diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 161c43e..7114150 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1546,6 +1546,19 @@ void GL_APIENTRY GLES2BindUniformLocationCHROMIUM(GLuint program, const char* name) { gles2::GetGLContext()->BindUniformLocationCHROMIUM(program, location, name); } +void GL_APIENTRY GLES2BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::GetGLContext()->BindTexImage2DCHROMIUM(target, imageId); +} +void GL_APIENTRY +GLES2BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) { + gles2::GetGLContext()->BindTexImage2DWithInternalformatCHROMIUM( + target, internalformat, imageId); +} +void GL_APIENTRY GLES2ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::GetGLContext()->ReleaseTexImage2DCHROMIUM(target, imageId); +} void GL_APIENTRY GLES2TraceBeginCHROMIUM(const char* category_name, const char* trace_name) { gles2::GetGLContext()->TraceBeginCHROMIUM(category_name, trace_name); @@ -2908,6 +2921,19 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast(glBindUniformLocationCHROMIUM), }, { + "glBindTexImage2DCHROMIUM", + reinterpret_cast(glBindTexImage2DCHROMIUM), + }, + { + "glBindTexImage2DWithInternalformatCHROMIUM", + reinterpret_cast( + glBindTexImage2DWithInternalformatCHROMIUM), + }, + { + "glReleaseTexImage2DCHROMIUM", + reinterpret_cast(glReleaseTexImage2DCHROMIUM), + }, + { "glTraceBeginCHROMIUM", reinterpret_cast(glTraceBeginCHROMIUM), }, diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 7676f76..1de1be1 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -2923,6 +2923,32 @@ void BindUniformLocationCHROMIUMBucket(GLuint program, } } +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::cmds::BindTexImage2DCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, imageId); + } +} + +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) { + gles2::cmds::BindTexImage2DWithInternalformatCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, internalformat, imageId); + } +} + +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::cmds::ReleaseTexImage2DCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, imageId); + } +} + void TraceBeginCHROMIUM(GLuint category_bucket_id, GLuint name_bucket_id) { gles2::cmds::TraceBeginCHROMIUM* c = GetCmdSpace(); diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index b556b23..f1c6a51 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -1090,6 +1090,14 @@ void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; + +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) override; + +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; + void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) override; diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index a8586eb..1b945f0 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -3326,6 +3326,40 @@ void GLES2Implementation::CopySubTextureCHROMIUM( CheckGLError(); } +void GLES2Implementation::BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindTexImage2DCHROMIUM(" + << GLES2Util::GetStringTextureBindTarget(target) << ", " + << imageId << ")"); + helper_->BindTexImage2DCHROMIUM(target, imageId); + CheckGLError(); +} + +void GLES2Implementation::BindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG( + "[" << GetLogPrefix() << "] glBindTexImage2DWithInternalformatCHROMIUM(" + << GLES2Util::GetStringTextureBindTarget(target) << ", " + << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " + << imageId << ")"); + helper_->BindTexImage2DWithInternalformatCHROMIUM(target, internalformat, + imageId); + CheckGLError(); +} + +void GLES2Implementation::ReleaseTexImage2DCHROMIUM(GLenum target, + GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReleaseTexImage2DCHROMIUM(" + << GLES2Util::GetStringTextureBindTarget(target) << ", " + << imageId << ")"); + helper_->ReleaseTexImage2DCHROMIUM(target, imageId); + CheckGLError(); +} + void GLES2Implementation::DiscardFramebufferEXT(GLenum target, GLsizei count, const GLenum* attachments) { diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 6f17bb34..c2d65f1 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -2874,6 +2874,39 @@ TEST_F(GLES2ImplementationTest, VertexAttribDivisorANGLE) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, BindTexImage2DCHROMIUM) { + struct Cmds { + cmds::BindTexImage2DCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, 2); + + gl_->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, BindTexImage2DWithInternalformatCHROMIUM) { + struct Cmds { + cmds::BindTexImage2DWithInternalformatCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, GL_ALPHA, 3); + + gl_->BindTexImage2DWithInternalformatCHROMIUM(GL_TEXTURE_2D, GL_ALPHA, 3); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, ReleaseTexImage2DCHROMIUM) { + struct Cmds { + cmds::ReleaseTexImage2DCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, 2); + + gl_->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, DiscardFramebufferEXT) { GLenum data[2][1] = {{0}}; struct Cmds { diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 9867b5d..d24bf67 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -814,6 +814,11 @@ virtual GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) = 0; virtual void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) = 0; +virtual void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0; +virtual void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) = 0; +virtual void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0; virtual void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) = 0; virtual void TraceEndCHROMIUM() = 0; diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 0127a24..c799d22 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -790,6 +790,11 @@ GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override; void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) override; +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) override; void TraceEndCHROMIUM() override; diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 7d3af70..0dc071a 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -1056,6 +1056,14 @@ GLuint GLES2InterfaceStub::CreateAndConsumeTextureCHROMIUM( void GLES2InterfaceStub::BindUniformLocationCHROMIUM(GLuint /* program */, GLint /* location */, const char* /* name */) {} +void GLES2InterfaceStub::BindTexImage2DCHROMIUM(GLenum /* target */, + GLint /* imageId */) {} +void GLES2InterfaceStub::BindTexImage2DWithInternalformatCHROMIUM( + GLenum /* target */, + GLenum /* internalformat */, + GLint /* imageId */) {} +void GLES2InterfaceStub::ReleaseTexImage2DCHROMIUM(GLenum /* target */, + GLint /* imageId */) {} void GLES2InterfaceStub::TraceBeginCHROMIUM(const char* /* category_name */, const char* /* trace_name */) {} void GLES2InterfaceStub::TraceEndCHROMIUM() {} diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 9c075c5..2103e9e 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -790,6 +790,11 @@ GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override; void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) override; +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) override; void TraceEndCHROMIUM() override; diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 071fc7c..e22cb21 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -2217,6 +2217,28 @@ void GLES2TraceImplementation::BindUniformLocationCHROMIUM(GLuint program, gl_->BindUniformLocationCHROMIUM(program, location, name); } +void GLES2TraceImplementation::BindTexImage2DCHROMIUM(GLenum target, + GLint imageId) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindTexImage2DCHROMIUM"); + gl_->BindTexImage2DCHROMIUM(target, imageId); +} + +void GLES2TraceImplementation::BindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint imageId) { + TRACE_EVENT_BINARY_EFFICIENT0( + "gpu", "GLES2Trace::BindTexImage2DWithInternalformatCHROMIUM"); + gl_->BindTexImage2DWithInternalformatCHROMIUM(target, internalformat, + imageId); +} + +void GLES2TraceImplementation::ReleaseTexImage2DCHROMIUM(GLenum target, + GLint imageId) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::ReleaseTexImage2DCHROMIUM"); + gl_->ReleaseTexImage2DCHROMIUM(target, imageId); +} + void GLES2TraceImplementation::TraceBeginCHROMIUM(const char* category_name, const char* trace_name) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::TraceBeginCHROMIUM"); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 0c8b458..c6e3715 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -14537,6 +14537,126 @@ static_assert( offsetof(BindUniformLocationCHROMIUMBucket, name_bucket_id) == 12, "offset of BindUniformLocationCHROMIUMBucket name_bucket_id should be 12"); +struct BindTexImage2DCHROMIUM { + typedef BindTexImage2DCHROMIUM ValueType; + static const CommandId kCmdId = kBindTexImage2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, GLint _imageId) { + SetHeader(); + target = _target; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLint _imageId) { + static_cast(cmd)->Init(_target, _imageId); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + int32_t imageId; +}; + +static_assert(sizeof(BindTexImage2DCHROMIUM) == 12, + "size of BindTexImage2DCHROMIUM should be 12"); +static_assert(offsetof(BindTexImage2DCHROMIUM, header) == 0, + "offset of BindTexImage2DCHROMIUM header should be 0"); +static_assert(offsetof(BindTexImage2DCHROMIUM, target) == 4, + "offset of BindTexImage2DCHROMIUM target should be 4"); +static_assert(offsetof(BindTexImage2DCHROMIUM, imageId) == 8, + "offset of BindTexImage2DCHROMIUM imageId should be 8"); + +struct BindTexImage2DWithInternalformatCHROMIUM { + typedef BindTexImage2DWithInternalformatCHROMIUM ValueType; + static const CommandId kCmdId = kBindTexImage2DWithInternalformatCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, GLenum _internalformat, GLint _imageId) { + SetHeader(); + target = _target; + internalformat = _internalformat; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLenum _internalformat, GLint _imageId) { + static_cast(cmd)->Init(_target, _internalformat, _imageId); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + uint32_t internalformat; + int32_t imageId; +}; + +static_assert(sizeof(BindTexImage2DWithInternalformatCHROMIUM) == 16, + "size of BindTexImage2DWithInternalformatCHROMIUM should be 16"); +static_assert( + offsetof(BindTexImage2DWithInternalformatCHROMIUM, header) == 0, + "offset of BindTexImage2DWithInternalformatCHROMIUM header should be 0"); +static_assert( + offsetof(BindTexImage2DWithInternalformatCHROMIUM, target) == 4, + "offset of BindTexImage2DWithInternalformatCHROMIUM target should be 4"); +static_assert(offsetof(BindTexImage2DWithInternalformatCHROMIUM, + internalformat) == 8, + "offset of BindTexImage2DWithInternalformatCHROMIUM " + "internalformat should be 8"); +static_assert( + offsetof(BindTexImage2DWithInternalformatCHROMIUM, imageId) == 12, + "offset of BindTexImage2DWithInternalformatCHROMIUM imageId should be 12"); + +struct ReleaseTexImage2DCHROMIUM { + typedef ReleaseTexImage2DCHROMIUM ValueType; + static const CommandId kCmdId = kReleaseTexImage2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, GLint _imageId) { + SetHeader(); + target = _target; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLint _imageId) { + static_cast(cmd)->Init(_target, _imageId); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + int32_t imageId; +}; + +static_assert(sizeof(ReleaseTexImage2DCHROMIUM) == 12, + "size of ReleaseTexImage2DCHROMIUM should be 12"); +static_assert(offsetof(ReleaseTexImage2DCHROMIUM, header) == 0, + "offset of ReleaseTexImage2DCHROMIUM header should be 0"); +static_assert(offsetof(ReleaseTexImage2DCHROMIUM, target) == 4, + "offset of ReleaseTexImage2DCHROMIUM target should be 4"); +static_assert(offsetof(ReleaseTexImage2DCHROMIUM, imageId) == 8, + "offset of ReleaseTexImage2DCHROMIUM imageId should be 8"); + struct TraceBeginCHROMIUM { typedef TraceBeginCHROMIUM ValueType; static const CommandId kCmdId = kTraceBeginCHROMIUM; diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 5f45c44..d4b335c 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -4795,6 +4795,47 @@ TEST_F(GLES2FormatTest, BindUniformLocationCHROMIUMBucket) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BindTexImage2DCHROMIUM) { + cmds::BindTexImage2DCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = + cmd.Set(&cmd, static_cast(11), static_cast(12)); + EXPECT_EQ(static_cast(cmds::BindTexImage2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, BindTexImage2DWithInternalformatCHROMIUM) { + cmds::BindTexImage2DWithInternalformatCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11), + static_cast(12), static_cast(13)); + EXPECT_EQ(static_cast( + cmds::BindTexImage2DWithInternalformatCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.internalformat); + EXPECT_EQ(static_cast(13), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, ReleaseTexImage2DCHROMIUM) { + cmds::ReleaseTexImage2DCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = + cmd.Set(&cmd, static_cast(11), static_cast(12)); + EXPECT_EQ(static_cast(cmds::ReleaseTexImage2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, TraceBeginCHROMIUM) { cmds::TraceBeginCHROMIUM& cmd = *GetBufferAs(); void* next_cmd = diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 4a47970..430f843 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -301,41 +301,44 @@ OP(ProduceTextureDirectCHROMIUMImmediate) /* 542 */ \ OP(CreateAndConsumeTextureINTERNALImmediate) /* 543 */ \ OP(BindUniformLocationCHROMIUMBucket) /* 544 */ \ - OP(TraceBeginCHROMIUM) /* 545 */ \ - OP(TraceEndCHROMIUM) /* 546 */ \ - OP(DiscardFramebufferEXTImmediate) /* 547 */ \ - OP(LoseContextCHROMIUM) /* 548 */ \ - OP(DrawBuffersEXTImmediate) /* 549 */ \ - OP(DiscardBackbufferCHROMIUM) /* 550 */ \ - OP(FlushDriverCachesCHROMIUM) /* 551 */ \ - OP(SetActiveURLCHROMIUM) /* 552 */ \ - OP(ContextVisibilityHintCHROMIUM) /* 553 */ \ - OP(CoverageModulationCHROMIUM) /* 554 */ \ - OP(BlendBarrierKHR) /* 555 */ \ - OP(BindFragDataLocationIndexedEXTBucket) /* 556 */ \ - OP(BindFragDataLocationEXTBucket) /* 557 */ \ - OP(GetFragDataIndexEXT) /* 558 */ \ - OP(InitializeDiscardableTextureCHROMIUM) /* 559 */ \ - OP(UnlockDiscardableTextureCHROMIUM) /* 560 */ \ - OP(LockDiscardableTextureCHROMIUM) /* 561 */ \ - OP(WindowRectanglesEXTImmediate) /* 562 */ \ - OP(CreateGpuFenceINTERNAL) /* 563 */ \ - OP(WaitGpuFenceCHROMIUM) /* 564 */ \ - OP(DestroyGpuFenceCHROMIUM) /* 565 */ \ - OP(SetReadbackBufferShadowAllocationINTERNAL) /* 566 */ \ - OP(FramebufferTextureMultiviewOVR) /* 567 */ \ - OP(MaxShaderCompilerThreadsKHR) /* 568 */ \ - OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 569 */ \ - OP(BeginSharedImageAccessDirectCHROMIUM) /* 570 */ \ - OP(EndSharedImageAccessDirectCHROMIUM) /* 571 */ \ - OP(EnableiOES) /* 572 */ \ - OP(DisableiOES) /* 573 */ \ - OP(BlendEquationiOES) /* 574 */ \ - OP(BlendEquationSeparateiOES) /* 575 */ \ - OP(BlendFunciOES) /* 576 */ \ - OP(BlendFuncSeparateiOES) /* 577 */ \ - OP(ColorMaskiOES) /* 578 */ \ - OP(IsEnablediOES) /* 579 */ + OP(BindTexImage2DCHROMIUM) /* 545 */ \ + OP(BindTexImage2DWithInternalformatCHROMIUM) /* 546 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 547 */ \ + OP(TraceBeginCHROMIUM) /* 548 */ \ + OP(TraceEndCHROMIUM) /* 549 */ \ + OP(DiscardFramebufferEXTImmediate) /* 550 */ \ + OP(LoseContextCHROMIUM) /* 551 */ \ + OP(DrawBuffersEXTImmediate) /* 552 */ \ + OP(DiscardBackbufferCHROMIUM) /* 553 */ \ + OP(FlushDriverCachesCHROMIUM) /* 554 */ \ + OP(SetActiveURLCHROMIUM) /* 555 */ \ + OP(ContextVisibilityHintCHROMIUM) /* 556 */ \ + OP(CoverageModulationCHROMIUM) /* 557 */ \ + OP(BlendBarrierKHR) /* 558 */ \ + OP(BindFragDataLocationIndexedEXTBucket) /* 559 */ \ + OP(BindFragDataLocationEXTBucket) /* 560 */ \ + OP(GetFragDataIndexEXT) /* 561 */ \ + OP(InitializeDiscardableTextureCHROMIUM) /* 562 */ \ + OP(UnlockDiscardableTextureCHROMIUM) /* 563 */ \ + OP(LockDiscardableTextureCHROMIUM) /* 564 */ \ + OP(WindowRectanglesEXTImmediate) /* 565 */ \ + OP(CreateGpuFenceINTERNAL) /* 566 */ \ + OP(WaitGpuFenceCHROMIUM) /* 567 */ \ + OP(DestroyGpuFenceCHROMIUM) /* 568 */ \ + OP(SetReadbackBufferShadowAllocationINTERNAL) /* 569 */ \ + OP(FramebufferTextureMultiviewOVR) /* 570 */ \ + OP(MaxShaderCompilerThreadsKHR) /* 571 */ \ + OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 572 */ \ + OP(BeginSharedImageAccessDirectCHROMIUM) /* 573 */ \ + OP(EndSharedImageAccessDirectCHROMIUM) /* 574 */ \ + OP(EnableiOES) /* 575 */ \ + OP(DisableiOES) /* 576 */ \ + OP(BlendEquationiOES) /* 577 */ \ + OP(BlendEquationSeparateiOES) /* 578 */ \ + OP(BlendFunciOES) /* 579 */ \ + OP(BlendFuncSeparateiOES) /* 580 */ \ + OP(ColorMaskiOES) /* 581 */ \ + OP(IsEnablediOES) /* 582 */ enum CommandId { kOneBeforeStartPoint = diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt index 590507a..a2801cd 100644 --- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt +++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt @@ -323,6 +323,9 @@ GL_APICALL void GL_APIENTRY glProduceTextureDirectCHROMIUM (GLidBindText GL_APICALL GLuint GL_APIENTRY glCreateAndConsumeTextureCHROMIUM (const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glCreateAndConsumeTextureINTERNAL (GLuint texture, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glBindUniformLocationCHROMIUM (GLidProgram program, GLint location, const char* name); +GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); +GL_APICALL void GL_APIENTRY glBindTexImage2DWithInternalformatCHROMIUM (GLenumTextureBindTarget target, GLenumTextureInternalFormat internalformat, GLint imageId); +GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); GL_APICALL void GL_APIENTRY glTraceBeginCHROMIUM (const char* category_name, const char* trace_name); GL_APICALL void GL_APIENTRY glTraceEndCHROMIUM (void); GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenumFramebufferTarget target, GLsizei count, const GLenum* attachments); diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 4632c26..a03eceb 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn @@ -48,6 +48,8 @@ target(link_target_type, "service_sources") { "gpu_switches.h", "image_factory.cc", "image_factory.h", + "image_manager.cc", + "image_manager.h", "mailbox_manager.h", "memory_tracking.cc", "memory_tracking.h", diff --git a/gpu/command_buffer/service/command_buffer_task_executor.h b/gpu/command_buffer/service/command_buffer_task_executor.h index 56f94e7..b01d55f 100644 --- a/gpu/command_buffer/service/command_buffer_task_executor.h +++ b/gpu/command_buffer/service/command_buffer_task_executor.h @@ -13,6 +13,7 @@ #include "gpu/command_buffer/common/activity_flags.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/framebuffer_completeness_cache.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/passthrough_discardable_manager.h" #include "gpu/command_buffer/service/sequence_id.h" #include "gpu/command_buffer/service/service_discardable_manager.h" @@ -91,6 +92,8 @@ class GPU_GLES2_EXPORT CommandBufferTaskExecutor { MailboxManager* mailbox_manager() const { return mailbox_manager_; } // Not const because these return inner pointers. + + gles2::ImageManager* image_manager() { return &image_manager_; } ServiceDiscardableManager* discardable_manager() { return &discardable_manager_; } @@ -118,6 +121,7 @@ class GPU_GLES2_EXPORT CommandBufferTaskExecutor { gl::GLSurfaceFormat share_group_surface_format_; std::unique_ptr owned_program_cache_; raw_ptr program_cache_; + gles2::ImageManager image_manager_; ServiceDiscardableManager discardable_manager_; PassthroughDiscardableManager passthrough_discardable_manager_; gles2::ShaderTranslatorCache shader_translator_cache_; diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 0638760..b714271 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -76,6 +76,7 @@ ContextGroup::ContextGroup( FramebufferCompletenessCache* framebuffer_completeness_cache, const scoped_refptr& feature_info, bool bind_generates_resource, + ImageManager* image_manager, gpu::ImageFactory* image_factory, gl::ProgressReporter* progress_reporter, const GpuFeatureInfo& gpu_feature_info, @@ -118,6 +119,7 @@ ContextGroup::ContextGroup( uniform_buffer_offset_alignment_(1u), program_cache_(nullptr), feature_info_(feature_info), + image_manager_(image_manager), image_factory_(image_factory), use_passthrough_cmd_decoder_(false), passthrough_resources_(new PassthroughResources), diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 0aaaf27..6760a38 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -44,6 +44,7 @@ namespace gles2 { class ProgramCache; class BufferManager; +class ImageManager; class RenderbufferManager; class ProgramManager; class SamplerManager; @@ -68,6 +69,7 @@ class GPU_GLES2_EXPORT ContextGroup : public base::RefCounted { FramebufferCompletenessCache* framebuffer_completeness_cache, const scoped_refptr& feature_info, bool bind_generates_resource, + ImageManager* image_manager, gpu::ImageFactory* image_factory, gl::ProgressReporter* progress_reporter, const GpuFeatureInfo& gpu_feature_info, @@ -164,6 +166,8 @@ class GPU_GLES2_EXPORT ContextGroup : public base::RefCounted { return feature_info_.get(); } + ImageManager* image_manager() const { return image_manager_; } + gpu::ImageFactory* image_factory() const { return image_factory_; } const GpuPreferences& gpu_preferences() const { @@ -309,6 +313,8 @@ class GPU_GLES2_EXPORT ContextGroup : public base::RefCounted { scoped_refptr feature_info_; + raw_ptr image_manager_; + raw_ptr image_factory_; std::vector> decoders_; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 0f2c253..43e00a8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -65,6 +65,7 @@ #include "gpu/command_buffer/service/gpu_state_tracer.h" #include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_factory.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -963,6 +964,8 @@ class GLES2DecoderImpl : public GLES2Decoder, return vertex_array_manager_.get(); } + ImageManager* image_manager() { return group_->image_manager(); } + MemoryTracker* memory_tracker() { return group_->memory_tracker(); } @@ -1221,6 +1224,16 @@ class GLES2DecoderImpl : public GLES2Decoder, uint32_t texture_target, gl::GLImage* image, bool can_bind_to_sampler) override; + void DoBindTexImage2DCHROMIUM(GLenum target, GLint image_id); + void DoBindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint image_id); + // Common implementation of DoBindTexImage2DCHROMIUM entry points. + void BindTexImage2DCHROMIUMImpl(const char* function_name, + GLenum target, + GLenum internalformat, + GLint image_id); + void DoReleaseTexImage2DCHROMIUM(GLenum target, GLint image_id); void DoTraceEndCHROMIUM(void); @@ -18586,6 +18599,115 @@ void GLES2DecoderImpl::BindImage(uint32_t client_texture_id, : gpu::gles2::Texture::UNBOUND); } +void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(GLenum target, GLint image_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM"); + + BindTexImage2DCHROMIUMImpl("glBindTexImage2DCHROMIUM", target, 0, image_id); +} + +void GLES2DecoderImpl::DoBindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint image_id) { + TRACE_EVENT0("gpu", + "GLES2DecoderImpl::DoBindTexImage2DWithInternalformatCHROMIUM"); + + BindTexImage2DCHROMIUMImpl("glBindTexImage2DWithInternalformatCHROMIUM", + target, internalformat, image_id); +} + +void GLES2DecoderImpl::BindTexImage2DCHROMIUMImpl(const char* function_name, + GLenum target, + GLenum internalformat, + GLint image_id) { + if (target == GL_TEXTURE_CUBE_MAP) { + LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, function_name, "invalid target"); + return; + } + + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "no texture bound"); + return; + } + + gl::GLImage* image = image_manager()->LookupImage(image_id); + if (!image) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "no image found with the given ID"); + return; + } + + Texture::ImageState image_state = Texture::UNBOUND; + + if (image->ShouldBindOrCopy() == gl::GLImage::BIND) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", error_state_.get()); + + // Note: We fallback to using CopyTexImage() before the texture is used + // when BindTexImage() fails. + if (internalformat) { + if (image->BindTexImageWithInternalformat(target, internalformat)) + image_state = Texture::BOUND; + } else { + if (image->BindTexImage(target)) + image_state = Texture::BOUND; + } + } + + gfx::Size size = image->GetSize(); + GLenum texture_internalformat = + internalformat ? internalformat : image->GetInternalFormat(); + texture_manager()->SetLevelInfo(texture_ref, target, 0, + texture_internalformat, size.width(), + size.height(), 1, 0, image->GetDataFormat(), + image->GetDataType(), gfx::Rect(size)); + texture_manager()->SetLevelImage(texture_ref, target, 0, image, image_state); +} + +void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(GLenum target, + GLint image_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM"); + + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReleaseTexImage2DCHROMIUM", + "no texture bound"); + return; + } + + gl::GLImage* image = image_manager()->LookupImage(image_id); + if (!image) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReleaseTexImage2DCHROMIUM", + "no image found with the given ID"); + return; + } + + Texture::ImageState image_state; + + // Do nothing when image is not currently bound. + if (texture_ref->texture()->GetLevelImage(target, 0, &image_state) != image) + return; + + if (image_state == Texture::BOUND) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", error_state_.get()); + + image->ReleaseTexImage(target); + texture_manager()->SetLevelInfo(texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + } + + texture_manager()->SetLevelImage(texture_ref, target, 0, nullptr, + Texture::UNBOUND); +} + error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index dc7f727..62bf9e9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -46,6 +46,7 @@ class CopyTexImageResourceManager; class CopyTextureCHROMIUMResourceManager; class FramebufferManager; class GLES2Util; +class ImageManager; class Logger; class Outputter; class ShaderTranslatorInterface; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index c07937b..e45bf73 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -5026,6 +5026,64 @@ error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureINTERNALImmediate( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBindTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindTexImage2DCHROMIUM", target, + "target"); + return error::kNoError; + } + DoBindTexImage2DCHROMIUM(target, imageId); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleBindTexImage2DWithInternalformatCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DWithInternalformatCHROMIUM& c = + *static_cast(cmd_data); + GLenum target = static_cast(c.target); + GLenum internalformat = static_cast(c.internalformat); + GLint imageId = static_cast(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBindTexImage2DWithInternalformatCHROMIUM", target, "target"); + return error::kNoError; + } + if (!validators_->texture_internal_format.IsValid(internalformat)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBindTexImage2DWithInternalformatCHROMIUM", internalformat, + "internalformat"); + return error::kNoError; + } + DoBindTexImage2DWithInternalformatCHROMIUM(target, internalformat, imageId); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleReleaseTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::ReleaseTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glReleaseTexImage2DCHROMIUM", target, + "target"); + return error::kNoError; + } + DoReleaseTexImage2DCHROMIUM(target, imageId); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleTraceEndCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index ab2f90a..c716981 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -3012,6 +3012,52 @@ error::Error GLES2DecoderPassthroughImpl::HandleSetActiveURLCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::BindTexImage2DCHROMIUMImpl( + GLenum target, + GLenum internalformat, + GLint imageId) { + TextureTarget target_enum = GLenumToTextureTarget(target); + if (target_enum == TextureTarget::kCubeMap || + target_enum == TextureTarget::kUnkown) { + InsertError(GL_INVALID_ENUM, "Invalid target"); + return error::kNoError; + } + + gl::GLImage* image = group_->image_manager()->LookupImage(imageId); + if (image == nullptr) { + InsertError(GL_INVALID_OPERATION, "No image found with the given ID"); + return error::kNoError; + } + + const BoundTexture& bound_texture = + bound_textures_[static_cast(target_enum)][active_texture_unit_]; + if (bound_texture.texture == nullptr) { + InsertError(GL_INVALID_OPERATION, "No texture bound"); + return error::kNoError; + } + + if (image->ShouldBindOrCopy() == gl::GLImage::BIND) { + if (internalformat) + image->BindTexImageWithInternalformat(target, internalformat); + else + image->BindTexImage(target); + } else { + image->CopyTexImage(target); + } + + // Target is already validated + UpdateTextureSizeFromTarget(target); + + DCHECK(bound_texture.texture != nullptr); + bound_texture.texture->SetLevelImage(target, 0, image); + + // If there was any GLImage bound to |target| on this texture unit, then + // forget it. + RemovePendingBindingTexture(target, active_texture_unit_); + + return error::kNoError; +} + void GLES2DecoderPassthroughImpl::VerifyServiceTextureObjectsExist() { resources_->texture_object_map.ForEach( [this](GLuint client_id, scoped_refptr texture) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index e46b8ae..2e791c8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h @@ -25,6 +25,7 @@ #include "gpu/command_buffer/service/client_service_map.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/passthrough_abstract_texture_impl.h" @@ -465,6 +466,10 @@ class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl // up-to-date. void LazilyUpdateCurrentlyBoundElementArrayBuffer(); + error::Error BindTexImage2DCHROMIUMImpl(GLenum target, + GLenum internalformat, + GLint image_id); + void VerifyServiceTextureObjectsExist(); bool IsEmulatedFramebufferBound(GLenum target) const; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index 3a96342..cd4a3e0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h @@ -873,6 +873,11 @@ error::Error DoCreateAndConsumeTextureINTERNAL(GLuint texture_client_id, error::Error DoBindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name); +error::Error DoBindTexImage2DCHROMIUM(GLenum target, GLint imageId); +error::Error DoBindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId); +error::Error DoReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId); error::Error DoTraceBeginCHROMIUM(const char* category_name, const char* trace_name); error::Error DoTraceEndCHROMIUM(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index 9b09ddf..9b51b08 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc @@ -4572,6 +4572,55 @@ error::Error GLES2DecoderPassthroughImpl::DoBindUniformLocationCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::DoBindTexImage2DCHROMIUM( + GLenum target, + GLint imageId) { + return BindTexImage2DCHROMIUMImpl(target, 0, imageId); +} + +error::Error +GLES2DecoderPassthroughImpl::DoBindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint imageId) { + return BindTexImage2DCHROMIUMImpl(target, internalformat, imageId); +} + +error::Error GLES2DecoderPassthroughImpl::DoReleaseTexImage2DCHROMIUM( + GLenum target, + GLint imageId) { + TextureTarget target_enum = GLenumToTextureTarget(target); + if (target_enum == TextureTarget::kCubeMap || + target_enum == TextureTarget::kUnkown) { + InsertError(GL_INVALID_ENUM, "Invalid target"); + return error::kNoError; + } + + const BoundTexture& bound_texture = + bound_textures_[static_cast(target_enum)][active_texture_unit_]; + if (bound_texture.texture == nullptr) { + InsertError(GL_INVALID_OPERATION, "No texture bound"); + return error::kNoError; + } + + gl::GLImage* image = group_->image_manager()->LookupImage(imageId); + if (image == nullptr) { + InsertError(GL_INVALID_OPERATION, "No image found with the given ID"); + return error::kNoError; + } + + // Only release the image if it is currently bound + if (bound_texture.texture->GetLevelImage(target, 0) == image) { + image->ReleaseTexImage(target); + bound_texture.texture->SetLevelImage(target, 0, nullptr); + } + + // Target is already validated + UpdateTextureSizeFromTarget(target); + + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::DoTraceBeginCHROMIUM( const char* category_name, const char* trace_name) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc index 09295b0..e52e094 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc @@ -4302,6 +4302,54 @@ GLES2DecoderPassthroughImpl::HandleCreateAndConsumeTextureINTERNALImmediate( return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::HandleBindTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + error::Error error = DoBindTexImage2DCHROMIUM(target, imageId); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + +error::Error +GLES2DecoderPassthroughImpl::HandleBindTexImage2DWithInternalformatCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DWithInternalformatCHROMIUM& c = + *static_cast(cmd_data); + GLenum target = static_cast(c.target); + GLenum internalformat = static_cast(c.internalformat); + GLint imageId = static_cast(c.imageId); + error::Error error = DoBindTexImage2DWithInternalformatCHROMIUM( + target, internalformat, imageId); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::HandleReleaseTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::ReleaseTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + error::Error error = DoReleaseTexImage2DCHROMIUM(target, imageId); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::HandleTraceEndCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { diff --git a/gpu/command_buffer/service/image_manager.cc b/gpu/command_buffer/service/image_manager.cc new file mode 100644 index 0000000..d7ca6d0 --- /dev/null +++ b/gpu/command_buffer/service/image_manager.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/image_manager.h" + +#include + +#include "base/check.h" +#include "ui/gl/gl_image.h" + +namespace gpu { +namespace gles2 { + +ImageManager::ImageManager() = default; + +ImageManager::~ImageManager() = default; + +void ImageManager::AddImage(gl::GLImage* image, int32_t service_id) { + DCHECK(images_.find(service_id) == images_.end()); + images_[service_id] = image; +} + +void ImageManager::RemoveImage(int32_t service_id) { + DCHECK(images_.find(service_id) != images_.end()); + images_.erase(service_id); +} + +gl::GLImage* ImageManager::LookupImage(int32_t service_id) { + GLImageMap::const_iterator iter = images_.find(service_id); + if (iter != images_.end()) + return iter->second.get(); + + return nullptr; +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/service/image_manager.h b/gpu/command_buffer/service/image_manager.h new file mode 100644 index 0000000..8397eee --- /dev/null +++ b/gpu/command_buffer/service/image_manager.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ + +#include + +#include + +#include "base/memory/ref_counted.h" +#include "gpu/gpu_export.h" + +namespace gl { +class GLImage; +} + +namespace gpu { +namespace gles2 { + +// This class keeps track of the images and their state. +class GPU_EXPORT ImageManager { + public: + ImageManager(); + ~ImageManager(); + ImageManager(const ImageManager&) = delete; + ImageManager& operator=(const ImageManager&) = delete; + + void AddImage(gl::GLImage* image, int32_t service_id); + void RemoveImage(int32_t service_id); + gl::GLImage* LookupImage(int32_t service_id); + + private: + typedef std::unordered_map> GLImageMap; + GLImageMap images_; +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc index 35fe874..9dfd81f 100644 --- a/gpu/gles2_conform_support/egl/context.cc +++ b/gpu/gles2_conform_support/egl/context.cc @@ -255,8 +255,8 @@ bool Context::CreateService(gl::GLSurface* gl_surface) { scoped_refptr group(new gpu::gles2::ContextGroup( gpu_preferences, true, &mailbox_manager_, nullptr /* memory_tracker */, &translator_cache_, &completeness_cache_, feature_info, true, - nullptr /* image_factory */, nullptr /* progress_reporter */, - gpu_feature_info, &discardable_manager_, + &image_manager_, nullptr /* image_factory */, + nullptr /* progress_reporter */, gpu_feature_info, &discardable_manager_, &passthrough_discardable_manager_, &shared_image_manager_)); auto command_buffer = std::make_unique(); diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h index f8d0b38..54dbc99 100644 --- a/gpu/gles2_conform_support/egl/context.h +++ b/gpu/gles2_conform_support/egl/context.h @@ -15,6 +15,7 @@ #include "gpu/command_buffer/service/command_buffer_direct.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_tracer.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/passthrough_discardable_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" @@ -116,6 +117,7 @@ class Context : public base::RefCountedThreadSafe, gpu::gles2::MailboxManagerImpl mailbox_manager_; gpu::gles2::TraceOutputter outputter_; + gpu::gles2::ImageManager image_manager_; gpu::ServiceDiscardableManager discardable_manager_; gpu::PassthroughDiscardableManager passthrough_discardable_manager_; gpu::SharedImageManager shared_image_manager_; diff --git a/gpu/ipc/common/gpu_channel.mojom b/gpu/ipc/common/gpu_channel.mojom index 717c9f0..e83f981 100644 --- a/gpu/ipc/common/gpu_channel.mojom +++ b/gpu/ipc/common/gpu_channel.mojom @@ -238,6 +238,15 @@ interface GpuChannel { ReleaseSysmemBufferCollection(mojo_base.mojom.UnguessableToken id); }; +struct CreateImageParams { + int32 id; + gfx.mojom.GpuMemoryBufferHandle gpu_memory_buffer; + gfx.mojom.Size size; + gfx.mojom.BufferFormat format; + gfx.mojom.BufferPlane plane; + uint64 image_release_count; +}; + // Interface used to issue commands to a specific CommandBuffer instance in the // GPU process. interface CommandBuffer { @@ -258,6 +267,17 @@ interface CommandBuffer { // Requests retrieval of a GpuFenceHandle by ID. GetGpuFenceHandle(uint32 id) => (gfx.mojom.GpuFenceHandle? fence_handle); + // Creates an image from an existing gpu memory buffer. The id that can be + // used to identify the image from a command buffer. + // + // TODO(crbug.com/1216120): Remove this once CreateImageCHROMIUM is gone. + CreateImage(CreateImageParams params); + + // Destroys a previously created image identified by `id`. + // + // TODO(crbug.com/1216120): Remove this once CreateImageCHROMIUM is gone. + DestroyImage(int32 id); + // Asynchronously waits until the SyncToken is signaled, then sends a // corresponding SignalAck on the CommandBufferClient interface, using // `signal_id` to identify this request. diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 0d9a6b3..8bf1b65 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc @@ -249,9 +249,9 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( task_executor_->mailbox_manager(), std::move(memory_tracker), task_executor_->shader_translator_cache(), task_executor_->framebuffer_completeness_cache(), feature_info, - params.attribs.bind_generates_resource, params.image_factory, - nullptr /* progress_reporter */, task_executor_->gpu_feature_info(), - task_executor_->discardable_manager(), + params.attribs.bind_generates_resource, task_executor_->image_manager(), + params.image_factory, nullptr /* progress_reporter */, + task_executor_->gpu_feature_info(), task_executor_->discardable_manager(), task_executor_->passthrough_discardable_manager(), task_executor_->shared_image_manager()); diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc index 88de4e9..8c87d63 100644 --- a/gpu/ipc/service/command_buffer_stub.cc +++ b/gpu/ipc/service/command_buffer_stub.cc @@ -544,6 +544,14 @@ void CommandBufferStub::GetGpuFenceHandle(uint32_t id, std::move(callback).Run(gfx::GpuFenceHandle()); } +void CommandBufferStub::CreateImage(mojom::CreateImageParamsPtr params) { + DLOG(ERROR) << "CreateImage unsupported."; +} + +void CommandBufferStub::DestroyImage(int32_t id) { + DLOG(ERROR) << "DestroyImage unsupported."; +} + void CommandBufferStub::OnDestroyTransferBuffer(int32_t id) { TRACE_EVENT0("gpu", "CommandBufferStub::OnDestroyTransferBuffer"); diff --git a/gpu/ipc/service/command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h index 9089132..2d1b5cd 100644 --- a/gpu/ipc/service/command_buffer_stub.h +++ b/gpu/ipc/service/command_buffer_stub.h @@ -220,6 +220,8 @@ class GPU_IPC_SERVICE_EXPORT CommandBufferStub gfx::GpuFenceHandle handle) override; void GetGpuFenceHandle(uint32_t id, GetGpuFenceHandleCallback callback) override; + void CreateImage(mojom::CreateImageParamsPtr params) override; + void DestroyImage(int32_t id) override; void SignalSyncToken(const SyncToken& sync_token, uint32_t id) override; void SignalQuery(uint32_t query, uint32_t id) override; void BindMediaReceiver(mojo::GenericPendingAssociatedReceiver receiver, diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc index be556d7..cd81adc 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.cc +++ b/gpu/ipc/service/gles2_command_buffer_stub.cc @@ -26,6 +26,7 @@ #include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gl_state_restorer_impl.h" #include "gpu/command_buffer/service/gpu_fence_manager.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -110,7 +111,7 @@ gpu::ContextResult GLES2CommandBufferStub::Initialize( manager->mailbox_manager(), CreateMemoryTracker(), manager->shader_translator_cache(), manager->framebuffer_completeness_cache(), feature_info, - init_params.attribs.bind_generates_resource, + init_params.attribs.bind_generates_resource, channel_->image_manager(), gmb_factory ? gmb_factory->AsImageFactory() : nullptr, manager->watchdog() /* progress_reporter */, manager->gpu_feature_info(), manager->discardable_manager(), @@ -508,6 +509,68 @@ void GLES2CommandBufferStub::GetGpuFenceHandle( std::move(callback).Run(std::move(handle)); } +void GLES2CommandBufferStub::CreateImage(mojom::CreateImageParamsPtr params) { + TRACE_EVENT0("gpu", "GLES2CommandBufferStub::OnCreateImage"); + const int32_t id = params->id; + const gfx::Size& size = params->size; + const gfx::BufferFormat& format = params->format; + const gfx::BufferPlane& plane = params->plane; + const uint64_t image_release_count = params->image_release_count; + ScopedContextOperation operation(*this); + if (!operation.is_context_current()) + return; + + gles2::ImageManager* image_manager = channel_->image_manager(); + DCHECK(image_manager); + if (image_manager->LookupImage(id)) { + LOG(ERROR) << "Image already exists with same ID."; + return; + } + + if (!gpu::IsImageFromGpuMemoryBufferFormatSupported( + format, gles2_decoder_->GetCapabilities())) { + LOG(ERROR) << "Format is not supported."; + return; + } + + if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, format)) { + LOG(ERROR) << "Invalid image size for format."; + return; + } + + if (!gpu::IsPlaneValidForGpuMemoryBufferFormat(plane, format)) { + LOG(ERROR) << "Invalid plane " << gfx::BufferPlaneToString(plane) << " for " + << gfx::BufferFormatToString(format); + return; + } + + scoped_refptr image = channel()->CreateImageForGpuMemoryBuffer( + std::move(params->gpu_memory_buffer), size, format, plane, + surface_handle_); + if (!image.get()) + return; + + image_manager->AddImage(image.get(), id); + if (image_release_count) + sync_point_client_state_->ReleaseFenceSync(image_release_count); +} + +void GLES2CommandBufferStub::DestroyImage(int32_t id) { + TRACE_EVENT0("gpu", "GLES2CommandBufferStub::OnDestroyImage"); + ScopedContextOperation operation(*this); + if (!operation.is_context_current()) + return; + + gles2::ImageManager* image_manager = channel_->image_manager(); + DCHECK(image_manager); + if (!image_manager->LookupImage(id)) { + LOG(ERROR) << "Image with ID doesn't exist."; + return; + } + + image_manager->RemoveImage(id); +} + void GLES2CommandBufferStub::OnSwapBuffers(uint64_t swap_id, uint32_t flags) {} } // namespace gpu diff --git a/gpu/ipc/service/gles2_command_buffer_stub.h b/gpu/ipc/service/gles2_command_buffer_stub.h index 4568fe5..973134f 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.h +++ b/gpu/ipc/service/gles2_command_buffer_stub.h @@ -66,6 +66,9 @@ class GPU_IPC_SERVICE_EXPORT GLES2CommandBufferStub void GetGpuFenceHandle(uint32_t gpu_fence_id, GetGpuFenceHandleCallback callback) override; + void CreateImage(mojom::CreateImageParamsPtr params) override; + void DestroyImage(int32_t id) override; + void OnSwapBuffers(uint64_t swap_id, uint32_t flags) override; // The group of contexts that share namespaces with this context. diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index 11b35bf..b00928a 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc @@ -41,6 +41,7 @@ #include "base/unguessable_token.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/service/image_factory.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/scheduler.h" @@ -50,6 +51,7 @@ #include "gpu/ipc/service/gles2_command_buffer_stub.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "gpu/ipc/service/image_decode_accelerator_stub.h" #include "gpu/ipc/service/raster_command_buffer_stub.h" #include "gpu/ipc/service/webgpu_command_buffer_stub.h" @@ -541,6 +543,7 @@ GpuChannel::GpuChannel( task_runner_(task_runner), io_task_runner_(io_task_runner), share_group_(share_group), + image_manager_(new gles2::ImageManager()), is_gpu_host_(is_gpu_host), filter_(base::MakeRefCounted( this, @@ -1078,4 +1081,22 @@ uint64_t GpuChannel::GetMemoryUsage() const { return size; } +scoped_refptr GpuChannel::CreateImageForGpuMemoryBuffer( + gfx::GpuMemoryBufferHandle handle, + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane, + SurfaceHandle surface_handle) { + GpuChannelManager* manager = gpu_channel_manager(); + if (!manager->gpu_memory_buffer_factory()) + return nullptr; + + // TODO(b/220336463): plumb the right color space. + return manager->gpu_memory_buffer_factory() + ->AsImageFactory() + ->CreateImageForGpuMemoryBuffer(std::move(handle), size, format, + gfx::ColorSpace(), plane, client_id_, + surface_handle); +} + } // namespace gpu diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h index 49f643b..c877b7b 100644 --- a/gpu/ipc/service/gpu_channel.h +++ b/gpu/ipc/service/gpu_channel.h @@ -36,6 +36,7 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_image.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gpu_preference.h" @@ -104,6 +105,8 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener, SyncPointManager* sync_point_manager() const { return sync_point_manager_; } + gles2::ImageManager* image_manager() const { return image_manager_.get(); } + const scoped_refptr& task_runner() const { return task_runner_; } @@ -155,6 +158,13 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener, uint64_t GetMemoryUsage() const; + scoped_refptr CreateImageForGpuMemoryBuffer( + gfx::GpuMemoryBufferHandle handle, + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane, + SurfaceHandle surface_handle); + // Executes a DeferredRequest that was previously received and has now been // scheduled by the scheduler. void ExecuteDeferredRequest(mojom::DeferredRequestParamsPtr params); @@ -285,6 +295,7 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener, // process use. scoped_refptr share_group_; + std::unique_ptr image_manager_; std::unique_ptr shared_image_stub_; const bool is_gpu_host_; diff --git a/ui/gl/gl_image.cc b/ui/gl/gl_image.cc index 18834f4..fca4990 100644 --- a/ui/gl/gl_image.cc +++ b/ui/gl/gl_image.cc @@ -67,6 +67,12 @@ bool GLImage::BindTexImage(unsigned target) { return false; } +bool GLImage::BindTexImageWithInternalformat(unsigned target, + unsigned internalformat) { + NOTREACHED(); + return false; +} + void GLImage::ReleaseTexImage(unsigned target) { NOTREACHED(); } diff --git a/ui/gl/gl_image.h b/ui/gl/gl_image.h index c7b3d98..1c65bcb 100644 --- a/ui/gl/gl_image.h +++ b/ui/gl/gl_image.h @@ -73,6 +73,13 @@ class GL_EXPORT GLImage : public base::RefCounted { // It is valid for an implementation to always return false. virtual bool BindTexImage(unsigned target); + // Bind image to texture currently bound to |target|, forcing the texture's + // internal format to the specified one. This is a feature not available on + // all platforms. Returns true on success. It is valid for an implementation + // to always return false. + virtual bool BindTexImageWithInternalformat(unsigned target, + unsigned internalformat); + // Release image from texture currently bound to |target|. virtual void ReleaseTexImage(unsigned target); -- 2.7.4 From f5520c6619ee217bbdfe45c0f6ef3b0ae68a0b67 Mon Sep 17 00:00:00 2001 From: Suhaspoornachandra Date: Wed, 11 Jan 2023 10:23:28 +0530 Subject: [PATCH 14/16] [M108 Migration][STT] Speech bring up. Refrence: https://review.tizen.org/gerrit/c/274769/ https://review.tizen.org/gerrit/c/275686/ Change-Id: Ic439f156dc8804d7d2ad7eed59f3bd550153623a Signed-off-by: Suhaspoornachandra --- content/browser/browser_interface_binders.cc | 2 + content/browser/browser_main_loop.cc | 13 +- content/browser/browser_main_loop.h | 8 +- .../speech/speech_recognition_dispatcher_host.cc | 9 + .../speech/speech_recognition_manager_impl.cc | 15 +- .../speech/speech_recognition_manager_impl.h | 12 + content/browser/speech/speech_recognizer.h | 8 + packaging/chromium-efl.spec | 2 + tizen_src/build/BUILD.gn | 32 ++ tizen_src/build/config/BUILD.gn | 3 + tizen_src/build/config/tizen_features.gni | 1 + tizen_src/build/gn_chromiumefl.sh | 1 + .../chromium_impl/content/browser/browser_efl.gni | 22 + .../browser/speech/speech_recognizer_impl_tizen.cc | 533 +++++++++++++++++++++ .../browser/speech/speech_recognizer_impl_tizen.h | 93 ++++ .../tizen_speech_recognition_manager_delegate.cc | 37 ++ .../tizen_speech_recognition_manager_delegate.h | 41 ++ .../efl_integration/content_browser_client_efl.cc | 11 + .../efl_integration/content_browser_client_efl.h | 10 + 19 files changed, 846 insertions(+), 7 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc create mode 100644 tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h create mode 100644 tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc create mode 100644 tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index adac0a4..541cf90 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc @@ -737,10 +737,12 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) { map->Add( base::BindRepeating(&BindSharedWorkerConnector, base::Unretained(host))); +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) map->Add( base::BindRepeating(&SpeechRecognitionDispatcherHost::Create, host->GetProcess()->GetID(), host->GetRoutingID()), GetIOThreadTaskRunner({})); +#endif map->Add(base::BindRepeating( &RenderFrameHostImpl::GetSpeechSynthesis, base::Unretained(host))); diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index eedf4ba..420eca0 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -87,7 +87,6 @@ #include "content/browser/screenlock_monitor/screenlock_monitor.h" #include "content/browser/screenlock_monitor/screenlock_monitor_device_source.h" #include "content/browser/sms/sms_provider.h" -#include "content/browser/speech/speech_recognition_manager_impl.h" #include "content/browser/speech/tts_controller_impl.h" #include "content/browser/startup_data_impl.h" #include "content/browser/startup_task_runner.h" @@ -149,6 +148,10 @@ #include "ui/gfx/font_render_params.h" #include "ui/gfx/switches.h" +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +#include "content/browser/speech/speech_recognition_manager_impl.h" +#endif + #if defined(USE_AURA) || BUILDFLAG(IS_MAC) #include "content/browser/compositor/image_transport_factory.h" #endif @@ -1111,14 +1114,14 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:MidiService"); midi_service_->Shutdown(); } - +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:SpeechRecognitionManager"); io_thread_->task_runner()->DeleteSoon( FROM_HERE, speech_recognition_manager_.release()); } - +#endif TtsControllerImpl::GetInstance()->Shutdown(); memory_pressure_monitor_.reset(); @@ -1358,14 +1361,14 @@ void BrowserMainLoop::PostCreateThreadsImpl() { media_stream_manager_ = std::make_unique(audio_system_.get()); } - +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) { TRACE_EVENT0("startup", "BrowserMainLoop::PostCreateThreads:InitSpeechRecognition"); speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl( audio_system_.get(), media_stream_manager_.get())); } - +#endif { TRACE_EVENT0("startup", "BrowserMainLoop::PostCreateThreads::InitUserInputMonitor"); diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index 5e2ef10..acc602d 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h @@ -93,11 +93,15 @@ class MediaStreamManager; class SaveFileManager; class ScreenlockMonitor; class SmsProvider; -class SpeechRecognitionManagerImpl; + class StartupTaskRunner; class TracingControllerImpl; struct MainFunctionParams; +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +class SpeechRecognitionManagerImpl; +#endif + namespace responsiveness { class Watcher; } // namespace responsiveness @@ -367,8 +371,10 @@ class CONTENT_EXPORT BrowserMainLoop { std::unique_ptr midi_service_; +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) // Must be deleted on the IO thread. std::unique_ptr speech_recognition_manager_; +#endif #if BUILDFLAG(IS_WIN) std::unique_ptr system_message_window_; diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc index bf5d858..f322ba6 100644 --- a/content/browser/speech/speech_recognition_dispatcher_host.cc +++ b/content/browser/speech/speech_recognition_dispatcher_host.cc @@ -121,6 +121,15 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI( DCHECK_NE(embedder_render_frame_id, MSG_ROUTING_NONE); } +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + if (SpeechRecognitionManagerImpl::GetInstance()) { + Evas_Object* parent_view = + static_cast(web_contents->GetEflNativeView()); + Evas* evas = evas_object_evas_get(parent_view); + SpeechRecognitionManagerImpl::GetInstance()->SetEvas(evas); + } +#endif + bool filter_profanities = SpeechRecognitionManagerImpl::GetInstance() && SpeechRecognitionManagerImpl::GetInstance()->delegate() && diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index 0fdb61f..007f645 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc @@ -45,6 +45,10 @@ #include "content/browser/speech/speech_recognizer_impl_android.h" #endif +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) && BUILDFLAG(IS_EFL) +#include "content/browser/speech/speech_recognizer_impl_tizen.h" +#endif + namespace content { SpeechRecognitionManager* SpeechRecognitionManager::manager_for_tests_; @@ -180,7 +184,7 @@ int SpeechRecognitionManagerImpl::CreateSession( session->config = config; session->context = config.initial_context; -#if !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_EFL) // A SpeechRecognitionEngine (and corresponding Config) is required only // when using SpeechRecognizerImpl, which performs the audio capture and // endpointing in the browser. This is not the case of Android where, not @@ -211,6 +215,15 @@ int SpeechRecognitionManagerImpl::CreateSession( session->recognizer = new SpeechRecognizerImpl( this, audio_system_, session_id, config.continuous, config.interim_results, google_remote_engine); +#elif BUILDFLAG(IS_EFL) +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) + session->recognizer = new SpeechRecognizerImplTizen(this, session_id); +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + session->recognizer->SetEvas(evas_); +#endif +#else + NOTREACHED(); +#endif #else session->recognizer = new SpeechRecognizerImplAndroid(this, session_id); #endif diff --git a/content/browser/speech/speech_recognition_manager_impl.h b/content/browser/speech/speech_recognition_manager_impl.h index 9f26103..6f1b15e 100644 --- a/content/browser/speech/speech_recognition_manager_impl.h +++ b/content/browser/speech/speech_recognition_manager_impl.h @@ -19,6 +19,10 @@ #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-forward.h" #include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h" +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) +#include +#endif + namespace media { class AudioSystem; } @@ -89,6 +93,10 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl SpeechRecognitionManagerDelegate* delegate() const { return delegate_.get(); } +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + void SetEvas(Evas* evas) { evas_ = evas; } +#endif + protected: // BrowserMainLoop is the only one allowed to instantiate this class. friend class BrowserMainLoop; @@ -185,6 +193,10 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl std::unique_ptr delegate_; const int requester_id_; +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + Evas* evas_ = nullptr; +#endif + // Used for posting asynchronous tasks (on the IO thread) without worrying // about this class being destroyed in the meanwhile (due to browser shutdown) // since tasks pending on a destroyed WeakPtr are automatically discarded. diff --git a/content/browser/speech/speech_recognizer.h b/content/browser/speech/speech_recognizer.h index 681691d..86822c8 100644 --- a/content/browser/speech/speech_recognizer.h +++ b/content/browser/speech/speech_recognizer.h @@ -10,6 +10,10 @@ #include "base/memory/ref_counted.h" #include "content/common/content_export.h" +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) +#include +#endif + namespace content { class SpeechRecognitionEventListener; @@ -32,6 +36,10 @@ class CONTENT_EXPORT SpeechRecognizer virtual bool IsActive() const = 0; virtual bool IsCapturingAudio() const = 0; +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + virtual void SetEvas(Evas* evas) {} +#endif + protected: friend class base::RefCountedThreadSafe; diff --git a/packaging/chromium-efl.spec b/packaging/chromium-efl.spec index 01e43e7..baa95b3 100644 --- a/packaging/chromium-efl.spec +++ b/packaging/chromium-efl.spec @@ -106,6 +106,7 @@ BuildRequires: pkgconfig(nss) BuildRequires: pkgconfig(scim) BuildRequires: pkgconfig(security-manager) BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(stt) BuildRequires: pkgconfig(tts) BuildRequires: pkgconfig(ui-gadget-1) BuildRequires: pkgconfig(vconf) @@ -141,6 +142,7 @@ BuildRequires: pkgconfig(xtst) %endif %if "%{?tizen_profile_name}" == "tv" +BuildRequires: pkgconfig(capi-stt-wrapper-tv) BuildRequires: pkgconfig(vd-win-util) %endif diff --git a/tizen_src/build/BUILD.gn b/tizen_src/build/BUILD.gn index 3fbf271..ce7e0ba 100644 --- a/tizen_src/build/BUILD.gn +++ b/tizen_src/build/BUILD.gn @@ -579,6 +579,38 @@ config("tts-public") { } } +config("capi-stt-wrapper-tv") { + if (tizen_product_tv) { + ldflags = [ "-lcapi-stt-wrapper-tv" ] + } +} + +tizen_pkg_config("libcapi-stt-wrapper-tv") { + packages = [] + if (tizen_product_tv) { + packages = [ "capi-stt-wrapper-tv" ] + } +} + +config("stt") { + if (is_tizen) { + ldflags = [ "-lstt" ] + } +} + +tizen_pkg_config("libstt") { + packages = [] + if (is_tizen) { + packages = [ "stt" ] + } +} + +config("stt-public") { + if (is_tizen) { + cflags = [ "-stt" ] + } +} + config("vconf") { if (is_tizen) { ldflags = [ "-lvconf" ] diff --git a/tizen_src/build/config/BUILD.gn b/tizen_src/build/config/BUILD.gn index ed0f2b7..3b4e9c1 100644 --- a/tizen_src/build/config/BUILD.gn +++ b/tizen_src/build/config/BUILD.gn @@ -39,6 +39,9 @@ config("tizen_feature_flags") { "TIZEN_MULTIMEDIA_USE_CAPI_AUDIO_IO", ] } + if (tizen_web_speech_recognition) { + defines += [ "TIZEN_WEB_SPEECH_RECOGNITION" ] + } # TODO: There are X11 dependencies in following condition. # The files need to be implemented based on Wayland. diff --git a/tizen_src/build/config/tizen_features.gni b/tizen_src/build/config/tizen_features.gni index 94b85b2..5e1ec9a 100644 --- a/tizen_src/build/config/tizen_features.gni +++ b/tizen_src/build/config/tizen_features.gni @@ -46,6 +46,7 @@ declare_args() { tizen_multimedia_support = false tizen_multimedia = false tizen_tbm_support = false + tizen_web_speech_recognition = false } if (is_tizen && tizen_multimedia_support) { diff --git a/tizen_src/build/gn_chromiumefl.sh b/tizen_src/build/gn_chromiumefl.sh index d2e392a..fd9662f 100755 --- a/tizen_src/build/gn_chromiumefl.sh +++ b/tizen_src/build/gn_chromiumefl.sh @@ -221,6 +221,7 @@ add_tizen_flags() { # FIXME: http://165.213.149.170/jira/browse/TWF-610 ADDITIONAL_GN_PARAMETERS+="tizen_multimedia=true proprietary_codecs=true + tizen_web_speech_recognition=true tizen_tbm_support=false " } diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index b6a1022..2586fa5 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -52,6 +52,19 @@ if (tizen_multimedia_support) { ] } +if (tizen_web_speech_recognition) { + external_content_browser_efl_configs += [ + "//tizen_src/build:stt", + "//tizen_src/build:libstt", + ] + if (tizen_product_tv) { + external_content_browser_efl_configs += [ + "//tizen_src/build:capi-stt-wrapper-tv", + "//tizen_src/build:libcapi-stt-wrapper-tv", + ] + } +} + ############################################################################## # Dependency ############################################################################## @@ -148,3 +161,12 @@ if (tizen_tbm_support) { "//tizen_src/chromium_impl/content/browser/media/browser_mediapacket_manager.h", ] } + +if (tizen_web_speech_recognition) { + external_content_browser_efl_sources += [ + "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc", + "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h", + "//tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc", + "//tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h", + ] +} diff --git a/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc new file mode 100644 index 0000000..72e2ac0 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc @@ -0,0 +1,533 @@ +// Copyright 2016 Samsung Electronics Inc. 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/speech/speech_recognizer_impl_tizen.h" + +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/speech_recognition_event_listener.h" +#include "content/public/browser/speech_recognition_manager.h" +#include "content/public/browser/speech_recognition_session_config.h" +#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h" + +#define RUN_ON_BROWSER_IO_THREAD(METHOD, ...) \ + do { \ + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { \ + GetIOThreadTaskRunner({})->PostTask( \ + FROM_HERE, base::BindOnce(&SpeechRecognizerImplTizen::METHOD, this, \ + ##__VA_ARGS__)); \ + return; \ + } \ + } while (0) + +#define RUN_ON_BROWSER_UI_THREAD(METHOD, ...) \ + do { \ + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { \ + GetUIThreadTaskRunner({})->PostTask( \ + FROM_HERE, base::BindOnce(&SpeechRecognizerImplTizen::METHOD, this, \ + ##__VA_ARGS__)); \ + return; \ + } \ + } while (0) + +#define ENUM_CASE(x) \ + case x: \ + return #x; \ + break + +#if !BUILDFLAG(IS_TIZEN_TV) +#define stt_wrapper_get_error_message stt_get_error_message +#define stt_wrapper_get_state stt_get_state +#define stt_wrapper_destroy stt_destroy +#define stt_wrapper_unset_error_cb stt_unset_error_cb +#define stt_wrapper_unset_state_changed_cb stt_unset_state_changed_cb +#define stt_wrapper_unset_recognition_result_cb stt_unset_recognition_result_cb +#define stt_wrapper_unprepare stt_unprepare +#define stt_wrapper_cancel stt_cancel +#define stt_wrapper_start stt_start +#define stt_wrapper_set_error_cb stt_set_error_cb +#define stt_wrapper_set_state_changed_cb stt_set_state_changed_cb +#define stt_wrapper_set_recognition_result_cb stt_set_recognition_result_cb +#define stt_wrapper_create stt_create +#define stt_wrapper_stop stt_stop +#define stt_wrapper_prepare stt_prepare +#define stt_wrapper_foreach_supported_languages stt_foreach_supported_languages +#endif + +namespace { + +// Replace hyphen "-" in language with underscore "_". CAPI does not +// support language string with hyphen. Example: en-US -> en_US. +// change character case. Example: en_us -> en_US. +std::string GetLanguageString(const std::string& language) { + std::string ret(language); + std::replace(ret.begin(), ret.end(), '-', '_'); + std::transform(ret.begin(), ret.begin() + 2, ret.begin(), ::tolower); + std::transform(ret.end() - 2, ret.end(), ret.end() - 2, ::toupper); + return ret; +} + +const char* GetErrorString(stt_error_e error) { + switch (error) { + ENUM_CASE(STT_ERROR_NONE); + ENUM_CASE(STT_ERROR_OUT_OF_MEMORY); + ENUM_CASE(STT_ERROR_IO_ERROR); + ENUM_CASE(STT_ERROR_INVALID_PARAMETER); + ENUM_CASE(STT_ERROR_TIMED_OUT); + ENUM_CASE(STT_ERROR_RECORDER_BUSY); + ENUM_CASE(STT_ERROR_OUT_OF_NETWORK); + ENUM_CASE(STT_ERROR_PERMISSION_DENIED); + ENUM_CASE(STT_ERROR_NOT_SUPPORTED); + ENUM_CASE(STT_ERROR_INVALID_STATE); + ENUM_CASE(STT_ERROR_INVALID_LANGUAGE); + ENUM_CASE(STT_ERROR_ENGINE_NOT_FOUND); + ENUM_CASE(STT_ERROR_OPERATION_FAILED); + ENUM_CASE(STT_ERROR_NOT_SUPPORTED_FEATURE); + ENUM_CASE(STT_ERROR_RECORDING_TIMED_OUT); + ENUM_CASE(STT_ERROR_NO_SPEECH); + ENUM_CASE(STT_ERROR_IN_PROGRESS_TO_READY); + ENUM_CASE(STT_ERROR_IN_PROGRESS_TO_RECORDING); + ENUM_CASE(STT_ERROR_IN_PROGRESS_TO_PROCESSING); + ENUM_CASE(STT_ERROR_SERVICE_RESET); + }; + + NOTREACHED() << "Invalid stt_error_e! (" << error << ")"; + return ""; +} + +} // namespace + +namespace content { + +blink::mojom::SpeechRecognitionErrorCode GetErrorCode(stt_error_e reason) { + switch (reason) { + case STT_ERROR_NONE: + return blink::mojom::SpeechRecognitionErrorCode::kNone; + case STT_ERROR_NO_SPEECH: + return blink::mojom::SpeechRecognitionErrorCode::kNoSpeech; + case STT_ERROR_RECORDING_TIMED_OUT: + case STT_ERROR_IO_ERROR: + case STT_ERROR_RECORDER_BUSY: + return blink::mojom::SpeechRecognitionErrorCode::kAudioCapture; + case STT_ERROR_OUT_OF_NETWORK: + return blink::mojom::SpeechRecognitionErrorCode::kNetwork; + case STT_ERROR_PERMISSION_DENIED: + return blink::mojom::SpeechRecognitionErrorCode::kNotAllowed; + case STT_ERROR_INVALID_LANGUAGE: + return blink::mojom::SpeechRecognitionErrorCode::kLanguageNotSupported; + case STT_ERROR_NOT_SUPPORTED: + return blink::mojom::SpeechRecognitionErrorCode::kServiceNotAllowed; + default: + return blink::mojom::SpeechRecognitionErrorCode::kAborted; + } +} + +SpeechRecognizerImplTizen::SpeechRecognizerImplTizen( + SpeechRecognitionEventListener* listener, + int session_id) + : SpeechRecognizer(listener, session_id) {} + +SpeechRecognizerImplTizen::~SpeechRecognizerImplTizen() { + base::AutoLock auto_lock(abort_lock_); + if (!handle_ || is_aborted_) + return; + + Destroy(); +} + +void SpeechRecognizerImplTizen::StartRecognition(const std::string& device_id) { + SpeechRecognitionSessionConfig config = + SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id()); + + recognition_type_ = config.interim_results ? STT_RECOGNITION_TYPE_FREE_PARTIAL + : STT_RECOGNITION_TYPE_FREE; + continuous_ = config.continuous; + + if (config.language.empty()) { + LOG(ERROR) << "stt session #" << session_id() + << " language config is empty! Use 'en_US'"; + is_lang_supported_ = true; + language_ = "en_US"; + } else { + language_ = GetLanguageString(config.language); + } + + // Initialize and prepare stt in UI thread + Prepare(); +} + +void SpeechRecognizerImplTizen::Prepare() { + RUN_ON_BROWSER_UI_THREAD(Prepare); + + if (!Initialize()) + return; + + stt_wrapper_foreach_supported_languages(handle_, &OnSupportedLanguages, this); + +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + int err = stt_wrapper_prepare_with_evas(handle_, evas_); +#else + int err = stt_wrapper_prepare(handle_); +#endif + if (STT_ERROR_NONE != err) + HandleSttError(static_cast(err), FROM_HERE); +} + +void SpeechRecognizerImplTizen::AbortRecognition() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + EndRecognition(FROM_HERE); +} + +void SpeechRecognizerImplTizen::StopAudioCapture() { + RUN_ON_BROWSER_UI_THREAD(StopAudioCapture); + continuous_ = false; + + if (GetCurrentState() != STT_STATE_RECORDING) + return; + + int err = stt_wrapper_stop(handle_); + if (STT_ERROR_NONE != err) + HandleSttError(static_cast(err), FROM_HERE); +} + +bool SpeechRecognizerImplTizen::IsActive() const { + return GetCurrentState() > STT_STATE_CREATED ? true : false; +} + +bool SpeechRecognizerImplTizen::IsCapturingAudio() const { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + return GetCurrentState() >= STT_STATE_RECORDING ? true : false; +} + +bool SpeechRecognizerImplTizen::Initialize() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + is_aborted_ = false; + + int err = stt_wrapper_create(&handle_); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + + err = stt_wrapper_set_recognition_result_cb(handle_, &OnRecognitionResult, + this); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + + err = stt_wrapper_set_state_changed_cb(handle_, &OnStateChange, this); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + + err = stt_wrapper_set_error_cb(handle_, &OnError, this); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + return true; +} + +void SpeechRecognizerImplTizen::StartInternal() { + RUN_ON_BROWSER_UI_THREAD(StartInternal); + + LOG(INFO) << "stt session #" << session_id() + << " language used : " << language_.c_str() + << " type : " << recognition_type_; + if (!is_lang_supported_) { + HandleSttError(STT_ERROR_INVALID_LANGUAGE, FROM_HERE); + return; + } + + int err = stt_wrapper_start(handle_, language_.c_str(), recognition_type_); + if (STT_ERROR_NONE != err) + HandleSttError(static_cast(err), FROM_HERE); +} + +void SpeechRecognizerImplTizen::Destroy() { + RUN_ON_BROWSER_UI_THREAD(Destroy); + if (!handle_) + return; + + is_lang_supported_ = false; + continuous_ = false; + if (GetCurrentState() >= STT_STATE_RECORDING) + stt_wrapper_cancel(handle_); + if (GetCurrentState() == STT_STATE_READY) { +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + stt_wrapper_unprepare_with_evas(handle_, evas_); +#else + stt_wrapper_unprepare(handle_); +#endif + } + if (GetCurrentState() == STT_STATE_CREATED) { + stt_wrapper_unset_recognition_result_cb(handle_); + stt_wrapper_unset_state_changed_cb(handle_); + stt_wrapper_unset_error_cb(handle_); + } + + // Valid states to be called: created, Ready, Recording, Processing +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + int err = stt_wrapper_destroy_with_evas(handle_, evas_); +#else + int err = stt_wrapper_destroy(handle_); +#endif + if (err != STT_ERROR_NONE) + LOG(ERROR) << "stt session #" << session_id() << " stt_destroy failed with " + << GetErrorString(static_cast(err)); + else + handle_ = nullptr; +} + +bool SpeechRecognizerImplTizen::ShouldStartRecognition() const { + return GetCurrentState() >= STT_STATE_READY; +} + +// There is no default stt state. So use |STT_STATE_CREATED| +// This will work as we will use it to determine audio capturing. +stt_state_e SpeechRecognizerImplTizen::GetCurrentState() const { + if (!handle_ || is_aborted_) + return STT_STATE_CREATED; + + stt_state_e state = STT_STATE_CREATED; + int err = stt_wrapper_get_state(handle_, &state); + if (err != STT_ERROR_NONE) + LOG(ERROR) << "stt session #" << session_id() << " stt_get_state FAILED!"; + return state; +} + +void SpeechRecognizerImplTizen::RecognitionResults( + bool no_speech, + std::vector& results) { + { + base::AutoLock auto_lock(abort_lock_); + if (is_aborted_) { + LOG(INFO) << "stt engine is in error state"; + return; + } + } + + if (no_speech && !continuous_) { + HandleSttError(STT_ERROR_NO_SPEECH, FROM_HERE); + return; + } + + listener()->OnRecognitionResults(session_id(), results); +} + +void SpeechRecognizerImplTizen::HandleSttError(stt_error_e error, + const base::Location& location) { + RUN_ON_BROWSER_IO_THREAD(HandleSttError, error, location); + LOG(ERROR) << "stt session #" << session_id() << " error " + << GetErrorString(error) << " from " << location.function_name() + << "(" << location.line_number() << ")"; + { + base::AutoLock auto_lock(abort_lock_); + if (!handle_ || is_aborted_) + return; + } + + blink::mojom::SpeechRecognitionError recognition_error; + recognition_error.code = GetErrorCode(static_cast(error)); + recognition_error.details = blink::mojom::SpeechAudioErrorDetails::kNone; + + listener()->OnRecognitionError(session_id(), recognition_error); + EndRecognition(FROM_HERE); +} + +void SpeechRecognizerImplTizen::HandleSttResultError(const std::string error) { + RUN_ON_BROWSER_IO_THREAD(HandleSttResultError, error); + LOG(ERROR) << "stt session #" << session_id() << " no result as " << error; + + { + base::AutoLock auto_lock(abort_lock_); + if (!handle_ || is_aborted_) + return; + } + + if (error == STT_RESULT_MESSAGE_ERROR_TOO_SOON || + error == STT_RESULT_MESSAGE_ERROR_TOO_SHORT || + error == STT_RESULT_MESSAGE_ERROR_TOO_LONG || + error == STT_RESULT_MESSAGE_ERROR_TOO_QUIET || + error == STT_RESULT_MESSAGE_ERROR_TOO_LOUD || + error == STT_RESULT_MESSAGE_ERROR_TOO_FAST) { + blink::mojom::SpeechRecognitionError recognition_error; + recognition_error.code = blink::mojom::SpeechRecognitionErrorCode::kNoMatch; + recognition_error.details = blink::mojom::SpeechAudioErrorDetails::kNone; + listener()->OnRecognitionError(session_id(), recognition_error); + } +} + +void SpeechRecognizerImplTizen::RecognitionStarted() { + RUN_ON_BROWSER_IO_THREAD(RecognitionStarted); + + listener()->OnAudioStart(session_id()); + listener()->OnSoundStart(session_id()); + listener()->OnRecognitionStart(session_id()); +} + +void SpeechRecognizerImplTizen::AudioCaptureEnd() { + RUN_ON_BROWSER_IO_THREAD(AudioCaptureEnd); + + listener()->OnSoundEnd(session_id()); + listener()->OnAudioEnd(session_id()); +} + +void SpeechRecognizerImplTizen::EndRecognition(const base::Location& location) { + RUN_ON_BROWSER_IO_THREAD(EndRecognition, location); + + { + base::AutoLock auto_lock(abort_lock_); + if (is_aborted_) + return; + + is_aborted_ = true; + } + + LOG(INFO) << "stt session #" << session_id() + << " ending recognition called from " << location.function_name() + << "(" << location.line_number() << ")"; + + if (GetCurrentState() == STT_STATE_RECORDING) + AudioCaptureEnd(); + + listener()->OnRecognitionEnd(session_id()); + Destroy(); +} + +bool SpeechRecognizerImplTizen::OnSupportedLanguages(stt_h stt, + const char* language, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return false; + + if (!speech->language_.compare(language)) { + speech->is_lang_supported_ = true; + return false; + } + + return true; +} + +void SpeechRecognizerImplTizen::OnRecognitionResult(stt_h stt, + stt_result_event_e event, + const char** data, + int data_count, + const char* msg, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return; + + if (event == STT_RESULT_EVENT_ERROR) { + speech->HandleSttResultError(msg); + return; + } + + bool no_speech = true; + blink::mojom::SpeechRecognitionResultPtr result = + blink::mojom::SpeechRecognitionResult::New(); + for (int i = 0; i < data_count; i++) { + if (data[i] && data[i][0] != ' ') { + no_speech = false; + std::u16string utterance; + base::UTF8ToUTF16(data[i], strlen(data[i]), &utterance); + result->hypotheses.push_back( + blink::mojom::SpeechRecognitionHypothesis::New(utterance, 1.0)); + } + } + + result->is_provisional = + (event == STT_RESULT_EVENT_FINAL_RESULT) ? false : true; + + std::vector results; + results.push_back(std::move(result)); + + speech->RecognitionResults(no_speech, results); +} + +void SpeechRecognizerImplTizen::OnStateChange(stt_h stt, + stt_state_e previous, + stt_state_e current, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return; + + LOG(INFO) << "stt session #" << speech->session_id() + << " state change called. Previous : " << previous + << " Current : " << current; + + switch (current) { + case STT_STATE_READY: + switch (previous) { + case STT_STATE_CREATED: + speech->StartInternal(); + break; + case STT_STATE_RECORDING: + if (!speech->is_aborted_) + speech->HandleSttError(STT_ERROR_NO_SPEECH, FROM_HERE); + break; + case STT_STATE_PROCESSING: + // If continuous attribute is true recognition shouldn't stop after + // receiving one final result. So start the recognition again. + if (speech->continuous_) + speech->StartInternal(); + // |stt_recognition_result_cb| is called even when a partial result is + // obtained. So, need to end recognition only when the state change + // is confirmed. + else + speech->EndRecognition(FROM_HERE); + break; + default: + break; + } + break; + case STT_STATE_RECORDING: + speech->RecognitionStarted(); + break; + case STT_STATE_PROCESSING: + speech->AudioCaptureEnd(); + break; + default: + break; + } +} + +void SpeechRecognizerImplTizen::OnError(stt_h stt, + stt_error_e reason, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return; +#if BUILDFLAG(IS_TIZEN_TV) + char* error_msg = nullptr; + const std::string no_speech_msg = "voice_engine.error.no_speech"; + int ret = stt_wrapper_get_error_message(stt, &error_msg); + if (ret == STT_ERROR_NONE) { + LOG(INFO) << "stt session #" << speech->session_id() + << "err msg : " << error_msg; + if (!no_speech_msg.compare(error_msg)) + reason = STT_ERROR_NO_SPEECH; + if (error_msg) + free(error_msg); + } else { + LOG(ERROR) << "stt session #" << speech->session_id() + << " stt_wrapper_get_error_message:" + << GetErrorString(static_cast(ret)); + } +#endif + speech->HandleSttError(reason, FROM_HERE); +} + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h new file mode 100644 index 0000000..1cb47ce --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h @@ -0,0 +1,93 @@ +// Copyright 2016 Samsung Electronics Inc. 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_SPEECH_SPEECH_RECOGNIZER_IMPL_TIZEN_ +#define CONTENT_BROWSER_SPEECH_SPEECH_RECOGNIZER_IMPL_TIZEN_ + +#include + +#include "base/location.h" +#include "content/browser/speech/speech_recognizer.h" +#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h" + +#if BUILDFLAG(IS_TIZEN_TV) +#include +#if defined(USE_WAYLAND) +#include +#endif +#else +#include +#endif + +namespace content { + +class CONTENT_EXPORT SpeechRecognizerImplTizen : public SpeechRecognizer { + public: + SpeechRecognizerImplTizen(SpeechRecognitionEventListener* listener, + int session_id); + + // SpeechRecognizer methods. + void StartRecognition(const std::string& device_id) override; + void AbortRecognition() override; + void StopAudioCapture() override; + bool IsActive() const override; + bool IsCapturingAudio() const override; +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + void SetEvas(Evas* evas) override { evas_ = evas; } +#endif + + private: + SpeechRecognizerImplTizen(const SpeechRecognizerImplTizen&) = delete; + SpeechRecognizerImplTizen& operator=(const SpeechRecognizerImplTizen&) = + delete; + + ~SpeechRecognizerImplTizen() override; + + void Prepare(); + bool Initialize(); + void StartInternal(); + void Destroy(); + stt_state_e GetCurrentState() const; + bool ShouldStartRecognition() const; + void RecognitionResults( + bool no_speech, + std::vector& results); + void HandleSttError(stt_error_e error, const base::Location& location); + void HandleSttResultError(const std::string error); + void RecognitionStarted(); + void AudioCaptureEnd(); + void EndRecognition(const base::Location& location); + + // Callbacks + static bool OnSupportedLanguages(stt_h stt, + const char* language, + void* user_data); + static void OnRecognitionResult(stt_h stt, + stt_result_event_e event, + const char** data, + int data_count, + const char* msg, + void* user_data); + static void OnStateChange(stt_h stt, + stt_state_e previous, + stt_state_e current, + void* user_data); + static void OnError(stt_h stt, stt_error_e reason, void* user_data); + +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + Evas* evas_ = nullptr; +#endif + + stt_h handle_ = nullptr; + std::string language_; + bool is_lang_supported_ = false; + bool continuous_ = false; + const char* recognition_type_ = ""; + bool is_aborted_ = false; + base::Lock abort_lock_; +}; + +} // namespace content + +#endif // BROWSER_SPEECH_SPEECH_RECOGNIZER_IMPL_TIZEN_ diff --git a/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc new file mode 100644 index 0000000..8435e66 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc @@ -0,0 +1,37 @@ +// Copyright 2016 Samsung Electronics Inc. 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/speech/tizen_speech_recognition_manager_delegate.h" + +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" + +#if BUILDFLAG(IS_TIZEN_TV) +#include "tizen_src/ewk/efl_integration/common/application_type.h" +#endif + +namespace content { + +void TizenSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( + int session_id, + base::OnceCallback callback) { + // For tizen, we expect speech recognition to happen when requested. + + // Therefore we simply authorize it by calling back with is_allowed=true. The + // first parameter, ask_user, is set to false because we don't want to prompt + // the user for permission with an infobar. + + // In browser, a pop-up for permission to use microphone will show up. + // In web app, however, the user agrees on the access to microphone + // when the app is installed on device. So the pop-up will not show up. +#if BUILDFLAG(IS_TIZEN_TV) && defined(WRT_BRINGUP) + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), IsTIZENWRT(), false)); +#else + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false, true)); +#endif +} + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h new file mode 100644 index 0000000..6ac79bb --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h @@ -0,0 +1,41 @@ +// Copyright 2016 Samsung Electronics Inc. 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_SPEECH_TIZEN_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ +#define CONTENT_BROWSER_SPEECH_TIZEN_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ + +#include "base/bind.h" +#include "content/public/browser/speech_recognition_manager_delegate.h" + +namespace content { + +class SpeechRecognitionEventListener; +// This delegate is used by the speech recognition manager to +// check for permission to record audio. For tizen, we always authorize +// speech recognition. +class TizenSpeechRecognitionManagerDelegate + : public SpeechRecognitionManagerDelegate { + public: + TizenSpeechRecognitionManagerDelegate() {} + ~TizenSpeechRecognitionManagerDelegate() override {} + + private: + TizenSpeechRecognitionManagerDelegate( + const TizenSpeechRecognitionManagerDelegate&) = delete; + TizenSpeechRecognitionManagerDelegate& operator=( + const TizenSpeechRecognitionManagerDelegate&) = delete; + + void CheckRecognitionIsAllowed( + int session_id, + base::OnceCallback callback) + override; + SpeechRecognitionEventListener* GetEventListener() override { + return nullptr; + } + bool FilterProfanities(int render_process_id) override { return false; } +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SPEECH_TIZEN_SPEECH_RECOGNITION_MANAGER_DELEGATE_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 7b36d0f..23882ee 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -41,6 +41,10 @@ #include "private/ewk_notification_private.h" +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +#include "content/browser/speech/tizen_speech_recognition_manager_delegate.h" +#endif + using web_contents_utils::WebContentsFromFrameID; using web_contents_utils::WebContentsFromViewID; using web_contents_utils::WebViewFromWebContents; @@ -250,6 +254,13 @@ bool ContentBrowserClientEfl::HasErrorPage(int http_status_code) { error_page::Error::kHttpErrorDomain, http_status_code); } +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +SpeechRecognitionManagerDelegate* +ContentBrowserClientEfl::CreateSpeechRecognitionManagerDelegate() { + return new TizenSpeechRecognitionManagerDelegate(); +} +#endif + 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 cef8cb6..7b3f8f1 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.h +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.h @@ -21,6 +21,11 @@ namespace content { class BrowserMainPartsEfl; class NotificationControllerEfl; class SharedURLLoaderFactoryEfl; + +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +class SpeechRecognitionManagerDelegate; +#endif + class WebContents; class WebContentsView; @@ -59,6 +64,11 @@ class ContentBrowserClientEfl : public ContentBrowserClient { bool opener_suppressed, bool* no_javascript_access) override; +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) + SpeechRecognitionManagerDelegate* CreateSpeechRecognitionManagerDelegate() + override; +#endif + scoped_refptr CreateQuotaPermissionContext() override; bool HasErrorPage(int http_status_code) override; -- 2.7.4 From eb1cfd8dd1dec8e0c312d1245ac19d51935c81ad Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Tue, 24 Jan 2023 12:15:06 +0530 Subject: [PATCH 15/16] [M108 Migration][API] Introduce AddJavascriptInterface for Tizen Introduces AddJavascriptInterface for tizen, adds logs for debugging and support for posting blob type data type when using custom JS msg handler. Additionally, on M108, due to lot of upstream changes in base/values.{h,cc} prototypes, this patch fixes many build errors with respect to conversion of JS types (list, blob, dict etc) to Native types. Reference: https://review.tizen.org/gerrit/273935 Change-Id: Id18d8756919c3730ad991ab2a2ea02f91d64131f Signed-off-by: Gajendra N --- .../renderer_host/render_frame_host_impl.cc | 1 + ipc/ipc_message_start.h | 1 + .../core/frame/local_frame_mojo_handler.cc | 1 + tizen_src/ewk/efl_integration/BUILD.gn | 21 ++ .../gin_native_bound_object.cc | 43 +++ .../javascript_interface/gin_native_bound_object.h | 63 ++++ .../gin_native_bridge_dispatcher_host.cc | 381 +++++++++++++++++++++ .../gin_native_bridge_dispatcher_host.h | 98 ++++++ .../gin_native_bridge_message_filter.cc | 137 ++++++++ .../gin_native_bridge_message_filter.h | 98 ++++++ .../common/gin_native_bridge_errors.cc | 39 +++ .../common/gin_native_bridge_errors.h | 31 ++ .../common/gin_native_bridge_messages.h | 60 ++++ .../common/gin_native_bridge_value.cc | 105 ++++++ .../common/gin_native_bridge_value.h | 56 +++ .../efl_integration/common/message_generator_ewk.h | 3 +- tizen_src/ewk/efl_integration/eweb_view.cc | 31 +- tizen_src/ewk/efl_integration/eweb_view.h | 13 + tizen_src/ewk/efl_integration/public/ewk_view.cc | 39 +++ .../renderer/content_renderer_client_efl.cc | 3 + .../renderer/gin_native_bridge_dispatcher.cc | 120 +++++++ .../renderer/gin_native_bridge_dispatcher.h | 77 +++++ .../renderer/gin_native_bridge_object.cc | 124 +++++++ .../renderer/gin_native_bridge_object.h | 74 ++++ .../renderer/gin_native_bridge_value_converter.cc | 37 ++ .../renderer/gin_native_bridge_value_converter.h | 36 ++ .../gin_native_function_invocation_helper.cc | 108 ++++++ .../gin_native_function_invocation_helper.h | 42 +++ 28 files changed, 1833 insertions(+), 9 deletions(-) create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index c735f4a..a614089 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -2326,6 +2326,7 @@ void RenderFrameHostImpl::ForEachRenderFrameHostImpl( base::FunctionRef on_frame, bool include_speculative) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + LOG(INFO) << __FUNCTION__; if (!include_speculative && (lifecycle_state() == LifecycleStateImpl::kSpeculative || diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h index 8c91037..7758a5f 100644 --- a/ipc/ipc_message_start.h +++ b/ipc/ipc_message_start.h @@ -27,6 +27,7 @@ enum IPCMessageStart { TtsMsgStart, #endif ExtensionWorkerMsgStart, + GinNativeBridgeMsgStart, LastIPCMsgStart // Must come last. }; diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index 4716b95..4dd8501 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc @@ -943,6 +943,7 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestForTests( bool resolve_promises, int32_t world_id, JavaScriptExecuteRequestForTestsCallback callback) { + LOG(INFO) << __FUNCTION__; TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests", TRACE_EVENT_SCOPE_THREAD); diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index c04d0c6..bfbb46a 100755 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -313,6 +313,12 @@ shared_library("chromium-ewk") { "browser/input_picker/color_chooser_efl.h", "browser/input_picker/input_picker.cc", "browser/input_picker/input_picker.h", + "browser/javascript_interface/gin_native_bound_object.cc", + "browser/javascript_interface/gin_native_bound_object.h", + "browser/javascript_interface/gin_native_bridge_dispatcher_host.cc", + "browser/javascript_interface/gin_native_bridge_dispatcher_host.h", + "browser/javascript_interface/gin_native_bridge_message_filter.cc", + "browser/javascript_interface/gin_native_bridge_message_filter.h", "browser/network_service/browser_url_loader_throttle_efl.cc", "browser/network_service/browser_url_loader_throttle_efl.h", "browser/notification/notification_controller_efl.cc", @@ -345,6 +351,11 @@ shared_library("chromium-ewk") { "common/content_switches_efl.cc", "common/content_switches_efl.h", "common/editing_messages.h", + "common/gin_native_bridge_errors.cc", + "common/gin_native_bridge_errors.h", + "common/gin_native_bridge_messages.h", + "common/gin_native_bridge_value.cc", + "common/gin_native_bridge_value.h", "common/hit_test_params.h", "common/message_generator_ewk.cc", "common/message_generator_ewk.h", @@ -549,6 +560,16 @@ shared_library("chromium-ewk") { "renderer/content_renderer_client_efl.h", "renderer/content_settings_client_efl.cc", "renderer/content_settings_client_efl.h", + "renderer/gin_native_bridge_dispatcher.cc", + "renderer/gin_native_bridge_dispatcher.h", + "renderer/gin_native_bridge_object.cc", + "renderer/gin_native_bridge_object.h", + "renderer/gin_native_bridge_value_converter.cc", + "renderer/gin_native_bridge_value_converter.h", + "renderer/gin_native_function_invocation_helper.cc", + "renderer/gin_native_function_invocation_helper.h", + "renderer/plugins/plugin_placeholder_efl.cc", + "renderer/plugins/plugin_placeholder_efl.h", "renderer/print_web_view_helper_efl.cc", "renderer/print_web_view_helper_efl.h", "renderer/render_frame_observer_efl.cc", diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc new file mode 100644 index 0000000..a16ee7a2 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc @@ -0,0 +1,43 @@ +// Copyright 2017 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/javascript_interface/gin_native_bound_object.h" + +namespace content { + +GinNativeBoundObject::GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name) + : obj_(obj), callback_(callback), name_(name), names_count_(0) {} + +GinNativeBoundObject::GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + const std::set& holders) + : obj_(obj), + callback_(callback), + name_(name), + names_count_(0), + holders_(holders) {} + +// static +GinNativeBoundObject* GinNativeBoundObject::CreateNamed( + Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name) { + return new GinNativeBoundObject(obj, callback, name); +} + +// static +GinNativeBoundObject* GinNativeBoundObject::CreateTransient( + Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + int32_t holder) { + std::set holders; + holders.insert(holder); + return new GinNativeBoundObject(obj, callback, name, holders); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h new file mode 100644 index 0000000..d95658f --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h @@ -0,0 +1,63 @@ +// Copyright 2017 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_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BOUND_OBJECT_H_ +#define EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BOUND_OBJECT_H_ + +#include +#include + +#include +#include + +#include "base/memory/ref_counted.h" +#include "public/ewk_view.h" + +namespace content { + +class GinNativeBoundObject + : public base::RefCountedThreadSafe { + public: + typedef int32_t ObjectID; + static GinNativeBoundObject* CreateNamed(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name); + static GinNativeBoundObject* CreateTransient( + Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + int32_t holder); + void AddName() { ++names_count_; } + void RemoveName() { --names_count_; } + Evas_Object* GetView() const { return obj_; } + Ewk_View_Script_Message_Cb CallBack() const { return callback_; } + const char* Name() const { return name_.c_str(); } + + private: + friend class base::RefCountedThreadSafe; + GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name); + GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + const std::set& holders); + ~GinNativeBoundObject(){}; + + GinNativeBoundObject(const GinNativeBoundObject&) = delete; + GinNativeBoundObject& operator=(const GinNativeBoundObject&) = delete; + + Evas_Object* obj_; + Ewk_View_Script_Message_Cb callback_; + std::string name_; + + // An object must be kept in retained_object_set_ either if it has + // names or if it has a non-empty holders set. + int names_count_; + std::set holders_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BOUND_OBJECT_H_ diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc new file mode 100644 index 0000000..145925c --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc @@ -0,0 +1,381 @@ +// Copyright 2017 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/javascript_interface/gin_native_bridge_dispatcher_host.h" + +#include "base/logging.h" +#include "base/task/task_runner_util.h" +#include "browser/javascript_interface/gin_native_bridge_message_filter.h" +#include "common/gin_native_bridge_messages.h" +#include "common/gin_native_bridge_value.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "ipc/ipc_message_utils.h" + +namespace content { + +GinNativeBridgeDispatcherHost::GinNativeBridgeDispatcherHost( + WebContents* web_contents) + : WebContentsObserver(web_contents), next_object_id_(1) {} + +GinNativeBridgeDispatcherHost::~GinNativeBridgeDispatcherHost() {} + +void GinNativeBridgeDispatcherHost::InstallFilterAndRegisterAllRoutingIds() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!web_contents()->GetPrimaryMainFrame()->GetProcess()->GetChannel()) { + return; + } + + web_contents()->GetPrimaryMainFrame()->ForEachRenderFrameHost( + [this](RenderFrameHostImpl* frame) { + auto filter = GinNativeBridgeMessageFilter::FromHost(this, true); + filter->AddRoutingIdForHost(this, frame); + }); +} + +void GinNativeBridgeDispatcherHost::RenderFrameCreated( + RenderFrameHost* render_frame_host) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (auto filter = GinNativeBridgeMessageFilter::FromHost(this, false)) { + filter->AddRoutingIdForHost( + this, static_cast(render_frame_host)); + } else { + InstallFilterAndRegisterAllRoutingIds(); + } + for (NamedObjectMap::const_iterator iter = named_objects_.begin(); + iter != named_objects_.end(); ++iter) { + render_frame_host->Send(new GinNativeBridgeMsg_AddNamedObject( + render_frame_host->GetRoutingID(), iter->first, iter->second)); + } +} + +void GinNativeBridgeDispatcherHost::WebContentsDestroyed() { + scoped_refptr filter = + GinNativeBridgeMessageFilter::FromHost(this, false); + if (filter) + filter->RemoveHost(this); +} + +WebContentsImpl* GinNativeBridgeDispatcherHost::web_contents() const { + return static_cast(WebContentsObserver::web_contents()); +} + +bool GinNativeBridgeDispatcherHost::AddNamedObject( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name) { + LOG(INFO) << __FUNCTION__; + DCHECK_CURRENTLY_ON(BrowserThread::UI); + GinNativeBoundObject::ObjectID object_id; + NamedObjectMap::iterator iter = named_objects_.find(name); + if (iter != named_objects_.end()) + return false; + + object_id = AddObject(view, callback, name, true, 0); + named_objects_[name] = object_id; + + InstallFilterAndRegisterAllRoutingIds(); + + web_contents() + ->GetPrimaryMainFrame() + ->ForEachRenderFrameHostIncludingSpeculative( + [&name, object_id](RenderFrameHostImpl* render_frame_host) { + render_frame_host->Send(new GinNativeBridgeMsg_AddNamedObject( + render_frame_host->GetRoutingID(), name, object_id)); + }); + + return true; +} + +void GinNativeBridgeDispatcherHost::RemoveNamedObject(const std::string& name) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + NamedObjectMap::iterator iter = named_objects_.find(name); + if (iter == named_objects_.end()) + return; + + // |name| may come from |named_objects_|. Make a copy of name so that if + // |name| is from |named_objects_| it'll be valid after the remove below. + const std::string copied_name(name); + { + base::AutoLock locker(objects_lock_); + objects_[iter->second]->RemoveName(); + } + named_objects_.erase(iter); + + // As the object isn't going to be removed from the JavaScript side until the + // next page reload, calls to it must still work, thus we should continue to + // hold it. All the transient objects and removed named objects will be purged + // during the cleansing caused by DocumentAvailableInMainFrame event. + web_contents() + ->GetPrimaryMainFrame() + ->ForEachRenderFrameHostIncludingSpeculative( + [&copied_name](RenderFrameHostImpl* render_frame_host) { + render_frame_host->Send(new GinNativeBridgeMsg_RemoveNamedObject( + render_frame_host->GetRoutingID(), copied_name)); + }); +} + +GinNativeBoundObject::ObjectID GinNativeBridgeDispatcherHost::AddObject( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + bool is_named, + int32_t holder) { + scoped_refptr new_object = + is_named + ? GinNativeBoundObject::CreateNamed(view, callback, name) + : GinNativeBoundObject::CreateTransient(view, callback, name, holder); + // Note that we are abusing the fact that StaticAtomicSequenceNumber + // uses Atomic32 as a counter, so it is guaranteed that it will not + // overflow our int32_t IDs. IDs start from 1. + GinNativeBoundObject::ObjectID object_id = next_object_id_++; + { + base::AutoLock locker(objects_lock_); + objects_[object_id] = new_object; + } + return object_id; +} + +void GinNativeBridgeDispatcherHost::PrimaryMainDocumentElementAvailable() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // Called when the window object has been cleared in the main frame. + // That means, all sub-frames have also been cleared, so only named + // objects survived. + + NOTIMPLEMENTED(); +} + +scoped_refptr GinNativeBridgeDispatcherHost::FindObject( + GinNativeBoundObject::ObjectID object_id) { + // Can be called on any thread. + base::AutoLock locker(objects_lock_); + auto iter = objects_.find(object_id); + if (iter != objects_.end()) + return iter->second; + LOG(ERROR) << "WebView: Unknown object: " << object_id; + return nullptr; +} + +void GinNativeBridgeDispatcherHost::OnHasMethod( + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result) { + scoped_refptr object = FindObject(object_id); + + *result = (object.get()) ? true : false; +} + +void GinNativeBridgeDispatcherHost::OnInvokeMethod( + int routing_id, + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* wrapped_result, + content::GinNativeBridgeError* error_code) { + LOG(INFO) << __FUNCTION__; + DCHECK(routing_id != MSG_ROUTING_NONE); + if (method_name != "postMessage") { + LOG(ERROR) << __FUNCTION__ << " : kGinNativeBridgeMethodNotFound"; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeMethodNotFound; + return; + } + + scoped_refptr object = FindObject(object_id); + if (!object.get()) { + LOG(ERROR) << "WebView: Unknown object: " << object_id; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeUnknownObjectId; + return; + } + + Ewk_Script_Message msg; + msg.name = object->Name(); + + if (named_objects_.find(msg.name) == named_objects_.end()) { + LOG(ERROR) << __FUNCTION__ << " : kGinNativeBridgeMessageNameIsWrong"; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeMessageNameIsWrong; + return; + } + + JavaScript_Values values; + values.bool_buf = EINA_FALSE; + values.int_buf = -1; + values.double_buf = -1; + values.str_buf = ""; + + bool bool_buf = false; + bool should_free = false; + + base::Value::List::const_iterator iter = arguments.begin(); + + switch (iter->type()) { + case base::Value::Type::BOOLEAN: + bool_buf = iter->GetBool(); + (bool_buf) ? values.bool_buf = EINA_TRUE : values.bool_buf = EINA_FALSE; + msg.body = &values.bool_buf; + break; + case base::Value::Type::INTEGER: + values.int_buf = iter->GetInt(); + msg.body = &values.int_buf; + break; + case base::Value::Type::DOUBLE: + values.double_buf = iter->GetDouble(); + msg.body = &values.double_buf; + break; + case base::Value::Type::STRING: + values.str_buf = iter->GetString(); + msg.body = strdup(values.str_buf.c_str()); + should_free = true; + break; + case base::Value::Type::DICTIONARY: + values.str_buf = ConvertDictionaryValueToString(iter->GetDict()); + msg.body = strdup(values.str_buf.c_str()); + should_free = true; + break; + case base::Value::Type::LIST: + values.str_buf = ConvertListValueToString(iter->GetList()); + msg.body = strdup(values.str_buf.c_str()); + should_free = true; + break; + case base::Value::Type::BINARY: + values.str_buf.assign(iter->GetBlob().begin(), iter->GetBlob().end()); + msg.body = (void*)values.str_buf.data(); + break; + default: + LOG(ERROR) << __FUNCTION__ << " : kGinNativeBridgeNotSupportedTypes"; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeNotSupportedTypes; + return; + } + + object->CallBack()(object->GetView(), msg); + wrapped_result->Append(base::Value::FromUniquePtrValue( + GinNativeBridgeValue::CreateObjectIDValue(object_id))); + + if (should_free) + free(msg.body); + + return; +} + +std::string GinNativeBridgeDispatcherHost::ConvertListValueToString( + const base::Value::List& list) { + bool init = false; + bool bool_buf = false; + int int_buf = -1; + double double_buf = -1; + std::string str_buf = ""; + std::string token = ""; + + str_buf = "["; + for (base::Value::List::const_iterator iter_list = list.begin(); + iter_list != list.end(); ++iter_list) { + if (init) + str_buf += ","; + + switch (iter_list->type()) { + case base::Value::Type::BOOLEAN: + bool_buf = false; + bool_buf = iter_list->GetBool(); + (bool_buf) ? str_buf += "true" : str_buf += "false"; + break; + case base::Value::Type::INTEGER: + int_buf = -1; + int_buf = iter_list->GetInt(); + str_buf += std::to_string(int_buf); + break; + case base::Value::Type::DOUBLE: + double_buf = -1; + double_buf = iter_list->GetDouble(); + str_buf += std::to_string(double_buf); + break; + case base::Value::Type::STRING: + token = ""; + token = iter_list->GetString(); + str_buf += "\""; + str_buf += token; + str_buf += "\""; + break; + case base::Value::Type::DICTIONARY: + str_buf = ConvertDictionaryValueToString(iter_list->GetDict()); + break; + case base::Value::Type::LIST: + str_buf += ConvertListValueToString(iter_list->GetList()); + break; + default: + str_buf += "\"\""; + break; + } + init = true; + } + str_buf += "]"; + + return str_buf; +} + +std::string GinNativeBridgeDispatcherHost::ConvertDictionaryValueToString( + const base::Value::Dict& dict) { + bool init = false; + bool bool_buf = false; + int int_buf = -1; + double double_buf = -1; + std::string str_buf = ""; + std::string token = ""; + + str_buf = "{"; + for (const auto item : dict) { + if (init) + str_buf += ","; + str_buf += " \""; + str_buf += item.first; + str_buf += "\": "; + + switch (item.second.type()) { + case base::Value::Type::BOOLEAN: + bool_buf = false; + bool_buf = item.second.GetBool(); + (bool_buf) ? str_buf += "true" : str_buf += "false"; + break; + case base::Value::Type::INTEGER: + int_buf = -1; + int_buf = item.second.GetInt(); + str_buf += std::to_string(int_buf); + break; + case base::Value::Type::DOUBLE: + double_buf = -1; + double_buf = item.second.GetDouble(); + str_buf += std::to_string(double_buf); + break; + case base::Value::Type::STRING: + token = ""; + token = item.second.GetString(); + str_buf += "\""; + str_buf += token; + str_buf += "\""; + break; + case base::Value::Type::DICTIONARY: + str_buf += ConvertDictionaryValueToString(item.second.GetDict()); + break; + case base::Value::Type::LIST: + str_buf += ConvertListValueToString(item.second.GetList()); + break; + default: + str_buf += "\"\""; + break; + } + init = true; + } + str_buf += "}"; + + return str_buf; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h new file mode 100644 index 0000000..43df6ef --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h @@ -0,0 +1,98 @@ +// Copyright 2017 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_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_DISPATCHER_HOST_H_ +#define EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_DISPATCHER_HOST_H_ + +#include +#include +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "browser/javascript_interface/gin_native_bound_object.h" +#include "common/gin_native_bridge_errors.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/web_contents_observer.h" +#include "public/ewk_view.h" + +namespace content { + +class GinNativeBridgeDispatcherHost + : public base::RefCountedThreadSafe, + public WebContentsObserver { + public: + explicit GinNativeBridgeDispatcherHost(WebContents* web_contents); + ~GinNativeBridgeDispatcherHost() override; + + GinNativeBridgeDispatcherHost(const GinNativeBridgeDispatcherHost&) = delete; + GinNativeBridgeDispatcherHost& operator=( + const GinNativeBridgeDispatcherHost&) = delete; + + // WebContentsObserver + void RenderFrameCreated(RenderFrameHost* render_frame_host) override; + void WebContentsDestroyed() override; + void PrimaryMainDocumentElementAvailable() override; + + bool AddNamedObject(Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name); + void RemoveNamedObject(const std::string& name); + void OnHasMethod(GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result); + + void OnInvokeMethod(int routing_id, + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* result, + content::GinNativeBridgeError* error_code); + WebContentsImpl* web_contents() const; + + private: + friend class base::RefCountedThreadSafe; + typedef std::map> + ObjectMap; + + // Run on the UI thread. + void InstallFilterAndRegisterAllRoutingIds(); + + bool FindObjectId(); + GinNativeBoundObject::ObjectID AddObject(Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + bool is_named, + int32_t holder); + scoped_refptr FindObject( + GinNativeBoundObject::ObjectID object_id); + + std::string ConvertListValueToString(const base::Value::List& list); + + std::string ConvertDictionaryValueToString(const base::Value::Dict& dict); + + typedef std::map NamedObjectMap; + NamedObjectMap named_objects_; + + GinNativeBoundObject::ObjectID next_object_id_; + + // Note that retained_object_set_ does not need to be consistent + // with objects_. + ObjectMap objects_; + base::Lock objects_lock_; + + struct _JavaScript_Values { + Eina_Bool bool_buf; /**< Buffer for boolean */ + int int_buf; /**< Buffer for integer */ + double double_buf; /**< Buffer for double */ + std::string str_buf; /**< Buffer for string */ + }; + typedef struct _JavaScript_Values JavaScript_Values; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_DISPATCHER_HOST_H_ diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc new file mode 100644 index 0000000..2eacac2 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc @@ -0,0 +1,137 @@ +// Copyright 2017 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/javascript_interface/gin_native_bridge_message_filter.h" + +#include "base/auto_reset.h" +#include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h" +#include "common/gin_native_bridge_messages.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" + +namespace { +const char kGinNativeBridgeMessageFilterKey[] = "GinNativeBridgeMessageFilter"; +} // namespace + +namespace content { + +GinNativeBridgeMessageFilter::GinNativeBridgeMessageFilter() + : BrowserMessageFilter(GinNativeBridgeMsgStart), + current_routing_id_(MSG_ROUTING_NONE) {} + +GinNativeBridgeMessageFilter::~GinNativeBridgeMessageFilter() {} + +void GinNativeBridgeMessageFilter::OnDestruct() const { + if (BrowserThread::CurrentlyOn(BrowserThread::UI)) + delete this; + else + BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); +} + +bool GinNativeBridgeMessageFilter::OnMessageReceived( + const IPC::Message& message) { + base::AutoReset routing_id(¤t_routing_id_, + message.routing_id()); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GinNativeBridgeMessageFilter, message) + IPC_MESSAGE_HANDLER(GinNativeBridgeHostMsg_HasMethod, OnHasMethod) + IPC_MESSAGE_HANDLER(GinNativeBridgeHostMsg_InvokeMethod, OnInvokeMethod) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +scoped_refptr +GinNativeBridgeMessageFilter::OverrideTaskRunnerForMessage( + const IPC::Message& message) { + // As the filter is only invoked for the messages of the particular class, + // we can return the task runner unconfitionally. + return nullptr; +} + +void GinNativeBridgeMessageFilter::AddRoutingIdForHost( + GinNativeBridgeDispatcherHost* host, + RenderFrameHostImpl* render_frame_host) { + base::AutoLock locker(hosts_lock_); + hosts_[render_frame_host->GetRoutingID()] = host; +} + +void GinNativeBridgeMessageFilter::RemoveHost( + GinNativeBridgeDispatcherHost* host) { + base::AutoLock locker(hosts_lock_); + auto iter = hosts_.begin(); + while (iter != hosts_.end()) { + if (iter->second == host) + hosts_.erase(iter++); + else + ++iter; + } +} + +// static +scoped_refptr +GinNativeBridgeMessageFilter::FromHost(GinNativeBridgeDispatcherHost* host, + bool create_if_not_exists) { + RenderProcessHost* rph = + host->web_contents()->GetPrimaryMainFrame()->GetProcess(); + scoped_refptr filter = + base::UserDataAdapter::Get( + rph, kGinNativeBridgeMessageFilterKey); + if (!filter && create_if_not_exists) { + filter = new GinNativeBridgeMessageFilter(); + rph->AddFilter(filter.get()); + rph->SetUserData( + kGinNativeBridgeMessageFilterKey, + base::WrapUnique( + new base::UserDataAdapter( + filter.get()))); + } + return filter; +} + +GinNativeBridgeDispatcherHost* GinNativeBridgeMessageFilter::FindHost() { + base::AutoLock locker(hosts_lock_); + auto iter = hosts_.find(current_routing_id_); + if (iter != hosts_.end()) + return iter->second; + // This is usually OK -- we can receive messages form RenderFrames for + // which the corresponding host part has already been destroyed. That means, + // any references to Native objects that the host was holding were already + // released (with the death of ContentViewCore), so we can just drop such + // messages. + LOG(WARNING) << "WebView: Unknown frame routing id: " << current_routing_id_; + return nullptr; +} + +void GinNativeBridgeMessageFilter::OnHasMethod( + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result) { + GinNativeBridgeDispatcherHost* host = FindHost(); + if (host) + host->OnHasMethod(object_id, method_name, result); + else + *result = false; +} + +void GinNativeBridgeMessageFilter::OnInvokeMethod( + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* wrapped_result, + content::GinNativeBridgeError* error_code) { + LOG(INFO) << __FUNCTION__; + GinNativeBridgeDispatcherHost* host = FindHost(); + if (host) { + host->OnInvokeMethod(current_routing_id_, object_id, method_name, arguments, + wrapped_result, error_code); + } else { + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeRenderFrameDeleted; + } +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h new file mode 100644 index 0000000..dbb24c6 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h @@ -0,0 +1,98 @@ +// Copyright 2017 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_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_MESSAGE_FILTER_H_ +#define EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_MESSAGE_FILTER_H_ + +#include + +#include +#include +#include + +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "base/values.h" +#include "browser/javascript_interface/gin_native_bound_object.h" +#include "common/gin_native_bridge_errors.h" +#include "content/public/browser/browser_message_filter.h" + +namespace base { +class ListValue; +} + +namespace IPC { +class Message; +} + +namespace content { + +class GinNativeBridgeDispatcherHost; +class RenderFrameHostImpl; + +class GinNativeBridgeMessageFilter : public BrowserMessageFilter { + public: + // BrowserMessageFilter + void OnDestruct() const override; + bool OnMessageReceived(const IPC::Message& message) override; + scoped_refptr OverrideTaskRunnerForMessage( + const IPC::Message& message) override; + + // Called on the UI thread. + void AddRoutingIdForHost(GinNativeBridgeDispatcherHost* host, + RenderFrameHostImpl* render_frame_host); + void RemoveHost(GinNativeBridgeDispatcherHost* host); + + static scoped_refptr FromHost( + GinNativeBridgeDispatcherHost* host, + bool create_if_not_exists); + + private: + friend class BrowserThread; + friend class base::DeleteHelper; + + // WebView (who owns GinNativeBridgeDispatcherHost) outlives + // WebContents, and GinNativeBridgeDispatcherHost removes itself form the map + // on WebContents destruction, so there is no risk that the pointer would + // become stale. + // + // The filter keeps its own routing map of RenderFrames for two reasons: + // 1. Message dispatching must be done on the background thread, + // without resorting to the UI thread, which can be in fact currently + // blocked, waiting for an event from an injected Native object. + // 2. As RenderFrames pass away earlier than JavaScript wrappers, + // messages form the latter can arrive after the RenderFrame has been + // removed from the WebContent's routing table. + typedef std::map HostMap; + + GinNativeBridgeMessageFilter(); + ~GinNativeBridgeMessageFilter() override; + + GinNativeBridgeMessageFilter(const GinNativeBridgeMessageFilter&) = delete; + GinNativeBridgeMessageFilter& operator=(const GinNativeBridgeMessageFilter&) = + delete; + + // Called on the background thread. + GinNativeBridgeDispatcherHost* FindHost(); + void OnHasMethod(GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result); + void OnInvokeMethod(GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* result, + content::GinNativeBridgeError* error_code); + + // Accessed both from UI and background threads. + HostMap hosts_; + base::Lock hosts_lock_; + + // The routing id of the RenderFrameHost whose request we are processing. + // Used on the backgrount thread. + int32_t current_routing_id_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_MESSAGE_FILTER_H_ diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc new file mode 100644 index 0000000..dd8184a --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc @@ -0,0 +1,39 @@ +// Copyright 2017 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 "common/gin_native_bridge_errors.h" + +#include "base/notreached.h" + +namespace content { + +const char* GinNativeBridgeErrorToString(GinNativeBridgeError error) { + switch (error) { + case kGinNativeBridgeNoError: + return "No error"; + case kGinNativeBridgeUnknownObjectId: + return "Unknown Native object ID"; + case kGinNativeBridgeObjectIsGone: + return "Native object is gone"; + case kGinNativeBridgeMethodNotFound: + return "Method not found"; + case kGinNativeBridgeAccessToObjectGetClassIsBlocked: + return "Access to Object.getClass is blocked"; + case kGinNativeBridgeNativeExceptionRaised: + return "Native exception was raised during method invocation"; + case kGinNativeBridgeNonAssignableTypes: + return "The type of the object passed to the method is incompatible " + "with the type of method's argument"; + case kGinNativeBridgeRenderFrameDeleted: + return "RenderFrame has been deleted"; + case kGinNativeBridgeNotSupportedTypes: + return "This type is not supported"; + case kGinNativeBridgeMessageNameIsWrong: + return "Message name is wrong"; + } + NOTREACHED(); + return "Unknown error"; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h new file mode 100644 index 0000000..cee74ff --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h @@ -0,0 +1,31 @@ +// Copyright 2017 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_COMMON_GIN_NATIVE_BRIDGE_ERRORS_H_ +#define EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_ERRORS_H_ + +#include "content/common/content_export.h" + +namespace content { + +enum GinNativeBridgeError { + kGinNativeBridgeNoError = 0, + kGinNativeBridgeUnknownObjectId, + kGinNativeBridgeObjectIsGone, + kGinNativeBridgeMethodNotFound, + kGinNativeBridgeAccessToObjectGetClassIsBlocked, + kGinNativeBridgeNativeExceptionRaised, + kGinNativeBridgeNonAssignableTypes, + kGinNativeBridgeRenderFrameDeleted, + kGinNativeBridgeNotSupportedTypes, + kGinNativeBridgeMessageNameIsWrong, + kGinNativeBridgeErrorLast = kGinNativeBridgeRenderFrameDeleted +}; + +CONTENT_EXPORT const char* GinNativeBridgeErrorToString( + GinNativeBridgeError error); + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_ERRORS_H_ diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h b/tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h new file mode 100644 index 0000000..6f976df --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h @@ -0,0 +1,60 @@ +// Copyright 2017 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 +#include + +#include "common/gin_native_bridge_errors.h" +#include "content/common/content_export.h" +#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_message_start.h" + +#undef IPC_MESSAGE_EXPORT +#define IPC_MESSAGE_EXPORT CONTENT_EXPORT +#define IPC_MESSAGE_START GinNativeBridgeMsgStart + +// Messages for handling Java objects injected into JavaScript ----------------- + +IPC_ENUM_TRAITS_MAX_VALUE(content::GinNativeBridgeError, + content::kGinNativeBridgeErrorLast) + +// Sent from browser to renderer to add a Native object with the given name. +// Object IDs are generated on the browser side. +IPC_MESSAGE_ROUTED2(GinNativeBridgeMsg_AddNamedObject, + std::string /* name */, + int32_t /* object_id */) + +// Sent from browser to renderer to remove a Java object with the given name. +IPC_MESSAGE_ROUTED1(GinNativeBridgeMsg_RemoveNamedObject, + std::string /* name */) + +// Sent from renderer to browser to get information about methods of +// the given object. The query will only succeed if inspection of injected +// objects is enabled on the browser side. +IPC_SYNC_MESSAGE_ROUTED1_1(GinNativeBridgeHostMsg_GetMethods, + int32_t /* object_id */, + std::set /* returned_method_names */) + +// Sent from renderer to browser to find out, if an object has a method with +// the given name. +IPC_SYNC_MESSAGE_ROUTED2_1(GinNativeBridgeHostMsg_HasMethod, + int32_t /* object_id */, + std::string /* method_name */, + bool /* result */) + +// Sent from renderer to browser to invoke a method. Method arguments +// are chained into |arguments| list. base::Value::List is used for |result| as +// a container to work around immutability of base::Value. +// Empty result list indicates that an error has happened on the Native side +// (either bridge-induced error or an unhandled Native exception) and an +// exception must be thrown into JavaScript. |error_code| indicates the cause of +// the error. +// Some special value types that are not supported by base::Value are encoded +// as BinaryValues via GinNativeBridgeValue. +IPC_SYNC_MESSAGE_ROUTED3_2(GinNativeBridgeHostMsg_InvokeMethod, + int32_t /* object_id */, + std::string /* method_name */, + base::Value::List /* arguments */, + base::Value::List /* result */, + content::GinNativeBridgeError /* error_code */) diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc new file mode 100644 index 0000000..ab8e34a --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc @@ -0,0 +1,105 @@ +// Copyright 2017 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/common/gin_native_bridge_value.h" + +namespace content { + +namespace { +// The magic value is only used to prevent accidental attempts of reading +// GinJavaBridgeValue from a random BinaryValue. GinJavaBridgeValue is not +// intended for scenarios where with BinaryValues are being used for anything +// else than holding GinJavaBridgeValues. If a need for such scenario ever +// emerges, the best solution would be to extend GinJavaBridgeValue to be able +// to wrap raw BinaryValues. +const uint32_t kHeaderMagic = 0xBEEFCAFE; + +#pragma pack(push, 4) +struct Header : public base::Pickle::Header { + uint32_t magic; + int32_t type; +}; +#pragma pack(pop) +} // namespace + +// static +std::unique_ptr GinNativeBridgeValue::CreateObjectIDValue( + int32_t in_value) { + GinNativeBridgeValue gin_value(TYPE_OBJECT_ID); + gin_value.pickle_.WriteInt(in_value); + return gin_value.SerializeToValue(); +} + +// static +bool GinNativeBridgeValue::ContainsGinJavaBridgeValue( + const base::Value* value) { + if (!value->is_blob()) + return false; + const base::Value* binary_value = reinterpret_cast(value); + if (binary_value->GetBlob().size() < sizeof(Header)) + return false; + base::Pickle pickle((const char*)binary_value->GetBlob().data(), + binary_value->GetBlob().size()); + // Broken binary value: payload or header size is wrong + if (!pickle.data() || pickle.size() - pickle.payload_size() != sizeof(Header)) + return false; + Header* header = pickle.headerT
(); + return (header->magic == kHeaderMagic && header->type >= TYPE_FIRST_VALUE && + header->type < TYPE_LAST_VALUE); +} + +// static +std::unique_ptr GinNativeBridgeValue::FromValue( + const base::Value* value) { + return std::unique_ptr( + value->is_blob() ? new GinNativeBridgeValue( + reinterpret_cast(value)) + : NULL); +} + +GinNativeBridgeValue::Type GinNativeBridgeValue::GetType() const { + const Header* header = pickle_.headerT
(); + DCHECK(header->type >= TYPE_FIRST_VALUE && header->type < TYPE_LAST_VALUE); + return static_cast(header->type); +} + +bool GinNativeBridgeValue::IsType(Type type) const { + return GetType() == type; +} + +bool GinNativeBridgeValue::GetAsNonFinite(float* out_value) const { + if (GetType() != TYPE_NONFINITE) + return false; + + base::PickleIterator iter(pickle_); + return iter.ReadFloat(out_value); +} + +bool GinNativeBridgeValue::GetAsObjectID(int32_t* out_object_id) const { + if (GetType() != TYPE_OBJECT_ID) + return false; + + base::PickleIterator iter(pickle_); + return iter.ReadInt(out_object_id); +} + +GinNativeBridgeValue::GinNativeBridgeValue(Type type) + : pickle_(sizeof(Header)) { + Header* header = pickle_.headerT
(); + header->magic = kHeaderMagic; + header->type = type; +} + +GinNativeBridgeValue::GinNativeBridgeValue(const base::Value* value) + : pickle_((const char*)value->GetBlob().data(), value->GetBlob().size()) { + DCHECK(ContainsGinJavaBridgeValue(value)); +} + +std::unique_ptr GinNativeBridgeValue::SerializeToValue() { + return std::make_unique(base::Value::BlobStorage( + reinterpret_cast(pickle_.data()), + reinterpret_cast(pickle_.data()) + pickle_.size())); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h new file mode 100644 index 0000000..946293f9 --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h @@ -0,0 +1,56 @@ +// Copyright 2017 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_COMMON_GIN_NATIVE_BRIDGE_VALUE_H_ +#define EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_VALUE_H_ + +#include + +#include "base/pickle.h" +#include "base/values.h" +#include "content/common/content_export.h" + +namespace content { + +class GinNativeBridgeValue { + public: + enum Type { + TYPE_FIRST_VALUE = 0, + // JavaScript 'undefined' + TYPE_UNDEFINED = 0, + // JavaScript NaN and Infinity + TYPE_NONFINITE, + // Bridge Object ID + TYPE_OBJECT_ID, + TYPE_LAST_VALUE + }; + + CONTENT_EXPORT static std::unique_ptr CreateObjectIDValue( + int32_t in_value); + + // De-serialization + CONTENT_EXPORT static bool ContainsGinJavaBridgeValue( + const base::Value* value); + CONTENT_EXPORT static std::unique_ptr FromValue( + const base::Value* value); + CONTENT_EXPORT Type GetType() const; + CONTENT_EXPORT bool IsType(Type type) const; + CONTENT_EXPORT bool GetAsNonFinite(float* out_value) const; + CONTENT_EXPORT bool GetAsObjectID(int32_t* out_object_id) const; + + private: + explicit GinNativeBridgeValue(Type type); + explicit GinNativeBridgeValue(const base::Value* value); + + GinNativeBridgeValue(const GinNativeBridgeValue&) = delete; + GinNativeBridgeValue& operator=(const GinNativeBridgeValue&) = delete; + + std::unique_ptr SerializeToValue(); + + base::Pickle pickle_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_VALUE_H_ diff --git a/tizen_src/ewk/efl_integration/common/message_generator_ewk.h b/tizen_src/ewk/efl_integration/common/message_generator_ewk.h index db42330..f9760ba 100644 --- a/tizen_src/ewk/efl_integration/common/message_generator_ewk.h +++ b/tizen_src/ewk/efl_integration/common/message_generator_ewk.h @@ -5,5 +5,6 @@ // Multiply-included file, hence no include guard. // efl message generator -#include "common/render_messages_ewk.h" #include "common/editing_messages.h" +#include "common/gin_native_bridge_messages.h" +#include "common/render_messages_ewk.h" diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index a9f9686..449ac1b 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/pickle.h" #include "base/strings/utf_string_conversions.h" +#include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h" #include "browser/navigation_policy_handler_efl.h" #include "browser/quota_permission_context_efl.h" #include "browser/selectpicker/popup_menu_item.h" @@ -64,6 +65,7 @@ #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/display/screen.h" +#include "ui/events/event_switches.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/platform_window/platform_window_init_properties.h" @@ -290,6 +292,7 @@ EWebView::~EWebView() { if (context_->GetImpl()->browser_context()->IsOffTheRecord()) Ewk_Context::Delete(context_.get()); + gin_native_bridge_dispatcher_host_.reset(); } void EWebView::ReleasePopupMenuList() { @@ -332,6 +335,17 @@ Eina_Bool EWebView::HasFocus() const { return rwhva()->offscreen_helper()->HasFocus() ? EINA_TRUE : EINA_FALSE; } +Eina_Bool EWebView::AddJavaScriptMessageHandler( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + std::string name) { + if (!gin_native_bridge_dispatcher_host_) + return EINA_FALSE; + + return gin_native_bridge_dispatcher_host_->AddNamedObject(view, callback, + name); +} + bool EWebView::CreateNewWindow( content::WebContentsEflDelegate::WebContentsCreateCallback cb) { create_new_window_web_contents_cb_ = cb; @@ -734,18 +748,17 @@ void JavaScriptComplete(JavaScriptCallbackDetails* script_callback_data, bool EWebView::ExecuteJavaScript(const char* script, Ewk_View_Script_Execute_Callback callback, void* userdata) { - if (!script) - return false; - - if (!web_contents_delegate_) // question, can I remove this check? - return false; - - if (!web_contents_) + LOG(INFO) << __FUNCTION__; + if (!web_contents_) { + LOG(ERROR) << __FUNCTION__ << "web_contents_ is null"; return false; + } RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame(); - if (!render_frame_host) + if (!render_frame_host) { + LOG(ERROR) << __FUNCTION__ << " render_frame_host is null"; return false; + } // Note: M37. Execute JavaScript, |script| with // |RenderFrameHost::ExecuteJavaScript|. @@ -2264,6 +2277,8 @@ void EWebView::InitializeContent() { new _Ewk_Back_Forward_List(web_contents_->GetController())); permission_popup_manager_.reset(new PermissionPopupManager(evas_object_)); + gin_native_bridge_dispatcher_host_.reset( + new content::GinNativeBridgeDispatcherHost(web_contents_.get())); native_view_ = static_cast(web_contents_.get())->GetEflNativeView(); diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 93a0b53..bb7357b 100755 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -71,6 +71,7 @@ class WebContentsViewAura; class ContextMenuControllerEfl; class PopupControllerEfl; class InputPicker; +class GinNativeBridgeDispatcherHost; } class ErrorParams; @@ -475,6 +476,14 @@ class EWebView { return context_menu_.get(); } void ResetContextMenuController(); + Eina_Bool AddJavaScriptMessageHandler(Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + std::string name); + + content::GinNativeBridgeDispatcherHost* GetGinNativeBridgeDispatcherHost() + const { + return gin_native_bridge_dispatcher_host_.get(); + } /// ---- Event handling bool HandleShow(); @@ -623,6 +632,10 @@ class EWebView { std::unique_ptr permission_popup_manager_; std::unique_ptr scroll_detector_; + // Manages injecting native objects. + std::unique_ptr + gin_native_bridge_dispatcher_host_; + #if BUILDFLAG(IS_TIZEN) blink::mojom::FileChooserParams::Mode filechooser_mode_; #endif diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 40d8e79..9392ea8 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -21,6 +21,7 @@ #include "ewk_view_product.h" #include +#include #include "authentication_challenge_popup.h" #include "content/public/browser/navigation_controller.h" @@ -1318,6 +1319,44 @@ Eina_Bool ewk_view_tts_mode_set(Evas_Object* view, ewk_tts_mode tts_mode) { return false; } +Eina_Bool ewk_view_javascript_message_handler_add( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const char* name) { + EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); + return impl->AddJavaScriptMessageHandler(view, callback, std::string(name)); +} + +Eina_Bool ewk_view_evaluate_javascript(Evas_Object* view, + const char* name, + const char* result) { + EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(result, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); + + std::string function(name); + std::string data(result); + std::string pattern("\n"); + std::string replace("
"); + std::string::size_type pos = 0; + std::string::size_type offset = 0; + while ((pos = data.find(pattern, offset)) != std::string::npos) { + data.replace(data.begin() + pos, data.begin() + pos + pattern.size(), + replace); + offset = pos + replace.size(); + } + + // For JSON Object or Array. + if (result[0] == '{' || result[0] == '[') { + data = "javascript:" + function + "(JSON.parse('" + data + "'))"; + } else { + data = "javascript:" + function + "('" + data + "')"; + } + + return impl->ExecuteJavaScript(data.c_str(), NULL, 0); +} + void ewk_view_authentication_callback_set( Evas_Object* ewk_view, Ewk_View_Authentication_Callback callback, 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 eb24496..aaf4c52 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 @@ -26,6 +26,7 @@ #if !defined(EWK_BRINGUP) // FIXME: m94 bringup #include "renderer/editorclient_agent.h" #endif +#include "renderer/gin_native_bridge_dispatcher.h" #include "renderer/plugins/plugin_placeholder_efl.h" #include "renderer/render_frame_observer_efl.h" #include "third_party/blink/public/platform/url_conversion.h" @@ -147,6 +148,8 @@ void ContentRendererClientEfl::RenderThreadStarted() { void ContentRendererClientEfl::RenderFrameCreated(content::RenderFrame* render_frame) { new content::RenderFrameObserverEfl(render_frame); new content::ContentSettingsClientEfl(render_frame); + // Deletes itself when render_frame is destroyed. + new content::GinNativeBridgeDispatcher(render_frame); #if defined(TIZEN_AUTOFILL_SUPPORT) PasswordAutofillAgent* password_autofill_agent = diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc new file mode 100644 index 0000000..1b95734 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc @@ -0,0 +1,120 @@ +// Copyright 2017 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 "renderer/gin_native_bridge_dispatcher.h" + +#include "base/auto_reset.h" +#include "common/gin_native_bridge_messages.h" +#include "content/public/renderer/render_frame.h" +#include "renderer/gin_native_bridge_object.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_view.h" + +namespace content { + +GinNativeBridgeDispatcher::GinNativeBridgeDispatcher(RenderFrame* render_frame) + : RenderFrameObserver(render_frame), + inside_did_clear_window_object_(false) {} + +GinNativeBridgeDispatcher::~GinNativeBridgeDispatcher() {} + +bool GinNativeBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GinNativeBridgeDispatcher, msg) + IPC_MESSAGE_HANDLER(GinNativeBridgeMsg_AddNamedObject, OnAddNamedObject) + IPC_MESSAGE_HANDLER(GinNativeBridgeMsg_RemoveNamedObject, + OnRemoveNamedObject) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void GinNativeBridgeDispatcher::DidClearWindowObject() { + // Accessing window object when adding properties to it may trigger + // a nested call to DidClearWindowObject. + if (inside_did_clear_window_object_) + return; + base::AutoReset flag_entry(&inside_did_clear_window_object_, true); + for (NamedObjectMap::const_iterator iter = named_objects_.begin(); + iter != named_objects_.end(); ++iter) { + // Always create a new GinNativeBridgeObject, so we don't pull any of the V8 + // wrapper's custom properties into the context of the page we have + // navigated to. The old GinNativeBridgeObject will be automatically + // deleted after its wrapper will be collected. + // On the browser side, we ignore wrapper deletion events for named objects, + // as they are only removed upon embedder's request (RemoveNamedObject). + if (objects_.Lookup(iter->second)) + objects_.Remove(iter->second); + GinNativeBridgeObject* object = GinNativeBridgeObject::InjectNamed( + render_frame()->GetWebFrame(), AsWeakPtr(), iter->first, iter->second); + if (object) { + objects_.AddWithID(object, iter->second); + } else { + // FIXME: Inform the host about wrapper creation failure. + } + } +} + +void GinNativeBridgeDispatcher::OnAddNamedObject(const std::string& name, + ObjectID object_id) { + LOG(INFO) << __FUNCTION__; + // Added objects only become available after page reload, so here they + // are only added into the internal map. + named_objects_.insert(std::make_pair(name, object_id)); +} + +void GinNativeBridgeDispatcher::OnRemoveNamedObject(const std::string& name) { + // Removal becomes in effect on next reload. We simply removing the entry + // from the map here. + NamedObjectMap::iterator iter = named_objects_.find(name); + DCHECK(iter != named_objects_.end()); + named_objects_.erase(iter); +} + +void GinNativeBridgeDispatcher::GetNativeMethods( + ObjectID object_id, + std::set* methods) { + render_frame()->Send( + new GinNativeBridgeHostMsg_GetMethods(routing_id(), object_id, methods)); +} + +bool GinNativeBridgeDispatcher::HasNativeMethod( + ObjectID object_id, + const std::string& method_name) { + bool result; + render_frame()->Send(new GinNativeBridgeHostMsg_HasMethod( + routing_id(), object_id, method_name, &result)); + return result; +} + +std::unique_ptr GinNativeBridgeDispatcher::InvokeNativeMethod( + ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + GinNativeBridgeError* error) { + LOG(INFO) << __FUNCTION__; + base::Value::List result_wrapper; + render_frame()->Send(new GinNativeBridgeHostMsg_InvokeMethod( + routing_id(), object_id, method_name, arguments, &result_wrapper, error)); + if (result_wrapper.empty()) + return nullptr; + return base::Value::ToUniquePtrValue(result_wrapper[0].Clone()); +} + +GinNativeBridgeObject* GinNativeBridgeDispatcher::GetObject( + ObjectID object_id) { + GinNativeBridgeObject* result = objects_.Lookup(object_id); + if (!result) { + result = GinNativeBridgeObject::InjectAnonymous(AsWeakPtr(), object_id); + if (result) + objects_.AddWithID(result, object_id); + } + return result; +} + +void GinNativeBridgeDispatcher::OnDestruct() { + delete this; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h new file mode 100644 index 0000000..0905eb6 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h @@ -0,0 +1,77 @@ +// Copyright 2017 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_RENDERER_GIN_NATIVE_BRIDGE_DISPATCHER_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_DISPATCHER_H_ + +#include +#include +#include + +#include "base/containers/id_map.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "content/public/renderer/render_frame_observer.h" +#include "ewk/efl_integration/common/gin_native_bridge_errors.h" + +namespace blink { +class WebFrame; +} + +namespace content { + +class GinNativeBridgeObject; + +// This class handles injecting Native objects into the main frame of a +// RenderView. The 'add' and 'remove' messages received from the browser +// process modify the entries in a map of 'pending' objects. These objects are +// bound to the window object of the main frame when that window object is next +// cleared. These objects remain bound until the window object is cleared +// again. + +class GinNativeBridgeDispatcher + : public base::SupportsWeakPtr, + public RenderFrameObserver { + public: + // GinNativeBridgeObjects are managed by gin. An object gets destroyed + // when it is no more referenced from JS. As GinNativeBridgeObjects reports + // deletion of self to GinNativeBridgeDispatcher, we would not have stale + // pointers here. + typedef base::IDMap ObjectMap; + typedef ObjectMap::KeyType ObjectID; + + explicit GinNativeBridgeDispatcher(RenderFrame* render_frame); + ~GinNativeBridgeDispatcher() override; + + GinNativeBridgeDispatcher(const GinNativeBridgeDispatcher&) = delete; + GinNativeBridgeDispatcher& operator=(const GinNativeBridgeDispatcher&) = + delete; + + // RenderFrameObserver override: + void OnDestruct() override; + bool OnMessageReceived(const IPC::Message& message) override; + void DidClearWindowObject() override; + + void GetNativeMethods(ObjectID object_id, std::set* methods); + bool HasNativeMethod(ObjectID object_id, const std::string& method_name); + std::unique_ptr InvokeNativeMethod( + ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + GinNativeBridgeError* error); + GinNativeBridgeObject* GetObject(ObjectID object_id); + + private: + void OnAddNamedObject(const std::string& name, ObjectID object_id); + void OnRemoveNamedObject(const std::string& name); + + typedef std::map NamedObjectMap; + NamedObjectMap named_objects_; + ObjectMap objects_; + bool inside_did_clear_window_object_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_DISPATCHER_H_ diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc new file mode 100644 index 0000000..caf9e41 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc @@ -0,0 +1,124 @@ +// Copyright 2017 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 "renderer/gin_native_bridge_object.h" + +#include "common/gin_native_bridge_messages.h" +#include "content/public/renderer/render_thread.h" +#include "gin/function_template.h" +#include "renderer/gin_native_function_invocation_helper.h" +#include "third_party/blink/public/web/blink.h" +#include "third_party/blink/public/web/web_frame.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "v8/include/v8-function.h" + +namespace content { +// static +GinNativeBridgeObject* GinNativeBridgeObject::InjectNamed( + blink::WebFrame* frame, + const base::WeakPtr& dispatcher, + const std::string& object_name, + GinNativeBridgeDispatcher::ObjectID object_id) { + v8::Isolate* isolate = blink::MainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + + if (!frame->IsWebLocalFrame()) + return NULL; + + v8::Local context = + frame->ToWebLocalFrame()->MainWorldScriptContext(); + if (context.IsEmpty()) + return NULL; + + GinNativeBridgeObject* object = + new GinNativeBridgeObject(isolate, dispatcher, object_id); + + v8::Context::Scope context_scope(context); + v8::Handle global = context->Global(); + gin::Handle controller = + gin::CreateHandle(isolate, object); + // WrappableBase instance deletes itself in case of a wrapper + // creation failure, thus there is no need to delete |object|. + if (controller.IsEmpty()) + return NULL; + + global->Set(context, gin::StringToV8(isolate, object_name), controller.ToV8()) + .Check(); + return object; +} + +// static +GinNativeBridgeObject* GinNativeBridgeObject::InjectAnonymous( + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id) { + return new GinNativeBridgeObject(blink::MainThreadIsolate(), dispatcher, + object_id); +} + +GinNativeBridgeObject::GinNativeBridgeObject( + v8::Isolate* isolate, + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id) + : gin::NamedPropertyInterceptor(isolate, this), + dispatcher_(dispatcher), + object_id_(object_id), + frame_routing_id_(dispatcher_->routing_id()), + template_cache_(isolate) {} + +GinNativeBridgeObject::~GinNativeBridgeObject() {} + +gin::ObjectTemplateBuilder GinNativeBridgeObject::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return gin::Wrappable::GetObjectTemplateBuilder( + isolate) + .AddNamedPropertyInterceptor(); +} + +v8::Local GinNativeBridgeObject::GetNamedProperty( + v8::Isolate* isolate, + const std::string& property) { + std::map::iterator method_pos = + known_methods_.find(property); + if (method_pos == known_methods_.end()) { + if (!dispatcher_) + return v8::Local(); + + known_methods_[property] = + dispatcher_->HasNativeMethod(object_id_, property); + } + if (known_methods_[property]) + return GetFunctionTemplate(isolate, property) + ->GetFunction(isolate->GetCurrentContext()) + .FromMaybe(v8::Local()); + else + return v8::Local(); +} + +std::vector GinNativeBridgeObject::EnumerateNamedProperties( + v8::Isolate* isolate) { + std::set method_names; + if (dispatcher_) + dispatcher_->GetNativeMethods(object_id_, &method_names); + return std::vector(method_names.begin(), method_names.end()); +} + +v8::Local GinNativeBridgeObject::GetFunctionTemplate( + v8::Isolate* isolate, + const std::string& name) { + v8::Local function_template = template_cache_.Get(name); + if (!function_template.IsEmpty()) + return function_template; + function_template = gin::CreateFunctionTemplate( + isolate, + base::BindRepeating(&GinNativeFunctionInvocationHelper::Invoke, + base::Owned(new GinNativeFunctionInvocationHelper( + name, dispatcher_)))); + template_cache_.Set(name, function_template); + return function_template; +} + +gin::WrapperInfo GinNativeBridgeObject::kWrapperInfo = { + gin::kEmbedderNativeGin}; + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h new file mode 100644 index 0000000..4c5af69 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h @@ -0,0 +1,74 @@ +// Copyright 2017 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_RENDERER_GIN_NATIVE_BRIDGE_OBJECT_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_OBJECT_H_ + +#include +#include +#include +#include + +#include "base/memory/weak_ptr.h" +#include "gin/handle.h" +#include "gin/interceptor.h" +#include "gin/object_template_builder.h" +#include "gin/wrappable.h" +#include "renderer/gin_native_bridge_dispatcher.h" +#include "v8/include/v8-util.h" + +namespace blink { +class WebFrame; +} + +namespace content { + +class GinNativeBridgeObject : public gin::Wrappable, + public gin::NamedPropertyInterceptor { + public: + static gin::WrapperInfo kWrapperInfo; + GinNativeBridgeDispatcher::ObjectID object_id() const { return object_id_; } + + // gin::Wrappable. + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + + // gin::NamedPropertyInterceptor + v8::Local GetNamedProperty(v8::Isolate* isolate, + const std::string& property) override; + std::vector EnumerateNamedProperties( + v8::Isolate* isolate) override; + + static GinNativeBridgeObject* InjectNamed( + blink::WebFrame* frame, + const base::WeakPtr& dispatcher, + const std::string& object_name, + GinNativeBridgeDispatcher::ObjectID object_id); + static GinNativeBridgeObject* InjectAnonymous( + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id); + + private: + GinNativeBridgeObject( + v8::Isolate* isolate, + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id); + ~GinNativeBridgeObject() override; + + GinNativeBridgeObject(const GinNativeBridgeObject&) = delete; + GinNativeBridgeObject& operator=(const GinNativeBridgeObject&) = delete; + + v8::Local GetFunctionTemplate(v8::Isolate* isolate, + const std::string& name); + + base::WeakPtr dispatcher_; + GinNativeBridgeDispatcher::ObjectID object_id_; + int frame_routing_id_; + std::map known_methods_; + v8::StdGlobalValueMap template_cache_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_OBJECT_H_ diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc new file mode 100644 index 0000000..209eb6a --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc @@ -0,0 +1,37 @@ +// Copyright 2017 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 "renderer/gin_native_bridge_value_converter.h" + +#include + +#include "base/values.h" +#include "gin/array_buffer.h" +#include "renderer/gin_native_bridge_object.h" + +namespace content { + +GinNativeBridgeValueConverter::GinNativeBridgeValueConverter() + : converter_(V8ValueConverter::Create()) { + converter_->SetDateAllowed(false); + converter_->SetRegExpAllowed(false); + converter_->SetFunctionAllowed(true); + converter_->SetStrategy(this); +} + +GinNativeBridgeValueConverter::~GinNativeBridgeValueConverter() {} + +v8::Local GinNativeBridgeValueConverter::ToV8Value( + const base::Value* value, + v8::Local context) const { + return converter_->ToV8Value(*value, context); +} + +std::unique_ptr GinNativeBridgeValueConverter::FromV8Value( + v8::Local value, + v8::Local context) const { + return converter_->FromV8Value(value, context); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h new file mode 100644 index 0000000..fb4185b --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h @@ -0,0 +1,36 @@ +// Copyright 2017 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_RENDERER_GIN_NATIVE_BRIDGE_VALUE_CONVERTER_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_VALUE_CONVERTER_H_ + +#include "content/common/content_export.h" +#include "content/public/renderer/v8_value_converter.h" + +namespace content { + +class GinNativeBridgeValueConverter + : public content::V8ValueConverter::Strategy { + public: + CONTENT_EXPORT GinNativeBridgeValueConverter(); + CONTENT_EXPORT ~GinNativeBridgeValueConverter() override; + + GinNativeBridgeValueConverter(const GinNativeBridgeValueConverter&) = delete; + GinNativeBridgeValueConverter& operator=( + const GinNativeBridgeValueConverter&) = delete; + + CONTENT_EXPORT v8::Local ToV8Value( + const base::Value* value, + v8::Local context) const; + CONTENT_EXPORT std::unique_ptr FromV8Value( + v8::Local value, + v8::Local context) const; + + private: + std::unique_ptr converter_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_VALUE_CONVERTER_H_ diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc new file mode 100644 index 0000000..8906fdd --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc @@ -0,0 +1,108 @@ +// Copyright 2017 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 "renderer/gin_native_function_invocation_helper.h" + +#include "common/gin_native_bridge_value.h" +#include "content/public/renderer/v8_value_converter.h" +#include "renderer/gin_native_bridge_object.h" +#include "renderer/gin_native_bridge_value_converter.h" +#include "v8/include/v8-exception.h" + +namespace content { + +namespace { + +const char kMethodInvocationAsConstructorDisallowed[] = + "Native bridge method can't be invoked as a constructor"; +const char kMethodInvocationOnNonInjectedObjectDisallowed[] = + "Native bridge method can't be invoked on a non-injected object"; +const char kMethodInvocationErrorMessage[] = + "Native bridge method invocation error"; + +} // namespace + +GinNativeFunctionInvocationHelper::GinNativeFunctionInvocationHelper( + const std::string& method_name, + const base::WeakPtr& dispatcher) + : method_name_(method_name), + dispatcher_(dispatcher), + converter_(new GinNativeBridgeValueConverter()) {} + +GinNativeFunctionInvocationHelper::~GinNativeFunctionInvocationHelper() {} + +v8::Local GinNativeFunctionInvocationHelper::Invoke( + gin::Arguments* args) { + if (!dispatcher_) { + args->isolate()->ThrowException(v8::Exception::Error( + gin::StringToV8(args->isolate(), kMethodInvocationErrorMessage))); + return v8::Undefined(args->isolate()); + } + + if (args->IsConstructCall()) { + args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( + args->isolate(), kMethodInvocationAsConstructorDisallowed))); + return v8::Undefined(args->isolate()); + } + + content::GinNativeBridgeObject* object = NULL; + if (!args->GetHolder(&object) || !object) { + args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( + args->isolate(), kMethodInvocationOnNonInjectedObjectDisallowed))); + return v8::Undefined(args->isolate()); + } + + base::Value::List arguments; + { + v8::HandleScope handle_scope(args->isolate()); + v8::Local context = args->isolate()->GetCurrentContext(); + v8::Local val; + while (args->GetNext(&val)) { + std::unique_ptr arg(converter_->FromV8Value(val, context)); + if (arg.get()) { + arguments.Append(base::Value::FromUniquePtrValue(std::move(arg))); + } else { + arguments.Append(base::Value()); + } + } + } + + GinNativeBridgeError error; + std::unique_ptr result = dispatcher_->InvokeNativeMethod( + object->object_id(), method_name_, arguments, &error); + if (!result.get()) { + args->isolate()->ThrowException(v8::Exception::Error( + gin::StringToV8(args->isolate(), GinNativeBridgeErrorToString(error)))); + return v8::Undefined(args->isolate()); + } + if (!result->is_blob()) { + return converter_->ToV8Value(result.get(), + args->isolate()->GetCurrentContext()); + } + + std::unique_ptr gin_value = + GinNativeBridgeValue::FromValue(result.get()); + + if (gin_value->IsType(GinNativeBridgeValue::TYPE_OBJECT_ID)) { + GinNativeBridgeObject* result = NULL; + GinNativeBridgeDispatcher::ObjectID object_id; + if (gin_value->GetAsObjectID(&object_id)) { + result = dispatcher_->GetObject(object_id); + } + if (result) { + gin::Handle controller = + gin::CreateHandle(args->isolate(), result); + if (controller.IsEmpty()) + return v8::Undefined(args->isolate()); + return controller.ToV8(); + } + } else if (gin_value->IsType(GinNativeBridgeValue::TYPE_NONFINITE)) { + float float_value; + gin_value->GetAsNonFinite(&float_value); + return v8::Number::New(args->isolate(), float_value); + } + return v8::Undefined(args->isolate()); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h new file mode 100644 index 0000000..adca806 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h @@ -0,0 +1,42 @@ +// Copyright 2017 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_RENDERER_GIN_NATIVE_FUNCTION_INVOCATION_HELPER_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_FUNCTION_INVOCATION_HELPER_H_ + +#include +#include + +#include "base/memory/weak_ptr.h" +#include "gin/arguments.h" +#include "gin/handle.h" +#include "renderer/gin_native_bridge_dispatcher.h" + +namespace content { + +class GinNativeBridgeValueConverter; + +class GinNativeFunctionInvocationHelper { + public: + GinNativeFunctionInvocationHelper( + const std::string& method_name, + const base::WeakPtr& dispatcher); + ~GinNativeFunctionInvocationHelper(); + + GinNativeFunctionInvocationHelper(const GinNativeFunctionInvocationHelper&) = + delete; + GinNativeFunctionInvocationHelper& operator=( + const GinNativeFunctionInvocationHelper&) = delete; + + v8::Local Invoke(gin::Arguments* args); + + private: + std::string method_name_; + base::WeakPtr dispatcher_; + std::unique_ptr converter_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_FUNCTION_INVOCATION_HELPER_H_ -- 2.7.4 From 466cbd900fd1345e16151291208758c451d818aa Mon Sep 17 00:00:00 2001 From: "b.kiran" Date: Wed, 25 Jan 2023 10:26:48 +0530 Subject: [PATCH 16/16] [M108 Migration] Implement view port setting and zoom factor API This patch implement below preference setting and API for content scale. 1. As default meta view port enabling for mobile 2. Implement ewk api for view port set/get Reference: https://review.tizen.org/gerrit/c/278887 Change-Id: Id030ba049d55d46e55aaa2b8c75e27f3c7ed5fe9 Signed-off-by: Bakka Uday Kiran --- content/browser/web_contents/web_contents_impl.cc | 8 ++++++++ tizen_src/ewk/efl_integration/eweb_context.cc | 22 ++++++++++++++++++++++ tizen_src/ewk/efl_integration/eweb_context.h | 3 +++ .../efl_integration/private/ewk_context_private.cc | 8 ++++++++ .../efl_integration/private/ewk_context_private.h | 4 ++++ .../ewk/efl_integration/public/ewk_context.cc | 16 +++++++++++----- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 0f16da0..c2cd303 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -189,6 +189,7 @@ #if BUILDFLAG(IS_EFL) #include "content/browser/date_time_chooser_efl.h" +#include "tizen/system_info.h" #endif #if BUILDFLAG(IS_ANDROID) @@ -2829,6 +2830,13 @@ const blink::web_pref::WebPreferences WebContentsImpl::ComputeWebPreferences() { prefs.viewport_meta_enabled = false; } +#if BUILDFLAG(IS_EFL) + if (IsMobileProfile()) + prefs.viewport_meta_enabled = true; + + prefs.viewport_enabled |= prefs.viewport_meta_enabled; +#endif + prefs.spatial_navigation_enabled = command_line.HasSwitch(switches::kEnableSpatialNavigation); diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index e74e8a3..6e0ef15 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -21,6 +21,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/dom_storage_context.h" +#include "content/public/browser/host_zoom_map.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_usage_info.h" @@ -31,6 +32,7 @@ #include "storage/browser/database/database_quota_client.h" #include "storage/browser/file_system/file_system_quota_client.h" #include "storage/browser/quota/quota_manager.h" +#include "third_party/blink/public/common/page/page_zoom.h" #include "ui/gl/gl_shared_context_efl.h" #if defined(ENABLE_PLUGINS) @@ -799,6 +801,26 @@ bool EWebContext::GetExtensibleAPI(const std::string& api_name) { return TizenExtensibleHost::GetInstance()->GetExtensibleAPI(api_name); } +void EWebContext::SetDefaultZoomFactor(double zoom_factor) { + content::HostZoomMap* host_zoom_map = + content::HostZoomMap::GetDefaultForBrowserContext(browser_context_.get()); + if (host_zoom_map) { + host_zoom_map->SetDefaultZoomLevel( + blink::PageZoomFactorToZoomLevel(zoom_factor)); + } +} + +double EWebContext::GetDefaultZoomFactor() const { + content::HostZoomMap* host_zoom_map = + content::HostZoomMap::GetDefaultForBrowserContext(browser_context_.get()); + if (host_zoom_map) { + return blink::PageZoomLevelToZoomFactor( + host_zoom_map->GetDefaultZoomLevel()); + } + + return -1.0; +} + void EWebContext::SetInterceptRequestCallback( Ewk_Context* ewk_context, Ewk_Context_Intercept_Request_Callback callback, diff --git a/tizen_src/ewk/efl_integration/eweb_context.h b/tizen_src/ewk/efl_integration/eweb_context.h index 04812da..560b3aa 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.h +++ b/tizen_src/ewk/efl_integration/eweb_context.h @@ -174,6 +174,9 @@ class EWebContext { bool SetExtensibleAPI(const std::string& api_name, bool enable); bool GetExtensibleAPI(const std::string& api_name); + void SetDefaultZoomFactor(double zoom_factor); + double GetDefaultZoomFactor() const; + void SetInterceptRequestCallback( Ewk_Context* ewk_context, Ewk_Context_Intercept_Request_Callback callback, 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 cd4e31d..f10f434 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_context_private.cc @@ -269,6 +269,14 @@ void Ewk_Context::SetContextInterceptRequestCallback( impl->SetInterceptRequestCallback(this, callback, user_data); } +void Ewk_Context::SetDefaultZoomFactor(double zoom_factor) { + impl->SetDefaultZoomFactor(zoom_factor); +} + +double Ewk_Context::GetDefaultZoomFactor() const { + return impl->GetDefaultZoomFactor(); +} + #if BUILDFLAG(IS_TIZEN_TV) void Ewk_Context::SetApplicationType( const Ewk_Application_Type application_type) { 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 dce8618..d6daffc 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_context_private.h @@ -134,6 +134,10 @@ struct Ewk_Context : public base::RefCounted { Ewk_Context_Notification_Cancel_Callback cancel_callback, void* user_data); + // default zoom factor + void SetDefaultZoomFactor(double zoom_factor); + double GetDefaultZoomFactor() const; + void SetContextInterceptRequestCallback( Ewk_Context_Intercept_Request_Callback callback, void* user_data); diff --git a/tizen_src/ewk/efl_integration/public/ewk_context.cc b/tizen_src/ewk/efl_integration/public/ewk_context.cc index 3e3d06f..358a9679 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_context.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_context.cc @@ -974,11 +974,6 @@ void ewk_context_form_autofill_credit_card_changed_callback_set( LOG_EWK_API_MOCKUP(); } -void ewk_context_default_zoom_factor_set(Ewk_Context* context, - double zoom_factor) { - LOG_EWK_API_MOCKUP(); -} - void ewk_context_application_type_set( Ewk_Context* ewkContext, const Ewk_Application_Type applicationType) { @@ -1002,3 +997,14 @@ Ewk_Application_Type ewk_context_application_type_get(Ewk_Context* ewkContext) { return EWK_APPLICATION_TYPE_OTHER; #endif } + +void ewk_context_default_zoom_factor_set(Ewk_Context* context, + double zoom_factor) { + EINA_SAFETY_ON_NULL_RETURN(context); + context->SetDefaultZoomFactor(zoom_factor); +} + +double ewk_context_default_zoom_factor_get(Ewk_Context* context) { + EINA_SAFETY_ON_NULL_RETURN_VAL(context, -1.0); + return context->GetDefaultZoomFactor(); +} -- 2.7.4