From dbc2a8a17324b44edbca9c5492d37954f43d7d8f Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Tue, 21 Mar 2023 14:26:25 +0530 Subject: [PATCH 01/16] [M108 Migration][Loading Performance] Apply to prevent incremental image rendering Do not request image rendering when image resource is loading for page loading performance. This patch is written referring to tizen 2.4 webkit's code. Reference: https://review.tizen.org/gerrit/268835 Change-Id: Ifc46153667dc5af8d782c890335d32ae9ae44035 Signed-off-by: Gajendra N --- third_party/blink/renderer/core/layout/layout_image.cc | 14 ++++++++++++++ .../core/loader/resource/image_resource_content.cc | 6 ++++++ .../renderer/core/loader/resource/image_resource_content.h | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc index a5828c0..a663397 100644 --- a/third_party/blink/renderer/core/layout/layout_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image.cc @@ -52,6 +52,10 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "ui/gfx/geometry/size_conversions.h" +#if BUILDFLAG(IS_TIZEN) +#include "third_party/blink/renderer/core/paint/paint_info.h" +#endif + namespace blink { LayoutImage::LayoutImage(Element* element) @@ -222,6 +226,16 @@ void LayoutImage::PaintReplaced(const PaintInfo& paint_info, void LayoutImage::Paint(const PaintInfo& paint_info) const { NOT_DESTROYED(); +#if BUILDFLAG(IS_TIZEN) + // Do not request image rendering when image resource is loading + // for page loading performance. + if (paint_info.phase == PaintPhase::kForeground && + !Style()->HasBoxDecorations() && image_resource_ && + image_resource_->CachedImage() && + image_resource_->CachedImage()->IsLoading()) { + return; + } +#endif ImagePainter(*this).Paint(paint_info); } diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc index aa6087b..c1b61f0 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc @@ -456,6 +456,12 @@ ImageResourceContent::UpdateImageResult ImageResourceContent::UpdateImage( DCHECK(all_data_received || size_available_ != Image::kSizeAvailableAndLoadingAsynchronously); +#if BUILDFLAG(IS_TIZEN) + if (!notified_) + notified_ = true; + else if (!all_data_received) + return UpdateImageResult::kNoDecodeError; +#endif // Notifies the observers. // It would be nice to only redraw the decoded band of the image, but with the // current design (decoding delayed until painting) that seems hard. diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h index 834a0dc..c9ae5e5 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h @@ -268,6 +268,10 @@ class CORE_EXPORT ImageResourceContent final scoped_refptr image_; +#if BUILDFLAG(IS_TIZEN) + bool notified_ = false; +#endif + HeapHashCountedSet> observers_; HeapHashCountedSet> finished_observers_; -- 2.7.4 From 01273634950284f6b4d37573a892e8ab8f735a9b Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Tue, 21 Mar 2023 14:19:36 +0530 Subject: [PATCH 02/16] [M108 Migration][Loading Performance] Introduce |BeginMainFrame| throttling Delaying posting a task |BeginMainFrame| means several tasks can be deferred such as recording, rasterization and compositing. It can be delayed for 0.1 sec. This will improve loading performance by renderer process focus on loading. Reference : https://review.tizen.org/gerrit/268908 Change-Id: I61c5e1b87e1b69604d5f2987199bda01e69a81c3 Signed-off-by: Gajendra N --- cc/trees/layer_tree_host.cc | 6 +++ cc/trees/layer_tree_host.h | 4 ++ cc/trees/proxy.h | 4 ++ cc/trees/proxy_main.cc | 52 ++++++++++++++++++++++ cc/trees/proxy_main.h | 15 +++++++ content/renderer/render_frame_impl.cc | 10 +++++ third_party/blink/public/web/web_frame_widget.h | 4 ++ .../renderer/core/frame/web_frame_widget_impl.cc | 6 +++ .../renderer/core/frame/web_frame_widget_impl.h | 4 ++ 9 files changed, 105 insertions(+) diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 6432697..0335270 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -557,6 +557,12 @@ void LayerTreeHost::DidFailToInitializeLayerTreeFrameSink() { client_->DidFailToInitializeLayerTreeFrameSink(); } +#if BUILDFLAG(IS_TIZEN) +void LayerTreeHost::DidChangeLoadState(bool is_loading) { + proxy_->DidChangeLoadState(is_loading); +} +#endif + std::unique_ptr LayerTreeHost::CreateLayerTreeHostImpl( LayerTreeHostImplClient* client) { // This method is special: it should be the only LayerTreeHost method that diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index adfdf9d..772b2b5 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -840,6 +840,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { return pending_commit_state()->viewport_property_ids; } +#if BUILDFLAG(IS_TIZEN) + virtual void DidChangeLoadState(bool); +#endif + void SetSourceURL(ukm::SourceId source_id, const GURL& url); base::ReadOnlySharedMemoryRegion CreateSharedMemoryForSmoothnessUkm(); diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h index 6868bf0..7c0c562 100644 --- a/cc/trees/proxy.h +++ b/cc/trees/proxy.h @@ -93,6 +93,10 @@ class CC_EXPORT Proxy { virtual void RequestBeginMainFrameNotExpected(bool new_state) = 0; +#if BUILDFLAG(IS_TIZEN) + virtual void DidChangeLoadState(bool) {} +#endif + // Testing hooks virtual bool MainFrameWillHappenForTesting() = 0; diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc index ac0d588..0cae27d 100644 --- a/cc/trees/proxy_main.cc +++ b/cc/trees/proxy_main.cc @@ -34,6 +34,11 @@ namespace cc { +#if BUILDFLAG(IS_TIZEN) +// For throttling BeginMainFrame +const int kBeginMainFrameDelay = 100; +#endif + ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host, TaskRunnerProvider* task_runner_provider) : layer_tree_host_(layer_tree_host), @@ -45,6 +50,9 @@ ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host, deferred_final_pipeline_stage_(NO_PIPELINE_STAGE), started_(false), defer_main_frame_update_(false), +#if BUILDFLAG(IS_TIZEN) + begin_main_frame_timer_(new base::OneShotTimer), +#endif pause_rendering_(false) { TRACE_EVENT0("cc", "ProxyMain::ProxyMain"); DCHECK(task_runner_provider_); @@ -126,8 +134,48 @@ void ProxyMain::DidCompletePageScaleAnimation() { layer_tree_host_->DidCompletePageScaleAnimation(); } +#if BUILDFLAG(IS_TIZEN) +void ProxyMain::DidChangeLoadState(bool is_loading) { + DCHECK(IsMainThread()); + if (need_to_throttle_ == is_loading) + return; + + need_to_throttle_ = is_loading; + + // Force to call BeginMainFrame immediately if loading is finished. + if (!need_to_throttle_ && begin_main_frame_timer_->IsRunning() && + !begin_main_frame_callback_.is_null()) { + std::move(begin_main_frame_callback_).Run(); + } + begin_main_frame_callback_.Reset(); +} +#endif + void ProxyMain::BeginMainFrame( std::unique_ptr begin_main_frame_state) { +#if BUILDFLAG(IS_TIZEN) + // Skip throttling for the first BeginMainFrame to improve launching + // performance. + if (need_to_throttle_ && !first_begin_main_frame_) { + DCHECK(!begin_main_frame_timer_->IsRunning()); + begin_main_frame_callback_ = + base::BindOnce(&ProxyMain::DoBeginMainFrame, base::Unretained(this), + std::move(begin_main_frame_state)); + begin_main_frame_timer_->Start(FROM_HERE, + base::Milliseconds(kBeginMainFrameDelay), + std::move(begin_main_frame_callback_)); + } else { + begin_main_frame_timer_->Stop(); + DoBeginMainFrame(std::move(begin_main_frame_state)); + } +} + +void ProxyMain::DoBeginMainFrame( + std::unique_ptr begin_main_frame_state) { + first_begin_main_frame_ = false; + begin_main_frame_timer_.reset(new base::OneShotTimer); +#endif + DCHECK(IsMainThread()); DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_); @@ -692,6 +740,10 @@ void ProxyMain::Stop() { DCHECK(IsMainThread()); DCHECK(started_); +#if BUILDFLAG(IS_TIZEN) + begin_main_frame_timer_->Stop(); +#endif + // Synchronously finishes pending GL operations and deletes the impl. // The two steps are done as separate post tasks, so that tasks posted // by the GL implementation due to the Finish can be executed by the diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h index f671dfc..20b91b2 100644 --- a/cc/trees/proxy_main.h +++ b/cc/trees/proxy_main.h @@ -18,6 +18,10 @@ #include "cc/trees/proxy.h" #include "cc/trees/proxy_common.h" +#if BUILDFLAG(IS_TIZEN) +#include "base/callback.h" +#endif + namespace cc { class CompletionEvent; @@ -139,6 +143,17 @@ class CC_EXPORT ProxyMain : public Proxy { RenderingStatsInstrumentation* rendering_stats_instrumentation); void DestroyProxyImplOnImplThread(CompletionEvent* completion_event); +#if BUILDFLAG(IS_TIZEN) + void DidChangeLoadState(bool is_loading) override; + void DoBeginMainFrame( + std::unique_ptr begin_main_frame_state); + + bool first_begin_main_frame_ = true; + bool need_to_throttle_ = false; + base::OnceClosure begin_main_frame_callback_; + std::unique_ptr begin_main_frame_timer_; +#endif + raw_ptr layer_tree_host_; raw_ptr task_runner_provider_; diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index d95e1b7..242f20d 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -3807,6 +3807,11 @@ void RenderFrameImpl::DidCommitNavigation( : nullptr, nullptr /* same_document_params */, GetWebFrame()->GetEmbeddingToken()); +#if BUILDFLAG(IS_TIZEN) + if (frame_ == GetWebView()->MainFrame()) + GetLocalRootWebFrameWidget()->DidChangeLoadState(true /* is_loading */); +#endif + // If we end up reusing this WebRequest (for example, due to a #ref click), // we don't want the transition type to persist. Just clear it. navigation_state->set_transition_type(ui::PAGE_TRANSITION_LINK); @@ -3962,6 +3967,11 @@ void RenderFrameImpl::DidFinishLoad() { for (auto& observer : observers_) observer.DidFinishLoad(); + +#if BUILDFLAG(IS_TIZEN) + if (frame_ == GetWebView()->MainFrame()) + GetLocalRootWebFrameWidget()->DidChangeLoadState(false /* is_loading */); +#endif } void RenderFrameImpl::DidFinishLoadForPrinting() { diff --git a/third_party/blink/public/web/web_frame_widget.h b/third_party/blink/public/web/web_frame_widget.h index d98d626..fbd473f 100644 --- a/third_party/blink/public/web/web_frame_widget.h +++ b/third_party/blink/public/web/web_frame_widget.h @@ -223,6 +223,10 @@ class WebFrameWidget : public WebWidget { virtual void SetMaxRefreshRate(uint32_t max_refresh_rate) {} #endif +#if BUILDFLAG(IS_TIZEN) + virtual void DidChangeLoadState(bool is_loading) {} +#endif + private: // This is a private virtual method so we don't expose cc::LayerTreeHost // outside of this class. Friend classes may be added in order to access it. 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 12866b0..43bc449 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 @@ -4300,6 +4300,12 @@ void WebFrameWidgetImpl::SetMaxRefreshRate(uint32_t max_refresh_rate) { } #endif +#if BUILDFLAG(IS_TIZEN) +void WebFrameWidgetImpl::DidChangeLoadState(bool is_loading) { + widget_base_->LayerTreeHost()->DidChangeLoadState(is_loading); +} +#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 03eb8e5..abb3c99 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 @@ -643,6 +643,10 @@ class CORE_EXPORT WebFrameWidgetImpl void SetMaxRefreshRate(uint32_t max_refresh_rate) override; #endif +#if BUILDFLAG(IS_TIZEN) + void DidChangeLoadState(bool is_loading) override; +#endif + protected: // WidgetBaseClient overrides: void ScheduleAnimation() override; -- 2.7.4 From 79c192988158b9b3f63d002bfb060532f1667a1d Mon Sep 17 00:00:00 2001 From: Chandan Padhi Date: Wed, 22 Mar 2023 22:03:18 +0530 Subject: [PATCH 03/16] [MemOpt] Disable JPEG XL image decoding This commit reduces libchromium-impl.so size by ~0.38MB. out.tz_v7.0.PontusM.armv7l/libchromium-impl.so size in bytes: w/o patch: 166863652 with patch: 166483208 Change-Id: I7bf80c7b6859afeaa61a0f6887652fce84ffd739 Signed-off-by: Chandan Padhi --- third_party/blink/public/public_features.gni | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/blink/public/public_features.gni b/third_party/blink/public/public_features.gni index ef7537d..a168118 100644 --- a/third_party/blink/public/public_features.gni +++ b/third_party/blink/public/public_features.gni @@ -6,7 +6,7 @@ import("//build/config/ui.gni") declare_args() { # If true, adds support for JPEG XL image decoding. - enable_jxl_decoder = !is_ios + enable_jxl_decoder = !is_ios && !use_efl } # Unhandled Tap enable means Contextual Search aka Touch to Search. -- 2.7.4 From a849f018435fa9c632a73f63632c7a0592404048 Mon Sep 17 00:00:00 2001 From: liuxd Date: Mon, 6 Mar 2023 14:00:19 +0800 Subject: [PATCH 04/16] [M108 Migration][VD] Fix Fonts Issue MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 1.[VD] Fix special character and vowel signs of khmer(Thai,Myanmar) show boxes issue. Currently,the HarfBuzz buffer of native app use HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS cluster level, Chromium use default cluster level: HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES. The difference between the two cluster level is like below: when input special character and vowel signs of khmer(Thai,Myanmar) (the special character which not included in the khmer(Thai,Myanmar)font): MONOTONE_CHARACTERS level: two unicode will split two clusters MONOTONE_GRAPHEMES level: two unicode will bind one cluster, cause can't get valid glyph, and show boxes. To keep same behaviour to native app,set the HarfBuzz buffer cluster level to HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS. Migrated from aura: https://review.tizen.org/gerrit/#/c/282743 2.[VD] Perform fallback font for private use unicode Private-use characters are most commonly used in East Asia, particularly in Japan, China, and Korea, to extend the available characters in various standards and vendor character sets. Refer: https://www.unicode.org/faq/private_use.html On VD, Private-use characters are been used, need perform fallback font for it, or else will cause can not show the correct glyph, but showed as a box. refer: https://review.tizen.org/gerrit/#/c/286928 Change-Id: Idc62e49117f676b90bd1ea9867afb8197f003c39 Signed-off-by: liuxd --- third_party/blink/renderer/platform/fonts/font_cache.cc | 5 ++++- .../blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/third_party/blink/renderer/platform/fonts/font_cache.cc b/third_party/blink/renderer/platform/fonts/font_cache.cc index e66ee96..338aac0 100644 --- a/third_party/blink/renderer/platform/fonts/font_cache.cc +++ b/third_party/blink/renderer/platform/fonts/font_cache.cc @@ -287,7 +287,10 @@ scoped_refptr FontCache::FallbackFontForCharacter( // http://www.unicode.org/faq/private_use.html#nonchar1 - See also // crbug.com/862352 where performing fallback for U+FFFE causes a memory // regression. - if (Character::IsPrivateUse(lookup_char) || + if ( +#if !BUILDFLAG(IS_TIZEN_TV) + Character::IsPrivateUse(lookup_char) || +#endif Character::IsNonCharacter(lookup_char)) return nullptr; base::ElapsedTimer timer; diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc index c55d58e..c2ae867 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc @@ -301,6 +301,15 @@ inline bool ShapeRange(hb_buffer_t* buffer, hb_buffer_set_script(buffer, ICUScriptToHBScript(current_run_script)); hb_buffer_set_direction(buffer, direction); +#if BUILDFLAG(IS_TIZEN_TV) + if (current_run_script == USCRIPT_KHMER || + current_run_script == USCRIPT_THAI || + current_run_script == USCRIPT_MYANMAR) { + hb_buffer_set_cluster_level(buffer, + HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); + } +#endif + hb_font_t* hb_font = face->GetScaledFont(std::move(current_font_range_set), HB_DIRECTION_IS_VERTICAL(direction) -- 2.7.4 From d6394f21f750e9fe64d254ddcf13812ade78fd76 Mon Sep 17 00:00:00 2001 From: wangjing Date: Tue, 21 Mar 2023 17:08:16 +0800 Subject: [PATCH 05/16] [M108 Migration][API] Implement ewk_view_edge_scroll_by for all profiles This function should be used for browser edge scroll. Scrolls webpage of view by dx and dy. "edge,scroll,left" "edge,scroll,top" "edge,scroll,bottom" "edge,scroll,right" reference: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/279660/ https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/280265/ Change-Id: Ifb4644e75467d1be2c6207c3b2462465303252b7 Signed-off-by: wangjing --- components/plugins/renderer/webview_plugin.h | 3 + .../renderer_host/render_widget_host_impl.cc | 9 ++ .../renderer_host/render_widget_host_impl.h | 4 + .../renderer_host/render_widget_host_view_aura.cc | 7 + .../renderer_host/render_widget_host_view_aura.h | 4 + .../renderer_host/render_widget_host_view_base.h | 5 + content/public/browser/web_contents_delegate.h | 5 + third_party/blink/public/mojom/BUILD.gn | 4 + third_party/blink/public/mojom/page/widget.mojom | 4 + .../public/mojom/widget/platform_widget.mojom | 4 + third_party/blink/public/web/web_view.h | 6 + .../blink/renderer/core/exported/web_view_impl.cc | 33 +++++ .../blink/renderer/core/exported/web_view_impl.h | 5 + .../renderer/core/frame/web_frame_widget_impl.cc | 12 ++ .../renderer/core/frame/web_frame_widget_impl.h | 5 + .../blink/renderer/core/input/event_handler.cc | 47 +++++++ .../blink/renderer/core/input/event_handler.h | 5 + .../blink/renderer/core/input/scroll_manager.cc | 6 +- .../blink/renderer/core/input/scroll_manager.h | 3 +- .../blink/renderer/platform/widget/widget_base.cc | 6 + .../blink/renderer/platform/widget/widget_base.h | 5 + .../renderer_host/rwhv_aura_common_helper_efl.cc | 7 + .../renderer_host/rwhv_aura_common_helper_efl.h | 5 + tizen_src/ewk/efl_integration/eweb_view.cc | 68 ++++++++++ tizen_src/ewk/efl_integration/eweb_view.h | 8 ++ .../ewk/efl_integration/eweb_view_callbacks.h | 8 ++ tizen_src/ewk/efl_integration/public/ewk_view.cc | 7 + .../efl_integration/web_contents_delegate_efl.cc | 8 ++ .../efl_integration/web_contents_delegate_efl.h | 5 + tizen_src/ewk/unittest/BUILD.gn | 1 + .../utc_blink_ewk_view_edge_scroll_by_func.cpp | 147 +++++++++++++++++++++ 31 files changed, 442 insertions(+), 4 deletions(-) create mode 100644 tizen_src/ewk/unittest/utc_blink_ewk_view_edge_scroll_by_func.cpp diff --git a/components/plugins/renderer/webview_plugin.h b/components/plugins/renderer/webview_plugin.h index 886d3ea..2856bf5 100644 --- a/components/plugins/renderer/webview_plugin.h +++ b/components/plugins/renderer/webview_plugin.h @@ -193,6 +193,9 @@ class WebViewPlugin : public blink::WebPlugin, public blink::WebViewObserver { // blink::mojom::WidgetHost implementation. void SetCursor(const ui::Cursor& cursor) override; +#if BUILDFLAG(IS_TIZEN_TV) + void DidEdgeScrollBy(const gfx::Point& point, bool handled) override {} +#endif void UpdateTooltipUnderCursor(const std::u16string& tooltip_text, base::i18n::TextDirection hint) override; void UpdateTooltipFromKeyboard(const std::u16string& tooltip_text, diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 380d147..84f8aae 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -2655,6 +2655,15 @@ void RenderWidgetHostImpl::ShowPopup(const gfx::Rect& initial_screen_rect, std::move(callback).Run(); } +#if BUILDFLAG(IS_TIZEN_TV) +void RenderWidgetHostImpl::DidEdgeScrollBy(const gfx::Point& offset, bool handled) { + if (!GetView()) + return; + + view_->DidEdgeScrollBy(offset, handled); +} +#endif + void RenderWidgetHostImpl::UpdateTooltipUnderCursor( const std::u16string& tooltip_text, base::i18n::TextDirection text_direction_hint) { diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 688d5a0..b069615 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -314,6 +314,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl const ChildProcessTerminationInfo& info) override; // blink::mojom::WidgetHost implementation. +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + void DidEdgeScrollBy(const gfx::Point& point, bool handled) override; +#endif void UpdateTooltipUnderCursor( const std::u16string& tooltip_text, base::i18n::TextDirection text_direction_hint) override; 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 e032c12..e803089 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -2122,6 +2122,13 @@ void RenderWidgetHostViewAura::FocusedNodeChanged( #endif } +#if BUILDFLAG(IS_TIZEN_TV) +void RenderWidgetHostViewAura::DidEdgeScrollBy(const gfx::Point& offset, + bool handled) { + efl_helper_->DidEdgeScrollBy(offset, handled); +} +#endif + void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) { event_handler_->OnScrollEvent(event); } 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 4db3ca5..d50796e 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -214,6 +214,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAura #endif ) override; +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + void DidEdgeScrollBy(const gfx::Point& offset, bool handled) override ; +#endif void OnSynchronizedDisplayPropertiesChanged(bool rotation = false) override; viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties( const cc::RenderFrameMetadata& metadata) override; 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 96e32a2..8669e1f 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h @@ -487,6 +487,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { // Tells the View to destroy itself. virtual void Destroy(); +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + virtual void DidEdgeScrollBy(const gfx::Point& offset, bool handled) {} +#endif + // Calls UpdateTooltip if the view is under the cursor. virtual void UpdateTooltipUnderCursor(const std::u16string& tooltip_text) {} diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 819ddc9..2dfc993 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h @@ -395,6 +395,11 @@ class CONTENT_EXPORT WebContentsDelegate { // Invoked when a primary main frame navigation occurs. virtual void DidNavigatePrimaryMainFramePostCommit(WebContents* source) {} +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + virtual void DidEdgeScrollBy(const gfx::Point& offset, bool handled) {} +#endif + // Returns a pointer to a service to manage JavaScript dialogs. May return // nullptr in which case dialogs aren't shown. virtual JavaScriptDialogManager* GetJavaScriptDialogManager( diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 3d36e4a..3e67835 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn @@ -1123,6 +1123,10 @@ mojom("mojom_core") { enabled_features += [ "is_efl" ] } + if (tizen_product_tv) { + enabled_features += [ "is_tizen_tv" ] + } + if (is_android) { # Direct deps (instead of transitive deps) are necessary for java targets. public_deps += [ diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom index 46ba938..f7feae5 100644 --- a/third_party/blink/public/mojom/page/widget.mojom +++ b/third_party/blink/public/mojom/page/widget.mojom @@ -148,6 +148,10 @@ interface FrameWidget { // third_party/blink/public/mojom/frame/viewport_intersection_state.mojom SetViewportIntersection(ViewportIntersectionState intersection_state, VisualProperties? visual_properties); + + [EnableIf=is_tizen_tv] + //Browser edge scroll + EdgeScrollBy(gfx.mojom.Point offset, gfx.mojom.Point mouse_position); }; // Implemented in Browser, this interface defines frame-widget-specific methods that diff --git a/third_party/blink/public/mojom/widget/platform_widget.mojom b/third_party/blink/public/mojom/widget/platform_widget.mojom index c4fe956..50071a7 100644 --- a/third_party/blink/public/mojom/widget/platform_widget.mojom +++ b/third_party/blink/public/mojom/widget/platform_widget.mojom @@ -37,6 +37,10 @@ interface WidgetHost { // location of a pointing device. SetCursor(ui.mojom.Cursor cursor); + [EnableIf=is_tizen_tv] + //Browser edge scroll + DidEdgeScrollBy(gfx.mojom.Point offset, bool handled); + // Sent by a widget to the browser to set the tooltip text for the current // cursor position. An empty |tooltip_text| will hide the tooltip view. UpdateTooltipUnderCursor(mojo_base.mojom.String16 tooltip_text, diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index 15a28ca..5a25218 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h @@ -43,6 +43,7 @@ #include "third_party/blink/public/platform/cross_variant_mojo_util.h" #include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h" #include "third_party/blink/public/platform/web_common.h" +#include "third_party/blink/renderer/core/scroll/scroll_types.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/display/mojom/screen_orientation.mojom-shared.h" @@ -488,6 +489,11 @@ class BLINK_EXPORT WebView { virtual bool IsVideoHoleForRender() const = 0; #endif +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + virtual bool EdgeScrollBy(const ScrollOffset&, const gfx::Point&) = 0; +#endif + // Misc ------------------------------------------------------------- // Returns the number of live WebView instances in this process. 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 74b18e9..316ae20 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc @@ -4338,4 +4338,37 @@ bool WebViewImpl::IsVideoHoleForRender() const { return GetPage()->GetSettings().GetVideoHoleEnabled(); } #endif + +#if BUILDFLAG(IS_TIZEN_TV) +bool WebViewImpl::EdgeScrollBy(const ScrollOffset& scroll_offset, + const gfx::Point& mouse_point) { + if (!MainFrameImpl()) + return false; + const LocalFrameView* view = MainFrameImpl()->GetFrameView(); + if (!view) + return false; + + LayoutView* const layout_view = view->GetLayoutView(); + if (!layout_view) + return false; + + const gfx::Point point(mouse_point); + HitTestLocation location(point); + const HitTestRequest request(HitTestRequest::kReadOnly | + HitTestRequest::kAllowChildFrameContent); + HitTestResult result(request, location); + + layout_view->HitTest(location, result); + + const LocalFrame* frame = result.InnerNodeFrame(); + if (!frame) { + frame = DynamicTo( + page_->GetFocusController().FocusedOrMainFrame()); + } + + return frame->GetEventHandler().ScrollWithMultiplier(scroll_offset, + result.InnerNode()); +} +#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 cd72cea..952342b 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h @@ -629,6 +629,11 @@ class CORE_EXPORT WebViewImpl final : public WebView, bool IsVideoHoleForRender() const override; #endif +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + bool EdgeScrollBy(const ScrollOffset&, const gfx::Point&) override; +#endif + private: FRIEND_TEST_ALL_PREFIXES(WebFrameTest, DivScrollIntoEditableTest); FRIEND_TEST_ALL_PREFIXES(WebFrameTest, 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 43bc449..b0ae6e6 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 @@ -1301,6 +1301,18 @@ void WebFrameWidgetImpl::Trace(Visitor* visitor) const { visitor->Trace(device_emulator_); } +#if BUILDFLAG(IS_TIZEN_TV) +void WebFrameWidgetImpl::EdgeScrollBy(const gfx::Point& offset, const gfx::Point& mouse_position) { + bool handled = false; + WebViewImpl* webview = View(); + if (webview) + handled = webview->EdgeScrollBy( + blink::ScrollOffset(offset.x(), offset.y()), + gfx::Point(mouse_position.x(), mouse_position.y())); + widget_base_->DidEdgeScrollBy(offset, handled); +} +#endif + void WebFrameWidgetImpl::SetNeedsRecalculateRasterScales() { if (!View()->does_composite()) return; 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 abb3c99..764b26a 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 @@ -791,6 +791,11 @@ class CORE_EXPORT WebFrameWidgetImpl GetStringAtPointCallback callback) override; #endif +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + void EdgeScrollBy(const gfx::Point& offset, const gfx::Point& mouse_position) override; +#endif + // mojom::blink::FrameWidgetInputHandler overrides. void AddImeTextSpansToExistingText( uint32_t start, diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index d451ade..9ef05a6 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc @@ -1402,6 +1402,53 @@ void EventHandler::ClearDragState() { should_only_fire_drag_over_event_ = false; } +#if BUILDFLAG(IS_TIZEN_TV) +bool EventHandler::ScrollNewPosition(const ScrollOffset& scroll_offset, + LocalFrameView* frame_view) { + ScrollableArea* const scrollable_area = frame_view->LayoutViewport(); + if (!scrollable_area) + return false; + + gfx::PointF ori_point = scrollable_area->ScrollPosition(); + scrollable_area->ScrollBy(scroll_offset, mojom::blink::ScrollType::kUser); + gfx::PointF new_point = scrollable_area->ScrollPosition(); + return new_point != ori_point; +} + +bool EventHandler::ScrollWithMultiplier(const ScrollOffset& scroll_offset, + Node* start_node) { + LocalFrame* frame = frame_; + while (frame) { + mojom::blink::ScrollDirection vertical_direction = + (scroll_offset.y() < 0) + ? mojom::blink::ScrollDirection::kScrollUpIgnoringWritingMode + : mojom::blink::ScrollDirection::kScrollDownIgnoringWritingMode; + mojom::blink::ScrollDirection horizontal_direction = + (scroll_offset.x() < 0) + ? mojom::blink::ScrollDirection::kScrollLeftIgnoringWritingMode + : mojom::blink::ScrollDirection::kScrollRightIgnoringWritingMode; + if (scroll_manager_->LogicalScroll( + vertical_direction, ui::ScrollGranularity::kScrollByPixel, start_node, + nullptr, std::abs(scroll_offset.y()))) + return true; + + if (scroll_manager_->LogicalScroll( + horizontal_direction, ui::ScrollGranularity::kScrollByPixel, start_node, + nullptr, std::abs(scroll_offset.x()))) + return true; + + LocalFrameView* frame_view = frame->View(); + if (frame_view && ScrollNewPosition(scroll_offset, frame_view)) + return true; + + frame = DynamicTo(frame->Tree().Parent()); + if (frame) + start_node = frame->DeprecatedLocalOwner(); + } + return false; +} +#endif + void EventHandler::AnimateSnapFling(base::TimeTicks monotonic_time) { scroll_manager_->AnimateSnapFling(monotonic_time); } diff --git a/third_party/blink/renderer/core/input/event_handler.h b/third_party/blink/renderer/core/input/event_handler.h index 6f7855e..60c2c70 100644 --- a/third_party/blink/renderer/core/input/event_handler.h +++ b/third_party/blink/renderer/core/input/event_handler.h @@ -269,6 +269,11 @@ class CORE_EXPORT EventHandler final : public GarbageCollected { // canceled. void ClearDragState(); +#if BUILDFLAG(IS_TIZEN_TV) + bool ScrollNewPosition(const ScrollOffset&, LocalFrameView*); + bool ScrollWithMultiplier(const ScrollOffset&, Node*); +#endif + EventHandlerRegistry& GetEventHandlerRegistry() const { return *event_handler_registry_; } diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc index c1f2ac4..850c181 100644 --- a/third_party/blink/renderer/core/input/scroll_manager.cc +++ b/third_party/blink/renderer/core/input/scroll_manager.cc @@ -318,7 +318,8 @@ bool ScrollManager::CanScroll(const ScrollState& scroll_state, bool ScrollManager::LogicalScroll(mojom::blink::ScrollDirection direction, ui::ScrollGranularity granularity, Node* start_node, - Node* mouse_press_node) { + Node* mouse_press_node, + float data) { Node* node = start_node; if (!node) @@ -406,8 +407,7 @@ bool ScrollManager::LogicalScroll(mojom::blink::ScrollDirection direction, WrapWeakPersistent(scrollable_area))); ScrollResult result = scrollable_area->UserScroll( granularity, - ToScrollDelta(physical_direction, - ScrollableArea::DirectionBasedScrollDelta(granularity)), + ToScrollDelta(physical_direction, data), std::move(callback)); if (result.DidScroll()) diff --git a/third_party/blink/renderer/core/input/scroll_manager.h b/third_party/blink/renderer/core/input/scroll_manager.h index a0ee9e7..576d519 100644 --- a/third_party/blink/renderer/core/input/scroll_manager.h +++ b/third_party/blink/renderer/core/input/scroll_manager.h @@ -71,7 +71,8 @@ class CORE_EXPORT ScrollManager : public GarbageCollected, bool LogicalScroll(mojom::blink::ScrollDirection, ui::ScrollGranularity, Node* start_node, - Node* mouse_press_node); + Node* mouse_press_node, + float data = 1.0); // Performs a logical scroll that chains, crossing frames, starting from // the given node or a reasonable default (focus/last clicked). diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index 8c2556c..a699184 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc @@ -1014,6 +1014,12 @@ void WidgetBase::SetCursor(const ui::Cursor& cursor) { } } +#if BUILDFLAG(IS_TIZEN_TV) +void WidgetBase::DidEdgeScrollBy(const gfx::Point& offset, bool handled) { + widget_host_->DidEdgeScrollBy(offset, handled); +} +#endif + void WidgetBase::UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir) { widget_host_->UpdateTooltipUnderCursor( diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h index 485070f..ad55f28 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.h +++ b/third_party/blink/renderer/platform/widget/widget_base.h @@ -239,6 +239,11 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget, WidgetBaseClient* client() { return client_; } +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + void DidEdgeScrollBy(const gfx::Point& offset, bool handled); +#endif + void UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir); // This function allows us to trigger a tooltip to show from a keypress. The // tooltip will be positioned relative to the gfx::Rect. That rect corresponds diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc index 283d714..0f7e55a 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc @@ -369,6 +369,13 @@ void RWHVAuraCommonHelperEfl::FocusedNodeChanged( is_focused_node_editable_ = editable; } +#if BUILDFLAG(IS_TIZEN_TV) +void RWHVAuraCommonHelperEfl::DidEdgeScrollBy(const gfx::Point& offset, + bool handled) { + web_contents_->GetDelegate()->DidEdgeScrollBy(offset, handled); +} +#endif + void RWHVAuraCommonHelperEfl::OnGetMainFrameScrollbarVisible( int callback_id, bool visible) { web_contents_->GetDelegate()->OnGetMainFrameScrollbarVisible(callback_id, diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.h index 4f7c79b..53c5d14 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.h @@ -102,6 +102,11 @@ class CONTENT_EXPORT RWHVAuraCommonHelperEfl { #endif bool is_content_editable); +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + void DidEdgeScrollBy(const gfx::Point& offset, bool handled) ; +#endif + void OnGestureEvent(ui::GestureEvent* event); void DidChangeInputType(bool is_password_field); void BackgroundColorReceived(int callback_id, SkColor bg_color); diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 48136a4..d7a964d 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -354,6 +354,7 @@ EWebView::EWebView(Ewk_Context* context, Evas_Object* object) x_delta_(0.0), y_delta_(0.0), #if BUILDFLAG(IS_TIZEN_TV) + is_processing_edge_scroll_(false), use_early_rwi_(false), rwi_info_showed_(false), #endif @@ -2604,6 +2605,73 @@ void EWebView::SyncAcceptLanguages(const std::string& accept_languages) { network_context->SetAcceptLanguage(accept_languages); } +#if BUILDFLAG(IS_TIZEN_TV) +bool EWebView::EdgeScrollBy(int delta_x, int delta_y) { + if ((delta_x == 0 && delta_y == 0) || is_processing_edge_scroll_) + return false; + + RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); + if (!render_view_host) + return false; + + if (!rwhva()) + return false; + + gfx::Point offset = gfx::Point(delta_x, delta_y); + gfx::Point mouse_position; + GetMousePosition(mouse_position); + is_processing_edge_scroll_ = true; + + static_cast(render_view_host) + ->GetWidget() + ->GetAssociatedFrameWidget() + ->EdgeScrollBy(offset, mouse_position); + return true; +} + +void EWebView::GetMousePosition(gfx::Point& mouse_position) { + int mouse_x, mouse_y; + evas_pointer_output_xy_get(GetEvas(), &mouse_x, &mouse_y); + Evas_Coord x, y, width, height; + evas_object_geometry_get(evas_object(), &x, &y, &width, &height); + + if (mouse_y < y) + mouse_y = y + 1; + else if (mouse_y > y + height) + mouse_y = y + height - 1; + if (mouse_x < x) + mouse_x = x + 1; + else if (mouse_x > x + width) + mouse_x = x + width - 1; + + mouse_x -= x; + mouse_y -= y; + + mouse_x /= + display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); + mouse_y /= + display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(); + + mouse_position.set_x(mouse_x); + mouse_position.set_y(mouse_y); +} + +void EWebView::InvokeEdgeScrollByCallback(const gfx::Point& offset, + bool handled) { + is_processing_edge_scroll_ = false; + + if (offset.x() < 0) + SmartCallback().call(&handled); + else if (offset.x() > 0) + SmartCallback().call(&handled); + + if (offset.y() < 0) + SmartCallback().call(&handled); + else if (offset.y() > 0) + SmartCallback().call(&handled); +} +#endif + void EWebView::HandleRendererProcessCrash() { content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce(&EWebView::InvokeWebProcessCrashedCallback, diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 05c7ef4..470e070 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -688,6 +688,13 @@ class EWebView { void ReplyBeforeUnloadConfirmPanel(Eina_Bool result); void SyncAcceptLanguages(const std::string& accept_languages); +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + bool EdgeScrollBy(int delta_x, int delta_y); + void GetMousePosition(gfx::Point&); + void InvokeEdgeScrollByCallback(const gfx::Point&, bool); +#endif + void OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll, const gfx::Vector2dF& latest_overscroll_delta); @@ -922,6 +929,7 @@ class EWebView { bool is_initialized_; #if BUILDFLAG(IS_TIZEN_TV) + bool is_processing_edge_scroll_; bool use_early_rwi_; bool rwi_info_showed_; GURL rwi_gurl_; diff --git a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h index 1e57776..be7eaf7 100644 --- a/tizen_src/ewk/efl_integration/eweb_view_callbacks.h +++ b/tizen_src/ewk/efl_integration/eweb_view_callbacks.h @@ -115,6 +115,10 @@ enum CallbackType { EdgeTop, EdgeBottom, #if BUILDFLAG(IS_TIZEN_TV) + EdgeScrollBottom, + EdgeScrollLeft, + EdgeScrollRight, + EdgeScrollTop, DeviceConnectionChanged, PlaybackLoad, PlaybackVideoReady, @@ -281,6 +285,10 @@ DECLARE_EWK_VIEW_CALLBACK(EdgeTop, "edge,top", void); DECLARE_EWK_VIEW_CALLBACK(EdgeBottom, "edge,bottom", void); DECLARE_EWK_VIEW_CALLBACK(EdgeRight, "edge,right", void); #if BUILDFLAG(IS_TIZEN_TV) +DECLARE_EWK_VIEW_CALLBACK(EdgeScrollBottom, "edge,scroll,bottom", bool*); +DECLARE_EWK_VIEW_CALLBACK(EdgeScrollLeft, "edge,scroll,left", bool*); +DECLARE_EWK_VIEW_CALLBACK(EdgeScrollRight, "edge,scroll,right", bool*); +DECLARE_EWK_VIEW_CALLBACK(EdgeScrollTop, "edge,scroll,top", bool*); DECLARE_EWK_VIEW_CALLBACK(DeviceConnectionChanged, "device,connection,changed", int*); diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index f699d14..ef55aff 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -1546,7 +1546,14 @@ void ewk_view_clear_all_tiles_resources(Evas_Object* ewkView) { Eina_Bool ewk_view_edge_scroll_by(Evas_Object *ewkView, int dx, int dy) { LOG_EWK_API_MOCKUP(); +#if BUILDFLAG(IS_TIZEN_TV) + EWK_VIEW_IMPL_GET_OR_RETURN(ewkView, impl, EINA_FALSE); + LOG(INFO) << "view: " << ewkView << ", dx:" << dx << ", dy:" << dy; + return impl->EdgeScrollBy(dx, dy); +#else + LOG_EWK_API_MOCKUP("edge_scroll_by feature is not enabled"); return EINA_FALSE; +#endif } Eina_Bool ewk_view_set_support_video_hole(Evas_Object* ewkView, 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 fd2eae8..c6dee1d 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -762,4 +762,12 @@ void WebContentsDelegateEfl::OnGetMainFrameScrollbarVisible(int callback_id, bool visible) { web_view_->InvokeMainFrameScrollbarVisibleCallback(callback_id, visible); } + +#if BUILDFLAG(IS_TIZEN_TV) +void WebContentsDelegateEfl::DidEdgeScrollBy(const gfx::Point& offset, + bool handled) { + if (web_view_) + web_view_->InvokeEdgeScrollByCallback(offset, handled); +} +#endif } // namespace content diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h index 91c0994..44cc7dd 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h @@ -69,6 +69,11 @@ class WebContentsDelegateEfl : public WebContentsDelegate { void DidChangeInputType(bool is_password_input) override; void OnGetMainFrameScrollbarVisible(int callback_id, bool visible) override; + +#if BUILDFLAG(IS_TIZEN_TV) + //Browser edge scroll + void DidEdgeScrollBy(const gfx::Point& offset, bool handled) override; +#endif void RequestCertificateConfirm( WebContents* web_contents, int cert_error, diff --git a/tizen_src/ewk/unittest/BUILD.gn b/tizen_src/ewk/unittest/BUILD.gn index e19c4a4..e4fd33b 100644 --- a/tizen_src/ewk/unittest/BUILD.gn +++ b/tizen_src/ewk/unittest/BUILD.gn @@ -317,6 +317,7 @@ test("ewk_unittests") { "utc_blink_ewk_view_custom_header_remove_func.cpp", "utc_blink_ewk_view_did_change_theme_color_callback_set_func.cpp", "utc_blink_ewk_view_draws_transparent_background_set_func.cpp", + "utc_blink_ewk_view_edge_scroll_by_func.cpp", "utc_blink_ewk_view_encoding_custom_set_func.cpp", "utc_blink_ewk_view_forward_func.cpp", "utc_blink_ewk_view_forward_possible_func.cpp", diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_view_edge_scroll_by_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_view_edge_scroll_by_func.cpp new file mode 100644 index 0000000..e2b5474 --- /dev/null +++ b/tizen_src/ewk/unittest/utc_blink_ewk_view_edge_scroll_by_func.cpp @@ -0,0 +1,147 @@ +// Copyright 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 "utc_blink_ewk_base.h" + +class utc_blink_ewk_view_edge_scroll_by : public utc_blink_ewk_base { + protected: + enum OrientaionType { Left, Right, Top, Bottom }; + + static void EdgeLeft(void* data, Evas_Object* o, void* data_finished) { + utc_message("[EdgeLeft] :: \n"); + if (data) { + auto scroll = static_cast(data); + if (scroll->orientation_ == Left) + scroll->EventLoopStop(Success); + } + } + + static void EdgeRight(void* data, Evas_Object* o, void* data_finished) { + utc_message("[EdgeRight] :: \n"); + if (data) { + auto scroll = static_cast(data); + if (scroll->orientation_ == Right) + scroll->EventLoopStop(Success); + } + } + + static void EdgeTop(void* data, Evas_Object* o, void* data_finished) { + utc_message("[EdgeTop] :: \n"); + if (data) { + auto scroll = static_cast(data); + if (scroll->orientation_ == Top) + scroll->EventLoopStop(Success); + } + } + + static void EdgeBottom(void* data, Evas_Object* o, void* data_finished) { + utc_message("[EdgeBottom] :: \n"); + if (data) { + auto scroll = static_cast(data); + if (scroll->orientation_ == Bottom) + scroll->EventLoopStop(Success); + } + } + + /* Startup function */ + void PostSetUp() override { + evas_object_smart_callback_add(GetEwkWebView(), "edge,scroll,left", + EdgeLeft, this); + evas_object_smart_callback_add(GetEwkWebView(), "edge,scroll,right", + EdgeRight, this); + evas_object_smart_callback_add(GetEwkWebView(), "edge,scroll,top", EdgeTop, + this); + evas_object_smart_callback_add(GetEwkWebView(), "edge,scroll,bottom", + EdgeBottom, this); + } + + /* Cleanup function */ + void PreTearDown() override { + evas_object_smart_callback_del(GetEwkWebView(), "edge,scroll,left", + EdgeLeft); + evas_object_smart_callback_del(GetEwkWebView(), "edge,scroll,right", + EdgeRight); + evas_object_smart_callback_del(GetEwkWebView(), "edge,scroll,top", EdgeTop); + evas_object_smart_callback_del(GetEwkWebView(), "edge,scroll,bottom", + EdgeBottom); + } + + protected: + OrientaionType orientation_; + static const char* const kResource; +}; + +const char* const utc_blink_ewk_view_edge_scroll_by::kResource = + "/ewk_view/index_big_red_square.html"; + +/** + * @brief Positive test case of ewk_view_edge_scroll_by(),testing scroll left + */ + +TEST_F(utc_blink_ewk_view_edge_scroll_by, POS_TEST_LEFT) { + ASSERT_TRUE( + ewk_view_url_set(GetEwkWebView(), GetResourceUrl(kResource).c_str())); + + const int kDeltaX = -10; + const int kDeltaY = 0; + orientation_ = Left; + + ASSERT_TRUE(ewk_view_edge_scroll_by(GetEwkWebView(), kDeltaX, kDeltaY)); + ASSERT_EQ(Success, EventLoopStart()); +} + +/** + * @brief Positive test case of ewk_view_edge_scroll_by(),testing scroll right + */ + +TEST_F(utc_blink_ewk_view_edge_scroll_by, POS_TEST_RIGHT) { + ASSERT_TRUE( + ewk_view_url_set(GetEwkWebView(), GetResourceUrl(kResource).c_str())); + + const int kDeltaX = 10; + const int kDeltaY = 0; + orientation_ = Right; + + ASSERT_TRUE(ewk_view_edge_scroll_by(GetEwkWebView(), kDeltaX, kDeltaY)); + ASSERT_EQ(Success, EventLoopStart()); +} + +/** + * @brief Positive test case of ewk_view_edge_scroll_by(),testing scroll top + */ + +TEST_F(utc_blink_ewk_view_edge_scroll_by, POS_TEST_TOP) { + ASSERT_TRUE( + ewk_view_url_set(GetEwkWebView(), GetResourceUrl(kResource).c_str())); + + const int kDeltaX = 0; + const int kDeltaY = -10; + orientation_ = Top; + + ASSERT_TRUE(ewk_view_edge_scroll_by(GetEwkWebView(), kDeltaX, kDeltaY)); + ASSERT_EQ(Success, EventLoopStart()); +} + +/** + * @brief Positive test case of ewk_view_edge_scroll_by(),testing scroll bottom + */ + +TEST_F(utc_blink_ewk_view_edge_scroll_by, POS_TEST_BOTTOM) { + ASSERT_TRUE( + ewk_view_url_set(GetEwkWebView(), GetResourceUrl(kResource).c_str())); + + const int kDeltaX = 0; + const int kDeltaY = 10; + orientation_ = Bottom; + + ASSERT_TRUE(ewk_view_edge_scroll_by(GetEwkWebView(), kDeltaX, kDeltaY)); + ASSERT_EQ(Success, EventLoopStart()); +} + +/** + * @brief Negative test case of ewk_view_edge_scroll_by(), testing for null + */ +TEST_F(utc_blink_ewk_view_edge_scroll_by, NEG_TEST) { + EXPECT_EQ(EINA_FALSE, ewk_view_edge_scroll_by(NULL, 1916, 1993)); +} -- 2.7.4 From 9a64b34bc71f54322e84a3aa018cfbe990c0108b Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Tue, 21 Mar 2023 14:28:22 +0530 Subject: [PATCH 06/16] [M108 Migration][Loading Performance] Add cache for mismatched SkTypeface |matchFamilyName| is always called in |onLegacyCreateTypeface| to match font. Because |SkTypeFaceCache| doesn't support for mismatched typeface. |matchFamilyName| takes a long time (at least 1ms~). This patch caches the mismatched SkTypeface and reduces the number of |matchFamilyName| calls. Hence, this patch improves loading performance. Reference: https://review.tizen.org/gerrit/268117 Change-Id: Ie2697394c45affcb95d600f3faad84d39a06c6a3 Signed-off-by: Gajendra N --- third_party/skia/src/core/SkTypefaceCache.cpp | 35 ++++++++++++++++++++++ third_party/skia/src/core/SkTypefaceCache.h | 16 ++++++++++ .../src/ports/SkFontMgr_FontConfigInterface.cpp | 9 ++++++ 3 files changed, 60 insertions(+) diff --git a/third_party/skia/src/core/SkTypefaceCache.cpp b/third_party/skia/src/core/SkTypefaceCache.cpp index 3272d6a..f9874dd 100644 --- a/third_party/skia/src/core/SkTypefaceCache.cpp +++ b/third_party/skia/src/core/SkTypefaceCache.cpp @@ -11,6 +11,10 @@ #define TYPEFACE_CACHE_LIMIT 1024 +#if defined(USE_SK_MISMATCH_CACHE) +#define MISMATCH_FONT_CACHE_LIMIT 64 +#endif + SkTypefaceCache::SkTypefaceCache() {} void SkTypefaceCache::add(sk_sp face) { @@ -50,6 +54,37 @@ void SkTypefaceCache::purgeAll() { this->purge(fTypefaces.count()); } +#if defined(USE_SK_MISMATCH_CACHE) +void SkTypefaceCache::addMismatch(const char* requestedFamily) { + if (fMismatches.count() >= MISMATCH_FONT_CACHE_LIMIT) { + this->purgeMismatch(MISMATCH_FONT_CACHE_LIMIT >> 2); + } + + fMismatches.emplace_back(SkString(requestedFamily)); +} + +bool SkTypefaceCache::findMismatch(const char* requestedFamily) { + for (const SkString& mismatch : fMismatches) { + if (mismatch.equals(requestedFamily)) { + return true; + } + } + return false; +} + +void SkTypefaceCache::purgeMismatch(int numToPurge) { + int count = fMismatches.count(); + int i = 0; + while (i < count) { + fMismatches.removeShuffle(i); + --count; + if (--numToPurge == 0) { + return; + } + } +} +#endif + /////////////////////////////////////////////////////////////////////////////// SkTypefaceCache& SkTypefaceCache::Get() { diff --git a/third_party/skia/src/core/SkTypefaceCache.h b/third_party/skia/src/core/SkTypefaceCache.h index 80bc341..69fabab 100644 --- a/third_party/skia/src/core/SkTypefaceCache.h +++ b/third_party/skia/src/core/SkTypefaceCache.h @@ -14,6 +14,12 @@ #include "include/core/SkTypeface.h" #include "include/private/SkTArray.h" +#include "build/build_config.h" + +#if BUILDFLAG(IS_EFL) +#define USE_SK_MISMATCH_CACHE +#endif + class SkTypefaceCache { public: SkTypefaceCache(); @@ -38,6 +44,12 @@ public: */ sk_sp findByProcAndRef(FindProc proc, void* ctx) const; +#if defined(USE_SK_MISMATCH_CACHE) + void addMismatch(const char*); + bool findMismatch(const char*); + void purgeMismatch(int numToPurge); +#endif + /** * This will unref all of the typefaces in the cache for which the cache * is the only owner. Normally this is handled automatically as needed. @@ -69,6 +81,10 @@ private: void purge(int count); SkTArray> fTypefaces; + +#if defined(USE_SK_MISMATCH_CACHE) + SkTArray fMismatches; +#endif }; #endif diff --git a/third_party/skia/src/ports/SkFontMgr_FontConfigInterface.cpp b/third_party/skia/src/ports/SkFontMgr_FontConfigInterface.cpp index 33778e3..3dc5936 100644 --- a/third_party/skia/src/ports/SkFontMgr_FontConfigInterface.cpp +++ b/third_party/skia/src/ports/SkFontMgr_FontConfigInterface.cpp @@ -302,12 +302,21 @@ protected: return sk_sp(face); } +#if defined(USE_SK_MISMATCH_CACHE) + if (fTFCache.findMismatch(requestedFamilyName)) { + return nullptr; + } +#endif + SkFontConfigInterface::FontIdentity identity; SkString outFamilyName; SkFontStyle outStyle; if (!fFCI->matchFamilyName(requestedFamilyName, requestedStyle, &identity, &outFamilyName, &outStyle)) { +#if defined(USE_SK_MISMATCH_CACHE) + fTFCache.addMismatch(requestedFamilyName); +#endif return nullptr; } -- 2.7.4 From cb359988e5c2483730d60699884f4803811284a9 Mon Sep 17 00:00:00 2001 From: Michal Jurkiewicz Date: Thu, 4 Mar 2021 11:27:39 +0100 Subject: [PATCH 07/16] [M108 Migration][Build system] Fix desktop build break Ported patch from tizen_7.0: https://review.tizen.org/gerrit/c/platform/framework/web/chromium-efl/+/273992 Bug: https://cam.sprc.samsung.pl/browse/VDWASM-1212 Change-Id: Ibe04d0d760152080566638d6569705c5ee960e91 Signed-off-by: Michal Jurkiewicz --- tizen_src/build/common.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tizen_src/build/common.sh b/tizen_src/build/common.sh index 4853132..2635217 100755 --- a/tizen_src/build/common.sh +++ b/tizen_src/build/common.sh @@ -188,6 +188,7 @@ function hostGnChromiumEfl() { } function hostNinja() { + local RESULT=0 if [[ $SKIP_NINJA == 0 ]]; then if [[ $BUILD_CHROME == 1 ]]; then TARGETS="content_shell chrome" @@ -203,8 +204,13 @@ function hostNinja() { export BUILD_SUBDIRECTORY="" BUILDDIR=${GN_GENERATOR_OUTPUT}/${BUILD_SUBDIRECTORY} ninja -C $BUILDDIR ${JOBS} ${TARGETS} + RESULT=$? fi undoReplacedGn $1 + + if [[ $RESULT != 0 ]]; then + exit $RESULT + fi } function error_report() { @@ -386,9 +392,14 @@ function setupAndExecuteTargetBuild() { processICU initialize_icu gbs $CONF_FLAG build -P $PROFILE --include-all -A $ARCHITECTURE "${ARGS[@]}" $BUILD_CONF_OPTS --incremental $GBS_ROOT_OPT + local RESULT=$? undoReplacedGn $platform processICU restore_icu + + if [[ $RESULT != 0 ]]; then + exit $RESULT + fi } function processICU() { -- 2.7.4 From 57e2a07c1c09af72c85c76f0ca354b38aae409e0 Mon Sep 17 00:00:00 2001 From: pengxia Date: Fri, 17 Mar 2023 13:32:58 +0800 Subject: [PATCH 08/16] [M108 Aura Migration][NaCl][PPFW] Fix memory leaks when reloading iframe Leaks of PepperHelper class instances. Class PepperHelper is created in ContentRendererClientEfl::RenderFrameCreated it should be deleted together with render frame for which was created. Removal of RenderFrame is signalized by call to OnDestruct method. In case of PepperHelper this method is empty. This patch adds proper implementation of this method to avoid leak. from 94 Aura Patch: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/280196/ Change-Id: I7aeaec172acab137e1e5d193a087de0248edaf23 Signed-off-by: pengxia --- tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc | 4 ++++ tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc index f065a12..757e1d6 100644 --- a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc +++ b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.cc @@ -32,4 +32,8 @@ void PepperHelper::DidCreatePepperPlugin(content::RendererPpapiHost* host) { host->GetPpapiHost()->AddInstanceMessageFilter( std::make_unique(host)); } +void PepperHelper::OnDestruct() { + delete this; +} + } // namespace pepper \ No newline at end of file diff --git a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h index 7b4cafe..0785413 100644 --- a/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h +++ b/tizen_src/ewk/efl_integration/renderer/pepper/pepper_helper.h @@ -22,7 +22,7 @@ class PepperHelper : public content::RenderFrameObserver { // RenderFrameObserver. void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; - void OnDestruct(){}; + void OnDestruct() override; }; } // namespace pepper #endif // RENDERER_PEPPER_PEPPER_HELPER_H_ -- 2.7.4 From a6118bf44ce40fa6d9721c244bf8e7b8a16fc6d6 Mon Sep 17 00:00:00 2001 From: chenhuasheng Date: Wed, 15 Mar 2023 17:31:01 +0800 Subject: [PATCH 09/16] [M108 Migration][API] Fix the webview transparency related API Webview transparency was not applied in the below APIs. ewk_view_draws_transparent_background_set ewk_view_draws_transparent_background_get ewk_view_bg_color_set This patch implement ewk_view_bg_color_set to set the background color and fixes that the application can set webview transparency using the above APIs ref: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/270944/ Change-Id: I86a9d9791f1a00ef328e81859fc2048c21072539 Signed-off-by: chenhuasheng --- .../browser/web_contents/web_contents_view_aura.h | 7 +++ third_party/blink/public/mojom/page/widget.mojom | 6 ++ .../renderer/core/frame/web_frame_widget_impl.cc | 27 +++++++++ .../renderer/core/frame/web_frame_widget_impl.h | 8 +++ tizen_src/ewk/efl_integration/eweb_view.cc | 64 ++++++++++++++++++++-- tizen_src/ewk/efl_integration/eweb_view.h | 5 +- tizen_src/ewk/efl_integration/public/ewk_view.cc | 16 ++++-- 7 files changed, 120 insertions(+), 13 deletions(-) diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h index 7e4abc8..f824e8f 100644 --- a/content/browser/web_contents/web_contents_view_aura.h +++ b/content/browser/web_contents/web_contents_view_aura.h @@ -38,6 +38,10 @@ #include "content/browser/web_contents/web_contents_view_aura_helper_efl.h" #endif +#if BUILDFLAG(IS_TIZEN) +#include "third_party/skia/include/core/SkColor.h" +#endif + namespace ui { class DropTargetEvent; class TouchSelectionController; @@ -88,6 +92,8 @@ class CONTENT_EXPORT WebContentsViewAura #if BUILDFLAG(IS_TIZEN) int GetOrientation() { return orientation_; } + void SetBackgroundColor(SkColor color) { background_color_ = color; } + SkColor GetBackgroundColor() const { return background_color_; } #endif private: @@ -418,6 +424,7 @@ class CONTENT_EXPORT WebContentsViewAura #if BUILDFLAG(IS_TIZEN) int orientation_ = 0; + SkColor background_color_ = SK_ColorWHITE; #endif base::WeakPtrFactory weak_ptr_factory_{this}; diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom index f7feae5..35aa492 100644 --- a/third_party/blink/public/mojom/page/widget.mojom +++ b/third_party/blink/public/mojom/page/widget.mojom @@ -152,6 +152,12 @@ interface FrameWidget { [EnableIf=is_tizen_tv] //Browser edge scroll EdgeScrollBy(gfx.mojom.Point offset, gfx.mojom.Point mouse_position); + + [EnableIf=is_tizen] + SetDrawsTransparentBackground(bool draws_transparent_background); + + [EnableIf=is_tizen] + SetBackgroundColor(int32 red, int32 green, int32 blue, int32 alpha); }; // Implemented in Browser, this interface defines frame-widget-specific methods that 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 b0ae6e6..d6b3018 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 @@ -4716,4 +4716,31 @@ void WebFrameWidgetImpl::NotifyKeyEvent(WebInputEvent::Type type, } #endif +#if BUILDFLAG(IS_TIZEN) +void WebFrameWidgetImpl::SetDrawsTransparentBackground( + bool draws_transparent_background) { + WebViewImpl* webview = View(); + if (!webview) + return; + + SkColor backgroundColor = draws_transparent_background + ? static_cast(0x00000000) + : static_cast(0xFFFFFFFF); + + webview->SetPageBaseBackgroundColor(absl::make_optional(backgroundColor)); +} + +void WebFrameWidgetImpl::SetBackgroundColor(int32_t red, + int32_t green, + int32_t blue, + int32_t alpha) { + WebViewImpl* webview = View(); + if (!webview) + return; + + SkColor backgroundColor = SkColorSetARGB(alpha, red, green, blue); + webview->SetPageBaseBackgroundColor(absl::make_optional(backgroundColor)); +} +#endif + } // namespace blink 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 764b26a..80cc841 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 @@ -641,6 +641,14 @@ class CORE_EXPORT WebFrameWidgetImpl #if BUILDFLAG(IS_TIZEN) void SetMaxRefreshRate(uint32_t max_refresh_rate) override; + + void SetDrawsTransparentBackground( + bool draws_transparent_background) override; + + void SetBackgroundColor(int32_t red, + int32_t green, + int32_t blue, + int32_t alpha) override; #endif #if BUILDFLAG(IS_TIZEN) diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index d7a964d..c0247ca 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -2358,14 +2358,66 @@ void EWebView::GetPageScaleRange(double* min_scale, double* max_scale) { *max_scale = prefs.default_maximum_page_scale_factor; } -void EWebView::SetDrawsTransparentBackground(bool enabled) { +content::WebContentsViewAura* EWebView::GetWebContentsViewAura() const { + WebContentsImpl* wc = static_cast(web_contents_.get()); + return static_cast(wc->GetView()); +} + +bool EWebView::SetDrawsTransparentBackground(bool enabled) { RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); - if (!render_view_host) - return; -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - render_view_host->Send(new EwkViewMsg_SetDrawsTransparentBackground( - render_view_host->GetRoutingID(), enabled)); + if (!render_view_host || !rwhva()) + return false; + +#if BUILDFLAG(IS_EFL) + if (!rwhva()->offscreen_helper()) + return false; + elm_object_style_set(rwhva()->offscreen_helper()->content_image_elm_host(), + enabled ? "transparent" : "default"); + evas_object_image_alpha_set(rwhva()->offscreen_helper()->content_image(), + enabled); +#endif + + GetWebContentsViewAura()->SetBackgroundColor(enabled ? SK_ColorTRANSPARENT + : SK_ColorWHITE); + static_cast(render_view_host) + ->GetWidget() + ->GetAssociatedFrameWidget() + ->SetDrawsTransparentBackground(enabled); + rwhva()->SetBackgroundColor(enabled ? SK_ColorTRANSPARENT : SK_ColorWHITE); + + return true; +} + +bool EWebView::GetDrawsTransparentBackground() { + return GetWebContentsViewAura()->GetBackgroundColor() == SK_ColorTRANSPARENT; +} + +bool EWebView::SetBackgroundColor(int red, int green, int blue, int alpha) { + if (!alpha) + return SetDrawsTransparentBackground(true); + + RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); + if (!render_view_host || !rwhva()) + return false; + +#if BUILDFLAG(IS_EFL) + if (!rwhva()->offscreen_helper()) + return false; + elm_object_style_set(rwhva()->offscreen_helper()->content_image_elm_host(), + alpha < 255 ? "transparent" : "default"); + evas_object_image_alpha_set(rwhva()->offscreen_helper()->content_image(), + alpha < 255); #endif + + GetWebContentsViewAura()->SetBackgroundColor( + SkColorSetARGB(alpha, red, green, blue)); + static_cast(render_view_host) + ->GetWidget() + ->GetAssociatedFrameWidget() + ->SetBackgroundColor(red, green, blue, alpha); + rwhva()->SetBackgroundColor(SkColorSetARGB(alpha, red, green, blue)); + + return true; } void EWebView::GetSessionData(const char** data, unsigned* length) const { diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 470e070..a5b33d5 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -319,6 +319,7 @@ class EWebView { } content::WebContents& web_contents() const { return *web_contents_.get(); } + content::WebContentsViewAura* GetWebContentsViewAura() const; #if defined(TIZEN_ATK_SUPPORT) EWebAccessibility& eweb_accessibility() const { @@ -577,7 +578,9 @@ class EWebView { void JavaScriptPromptReply(const char* result); void set_renderer_crashed(); void GetPageScaleRange(double* min_scale, double* max_scale); - void SetDrawsTransparentBackground(bool enabled); + bool SetDrawsTransparentBackground(bool enabled); + bool GetDrawsTransparentBackground(); + bool SetBackgroundColor(int red, int green, int blue, int alpha); bool GetBackgroundColor(Ewk_View_Background_Color_Get_Callback callback, void* user_data); void OnGetBackgroundColor(int callback_id, SkColor bg_color); diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index ef55aff..af9ed6d 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -1027,8 +1027,7 @@ Eina_Bool ewk_view_fullscreen_exit(Evas_Object* view) Eina_Bool ewk_view_draws_transparent_background_set(Evas_Object *view, Eina_Bool enabled) { EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, EINA_FALSE); - impl->SetDrawsTransparentBackground(enabled); - return EINA_TRUE; + return impl->SetDrawsTransparentBackground(!!enabled); } void ewk_view_browser_font_set(Evas_Object* ewkView) @@ -1200,8 +1199,8 @@ Evas_Object* ewk_view_widget_get(Evas_Object* view) Eina_Bool ewk_view_draws_transparent_background_get(Evas_Object* o) { - LOG_EWK_API_MOCKUP(); - return false; + EWK_VIEW_IMPL_GET_OR_RETURN(o, impl, EINA_FALSE); + return impl->GetDrawsTransparentBackground(); } Eina_Bool ewk_view_did_change_theme_color_callback_set( @@ -1517,8 +1516,13 @@ void ewk_view_app_installation_request_callback_set(Evas_Object* o, Ewk_App_Inst } Eina_Bool ewk_view_bg_color_set(Evas_Object* o, int r, int g, int b, int a) { - LOG_EWK_API_MOCKUP("This will be implemented soon"); - return false; + EWK_VIEW_IMPL_GET_OR_RETURN(o, impl, EINA_FALSE); + if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || + a > 255) { + LOG(ERROR) << "Invalid background color"; + return EINA_FALSE; + } + return impl->SetBackgroundColor(r, g, b, a); } Eina_Bool ewk_view_key_events_enabled_set(Evas_Object* o, Eina_Bool enabled) { -- 2.7.4 From ca03b6379d48ed1bbf7989812cb01d89da7a4886 Mon Sep 17 00:00:00 2001 From: pengxia Date: Thu, 9 Mar 2023 14:46:03 +0800 Subject: [PATCH 10/16] [M108 Aura Migration][NaCl][PPAPI] Fix crash related to Pepper Var object and ~VarTracker Fix crash while releasing null Pepper Var object. Fixed crash in ~VarTracker when VarDictionary is tracked. Patch ported from M94: https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/280664/ Change-Id: Ia2a222dfa46ab7998b4f70bcb9656db327fd5d25 Signed-off-by: pengxia --- ppapi/shared_impl/var_tracker.cc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/ppapi/shared_impl/var_tracker.cc b/ppapi/shared_impl/var_tracker.cc index 3100e1d..ba08998 100644 --- a/ppapi/shared_impl/var_tracker.cc +++ b/ppapi/shared_impl/var_tracker.cc @@ -30,7 +30,16 @@ VarTracker::VarTracker(ThreadMode thread_mode) : last_var_id_(0) { thread_checker_ = std::make_unique(); } -VarTracker::~VarTracker() {} +VarTracker::~VarTracker() { +#if defined(TIZEN_PEPPER_EXTENSIONS) + // If VarDictionary is nested in live_vars_ and live_vars_ is being destroyed, + // then VarDictionary will call VarTracker::ReleaseVar. This results in + // operation on invalid live_vars_ (they are mid-destruction). Secondary map + // prevents invalid operations on live_vars_. + VarMap vars; + std::swap(vars, live_vars_); +#endif +} void VarTracker::CheckThreadingPreconditions() const { DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread()); @@ -113,6 +122,13 @@ bool VarTracker::ReleaseVar(int32_t var_id) { info.ref_count--; if (info.ref_count == 0) { +#if defined(TIZEN_PEPPER_EXTENSIONS) + if (!info.var) { + live_vars_.erase(found); + return false; + } +#endif + // Hold a reference to the Var until it is erased so that we don't re-enter // live_vars_.erase() during deletion. // TODO(raymes): Make deletion of Vars iterative instead of recursive. @@ -140,6 +156,11 @@ bool VarTracker::ReleaseVar(const PP_Var& var) { } int32_t VarTracker::AddVarInternal(Var* var, AddVarRefMode mode) { +#if defined(TIZEN_PEPPER_EXTENSIONS) + if (!var) + return 0; +#endif + // If the plugin manages to create millions of strings. if (last_var_id_ == std::numeric_limits::max() >> kPPIdTypeBits) return 0; -- 2.7.4 From 0e3561032002eabadc6d1d5cba25d8656ebb1cc9 Mon Sep 17 00:00:00 2001 From: Suhaspoornachandra Date: Wed, 22 Mar 2023 19:40:21 +0530 Subject: [PATCH 11/16] [M108 Aura Migration][WebRTC] Camera implementation related patches - Enable network camera feature. - Add remote camera and camera device manager API. - Adapt the change of camera FW. Including following patches: https://review.tizen.org/gerrit/#/c/280505/ https://review.tizen.org/gerrit/#/c/272718/ Change-Id: Iba32024cf344e5eb6a4285bb9020229ccdd249d1 Signed-off-by: Suhaspoornachandra --- .../video/video_capture_device_descriptor.h | 5 + packaging/chromium-efl.spec | 10 + tizen_src/build/config/BUILD.gn | 11 +- tizen_src/build/config/tizen_features.gni | 1 + .../capture/video/tizen/camera_device_tizen.cc | 582 ++++++++++++++++++++- .../capture/video/tizen/camera_device_tizen.h | 87 ++- .../tizen/video_capture_device_factory_tizen.cc | 49 +- .../tizen/video_capture_device_factory_tizen.h | 4 + .../video/tizen/video_capture_device_tizen.cc | 370 ++++++++++--- .../video/tizen/video_capture_device_tizen.h | 50 +- 10 files changed, 1008 insertions(+), 161 deletions(-) diff --git a/media/capture/video/video_capture_device_descriptor.h b/media/capture/video/video_capture_device_descriptor.h index 721d930..76d7a7c 100644 --- a/media/capture/video/video_capture_device_descriptor.h +++ b/media/capture/video/video_capture_device_descriptor.h @@ -8,6 +8,7 @@ #include #include +#include "build/build_config.h" #include "media/base/video_facing.h" #include "media/capture/capture_export.h" @@ -28,6 +29,10 @@ enum class VideoCaptureApi { ANDROID_API2_LIMITED, FUCHSIA_CAMERA3, VIRTUAL_DEVICE, +#if BUILDFLAG(IS_TIZEN_TV) + TIZEN_CAPI_CAMERA_LOCAL, + TIZEN_CAPI_CAMERA_REMOTE, +#endif UNKNOWN }; diff --git a/packaging/chromium-efl.spec b/packaging/chromium-efl.spec index 9f37ad3..849920c 100755 --- a/packaging/chromium-efl.spec +++ b/packaging/chromium-efl.spec @@ -49,6 +49,13 @@ Source1: content_shell.in %define __enable_capi_thread_booster 0 %endif +%if "%{?tizen_profile_name}" == "tv" && %{tizen_version} > 60 +# Tizen TV 6.5 +%define __enable_network_camera 1 +%else +%define __enable_network_camera 0 +%endif + %{?_use_system_icu: %define __use_system_icu %{_use_system_icu}} # Product tv can't utilize system icu due to nacl dependency. %if "%{?profile}" != "tv" && %{tizen_version} == 60 && %{?_use_system_icu: 0}%{!?_use_system_icu: 1} @@ -516,6 +523,9 @@ touch ./tizen_src/downloadable/ewk_api_wrapper_generator.py "enable_wrt_js=%{macro_to_bool __enable_wrt_js}" \ "xwalk_extension_path=\"%{__xwalk_extension_path}\"" \ "xwalk_extension_service_path=\"%{__xwalk_extension_service_path}\"" \ +%if %{__enable_network_camera} + "enable_network_camera=true" \ +%endif %endif # _skip_gn ninja %{_smp_mflags} -C "%{OUTPUT_FOLDER}" \ diff --git a/tizen_src/build/config/BUILD.gn b/tizen_src/build/config/BUILD.gn index 9cd713a..34fde9c 100644 --- a/tizen_src/build/config/BUILD.gn +++ b/tizen_src/build/config/BUILD.gn @@ -57,9 +57,7 @@ config("tizen_feature_flags") { defines += [ "OS_TIZEN_TV_PRODUCT" ] } if (use_plugin_placeholder_hole) { - defines += [ - "USE_PLUGIN_PLACEHOLDER_HOLE", - ] + defines += [ "USE_PLUGIN_PLACEHOLDER_HOLE" ] } if (tizen_multimedia) { defines += [ "TIZEN_MULTIMEDIA" ] @@ -94,9 +92,10 @@ config("tizen_feature_flags") { ] } if (tizen_pepper_extensions) { - defines += [ - "TIZEN_PEPPER_EXTENSIONS" - ] + defines += [ "TIZEN_PEPPER_EXTENSIONS" ] + } + if (enable_network_camera) { + defines += [ "TIZEN_NETWORK_CAMERA" ] } if (tizen_vd_accessory) { defines += [ diff --git a/tizen_src/build/config/tizen_features.gni b/tizen_src/build/config/tizen_features.gni index 7712d5f..46cc294 100644 --- a/tizen_src/build/config/tizen_features.gni +++ b/tizen_src/build/config/tizen_features.gni @@ -68,6 +68,7 @@ declare_args() { tizen_vd_accessory = false tizen_resource_manager = false + enable_network_camera = false } if (is_tizen) { diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc index 65356f6..7d46b37 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc +++ b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc @@ -4,18 +4,52 @@ #include "media/capture/video/tizen/camera_device_tizen.h" +#include "base/system/system_monitor.h" +#include "device/udev_linux/scoped_udev.h" +#include "device/udev_linux/udev.h" #include "media/capture/video/tizen/video_capture_device_tizen.h" namespace { +const char kFsUUID[] = "ID_FS_UUID"; +const char kModel[] = "ID_MODEL"; +const char kModelID[] = "ID_MODEL_ID"; +const char kSerialShort[] = "ID_SERIAL_SHORT"; +const char kVendor[] = "ID_VENDOR"; +const char kVendorID[] = "ID_VENDOR_ID"; +const char kFSUniqueIdPrefix[] = "UUID:"; +const char kVendorModelSerialPrefix[] = "VendorModelSerial:"; + +#if BUILDFLAG(IS_TIZEN_TV) +enum { kMaxWidth = 1920 }; +enum { kMaxHeight = 1080 }; +#else enum { kMaxWidth = 1280 }; enum { kMaxHeight = 720 }; +#endif + enum { kMaxFramerate = CAMERA_ATTR_FPS_30 }; constexpr int kMinIso = 50; constexpr int kMaxIso = 3200; constexpr int kStepIso = 50; +// Construct a device id using label or manufacturer (vendor and model) details. +std::string MakeDeviceUniqueIdForUdevDevice(struct udev_device* device) { + std::string uuid = device::UdevDeviceGetPropertyValue(device, kFsUUID); + if (!uuid.empty()) + return kFSUniqueIdPrefix + uuid; + + std::string vendor = device::UdevDeviceGetPropertyValue(device, kVendorID); + std::string model = device::UdevDeviceGetPropertyValue(device, kModelID); + std::string serial_short = + device::UdevDeviceGetPropertyValue(device, kSerialShort); + if (vendor.empty() && model.empty() && serial_short.empty()) + return std::string(); + + return kVendorModelSerialPrefix + vendor + ":" + model + ":" + serial_short; +} + media::VideoPixelFormat toChromiumType(camera_pixel_format_e e) { switch (e) { case CAMERA_PIXEL_FORMAT_NV12: @@ -35,7 +69,12 @@ media::VideoPixelFormat toChromiumType(camera_pixel_format_e e) { case CAMERA_PIXEL_FORMAT_YV12: return media::PIXEL_FORMAT_YV12; case CAMERA_PIXEL_FORMAT_JPEG: + case CAMERA_PIXEL_FORMAT_MJPEG: return media::PIXEL_FORMAT_MJPEG; + case CAMERA_PIXEL_FORMAT_H264: + case CAMERA_PIXEL_FORMAT_VP8: + case CAMERA_PIXEL_FORMAT_VP9: + return media::PIXEL_FORMAT_ENCODED; default: NOTREACHED() << "Unknown format #" << e; } @@ -109,7 +148,9 @@ bool OnCameraSupportedPreviewFormat(camera_pixel_format_e format, static_cast*>(user_data); DCHECK(list_format); - list_format->push_back(toChromiumType(format)); + if (format != CAMERA_PIXEL_FORMAT_YUYV) + list_format->push_back(toChromiumType(format)); + return true; } @@ -145,7 +186,6 @@ void GenerateChromiumVideoCaptureFormat( } } } - } // anonymous namespace namespace media { @@ -235,25 +275,72 @@ mojom::RangePtr PhotoCapabilities::GetZoom() { return mojom::Range::New(); } -CameraHandle::CameraHandle() : camera_handle_(nullptr), client_(nullptr) { - LOG(INFO) << "Creating the camera instance"; - device_name_ = CAMERA_DEVICE_CAMERA0; - ResetHandle(device_name_); +// Get the camera index used by camera_create by device_id in descriptor +std::string CameraHandle::GetLowLevelIdFromUniqueId(std::string unique_id) { +#if BUILDFLAG(IS_TIZEN_TV) && !defined(TIZEN_NETWORK_CAMERA) + // Before using device manager, the unique id is like: + // kVendorModelSerialPrefix + vendor + ":" + model + ":" + serial_short + // and cached in cur_device_list_, the array index is low level index + // used by camera_create + for (unsigned int i = 0; i < cur_device_list_.size(); i++) { + if (cur_device_list_.at(i).device_id.compare(unique_id) == 0) + return std::to_string(i); + } + LOG(ERROR) << "Match no device item in descriptor list for: " << unique_id; + return ""; +#else + return unique_id; +#endif +} + +// Get the camera index used by camera_create by descriptor +camera_device_e CameraHandle::GetLowLevelIdFromDescriptor( + const VideoCaptureDeviceDescriptor& device_descriptor) { + std::string low_level_id = + GetLowLevelIdFromUniqueId(device_descriptor.device_id); + if (low_level_id.compare("0") == 0) { + return CAMERA_DEVICE_CAMERA0; + } else if (low_level_id.compare("1") == 0) { + return CAMERA_DEVICE_CAMERA1; + } else { + NOTREACHED(); + } + + return static_cast(-1); +} + +CameraHandle::CameraHandle() { + LOG(INFO) << "CameraHandle[" << (void*)this << "]::CameraHandle"; } CameraHandle::~CameraHandle() { + LOG(INFO) << "CameraHandle[" << (void*)this << "]::~CameraHandle"; if (camera_handle_ != nullptr) { + LOG(INFO) << "CameraHandle[" << (void*)this + << "]::~CameraHandle destory camera: " << (void*)camera_handle_; camera_destroy(camera_handle_); camera_handle_ = nullptr; } +#if defined(TIZEN_NETWORK_CAMERA) + DeinitializeDeviceManager(); +#endif + is_initialized_ = false; } -void CameraHandle::ResetHandle(camera_device_e device_name) { +camera_device_e CameraHandle::GetDeviceIndex() { + return GetLowLevelIdFromDescriptor(device_descriptor_); +} + +void CameraHandle::ResetHandle( + const VideoCaptureDeviceDescriptor& device_descriptor) { int err = 0; + base::AutoLock auto_lock(handle_lock_); if (camera_handle_ != nullptr) { if (client_ != nullptr) client_->OnStreamStopped(); + LOG(INFO) << "CameraHandle[" << (void*)this + << "]::ResetHandle, destory camera: " << (void*)camera_handle_; if (CAMERA_ERROR_NONE != (err = camera_destroy(camera_handle_))) { LOG(ERROR) << "camera_destroy error : " << media::VideoCaptureDeviceTizen::GetErrorString(err); @@ -261,17 +348,50 @@ void CameraHandle::ResetHandle(camera_device_e device_name) { camera_handle_ = nullptr; } - +#if defined(TIZEN_NETWORK_CAMERA) + LOG(INFO) << "device_descriptor.device_id: " << device_descriptor.device_id; + for (unsigned int i = 0; i < device_list_.count; ++i) { + LOG(INFO) << " device_list_.device[i].id " << device_list_.device[i].id; + if (device_descriptor.device_id.compare(device_list_.device[i].id) == 0) { + if (device_list_.device[i].type == CAMERA_DEVICE_TYPE_NETWORK) { + err = camera_create_network(device_list_.device[i].index, + &camera_handle_); + LOG(INFO) + << "CameraHandle[" << (void*)this + << "]::ResetHandle call camera_create_network for device index: " + << device_list_.device[i].index + << ", ret: " << media::VideoCaptureDeviceTizen::GetErrorString(err) + << ", camera_handle_: " << (void*)camera_handle_; + } else { + err = camera_create(device_list_.device[i].index, &camera_handle_); + LOG(INFO) << "CameraHandle[" << (void*)this + << "]::ResetHandle call camera_create for device index: " + << device_list_.device[i].index << ", ret: " + << media::VideoCaptureDeviceTizen::GetErrorString(err) + << ", camera_handle_: " << (void*)camera_handle_; + } + if (CAMERA_ERROR_NONE != err) { + camera_handle_ = nullptr; + LOG(ERROR) << "Cannot create camera, Error:" + << media::VideoCaptureDeviceTizen::GetErrorString(err); + return; + } + device_descriptor_ = device_descriptor; + break; + } + } +#else if (CAMERA_ERROR_NONE != - (err = camera_create(device_name, &camera_handle_))) { + (err = camera_create(GetLowLevelIdFromDescriptor(device_descriptor), + &camera_handle_))) { camera_handle_ = nullptr; LOG(ERROR) << "Cannot create camera, Error:" << media::VideoCaptureDeviceTizen::GetErrorString(err); return; } else { - device_name_ = device_name; + device_descriptor_ = device_descriptor; } - +#endif capabilities_.reset(new PhotoCapabilities(camera_handle_)); } @@ -284,12 +404,54 @@ void CameraHandle::UnsetClient(CameraHandleClient* client) { client_ = nullptr; } -CameraHandle* CameraHandle::GetInstance() { - return base::Singleton::get(); +bool CameraHandle::Initialize() { +#if defined(TIZEN_NETWORK_CAMERA) + InitializeDeviceManager(); +#endif + + is_initialized_ = true; + return true; +} + +bool CameraHandle::SetDefaultCameraToHandle() { + // Reset the first camera device to handle. + if (!camera_handle_) { + VideoCaptureDeviceDescriptors descriptors; +#if BUILDFLAG(IS_TIZEN_TV) +#if defined(TIZEN_NETWORK_CAMERA) + GetDeviceDescriptorsFromDeviceManager(&descriptors); +#else + GetDeviceDescriptorsFromUdev(&descriptors); +#endif +#else + VideoCaptureControlSupport control_support; + descriptors.push_back(VideoCaptureDeviceDescriptor( + VideoCaptureDeviceTizen::kFrontCameraName, + VideoCaptureDeviceTizen::GetFrontCameraID(), "front_camera", + VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE, control_support, + VideoCaptureTransportType::OTHER_TRANSPORT)); +#endif + if (descriptors.size() > 0) { + LOG(INFO) << "SetDefaultCameraToHandle to the first camera"; + VideoCaptureDeviceDescriptor descriptor = descriptors.front(); + ResetHandle(descriptor); + } + + if (!camera_handle_) { + LOG(INFO) << "No valid camera to use"; + return false; + } + } + + return true; +} + +bool CameraHandle::IsInitialized() { + return is_initialized_; } bool CameraHandle::IsValid() { - return camera_handle_ != nullptr; + return is_initialized_ && camera_handle_ != nullptr; } bool CameraHandle::GetSupportedPreviewResolutions( @@ -307,11 +469,13 @@ bool CameraHandle::GetSupportedPreviewResolutions( } bool CameraHandle::GetSupportedPreviewPixelFormats( - std::vector& supported_formats) const { + std::vector& supported_formats, + camera_h camera_handle) const { int err = 0; - if (CAMERA_ERROR_NONE != (err = camera_foreach_supported_preview_format( - camera_handle_, OnCameraSupportedPreviewFormat, - &supported_formats))) { + if (CAMERA_ERROR_NONE != + (err = camera_foreach_supported_preview_format( + camera_handle ? camera_handle : camera_handle_, + OnCameraSupportedPreviewFormat, &supported_formats))) { LOG(ERROR) << "Cannot get the supported formats for camera, Error:" << media::VideoCaptureDeviceTizen::GetErrorString(err); return false; @@ -320,7 +484,8 @@ bool CameraHandle::GetSupportedPreviewPixelFormats( } bool CameraHandle::GetSupportedPreviewCapabilities( - std::vector& supported_capabilities) const { + std::vector& supported_capabilities, + camera_h camera_handle) const { std::vector preview_resolutions; if (!GetSupportedPreviewResolutions(preview_resolutions)) return false; @@ -330,8 +495,9 @@ bool CameraHandle::GetSupportedPreviewCapabilities( int width = resolution.width(); int height = resolution.height(); if (CAMERA_ERROR_NONE != camera_attr_foreach_supported_fps_by_resolution( - camera_handle_, width, height, - OnCameraSupportedFPS, &frame_rates)) { + camera_handle ? camera_handle : camera_handle_, + width, height, OnCameraSupportedFPS, + &frame_rates)) { LOG(WARNING) << "Cannot get the supported FPS for this resolution : " << width << "X" << height; continue; @@ -348,6 +514,7 @@ bool CameraHandle::GetSupportedPreviewCapabilities( } void CameraHandle::GetDeviceSupportedFormats( + const VideoCaptureDeviceDescriptor& device_descriptor, media::VideoCaptureFormats& supported_formats) { std::vector supported_pixel_formats; std::vector supported_capabilities; @@ -356,11 +523,51 @@ void CameraHandle::GetDeviceSupportedFormats( LOG(ERROR) << "Cannot use camera"; return; } + camera_h camera_handle = nullptr; +#if defined(TIZEN_NETWORK_CAMERA) + /** To support multi camera device cases. if request is for current device, + * pass camera_handle as nullptr, related funtions will use camera_handle_; + * otherwise, need create a new handle */ + base::AutoLock auto_lock(handle_lock_); + if (device_descriptor.device_id.compare(device_descriptor_.device_id) != 0) { + for (unsigned int i = 0; i < device_list_.count; ++i) { + if (device_descriptor.device_id.compare(device_list_.device[i].id) == 0) { + int err = 0; + if (device_list_.device[i].type == CAMERA_DEVICE_TYPE_NETWORK) { + err = camera_create_network(device_list_.device[i].index, + &camera_handle); + } else { + err = camera_create(device_list_.device[i].index, &camera_handle); + } + if (CAMERA_ERROR_NONE != err) { + camera_handle = nullptr; + LOG(ERROR) << "Cannot create camera, Error:" + << media::VideoCaptureDeviceTizen::GetErrorString(err); + return; + } + break; + } + } + } +#else + // pass camera_handle as nullptr, related functions will use camera_handle_ +#endif + + bool result = false; + if (GetSupportedPreviewPixelFormats(supported_pixel_formats, camera_handle) && + GetSupportedPreviewCapabilities(supported_capabilities, camera_handle)) + result = true; + else + LOG(ERROR) << "Get supported preview pixel formats or capabilities failed"; + +#if defined(TIZEN_NETWORK_CAMERA) + if (camera_handle) { + camera_destroy(camera_handle); + camera_handle = nullptr; + } +#endif - if (!GetSupportedPreviewPixelFormats(supported_pixel_formats)) - return; - - if (!GetSupportedPreviewCapabilities(supported_capabilities)) + if (!result) return; supported_formats.clear(); @@ -397,6 +604,303 @@ int CameraHandle::GetDeviceCounts() { return device_count; } +#if BUILDFLAG(IS_TIZEN_TV) +void CameraHandle::CheckCurrentHandleChange( + VideoCaptureDeviceDescriptors* device_descriptors) { + if (!camera_handle_) + return; + + unsigned int old_index = GetLowLevelIdFromDescriptor(device_descriptor_); + for (unsigned int i = 0; i < device_descriptors->size(); i++) { + if (device_descriptors->at(i).device_id.compare( + device_descriptor_.device_id) == 0) { + if (i != old_index) { + LOG(ERROR) + << "The low level id of current using device has been changed from " + << old_index << " to " << i; + // logicly we should reset handle for current item, but for one hand + // that should be triggered by JS side (if we put low level id as prefix + // of device id, js side will perceive the change of device id), on + // other hand that will interrupt current using device, take example: + // plug in a camera, current using camera will be black. while because + // camera_destroy only need camera_handle_, for continuous using of + // current camera, let do nothing now but keep in mind in this branch + // the low level id is not anymore the one used in camera_create for + // current device handle + } + return; + } + } + + // In this branch, the current using camera has been unpluged + // we may need destroy camera and clear device_descriptor_ in future + // to optimize the ResetHandle. current every time OnAllocateAndStart + // we re-create camera in ResetHandle, that's inefficient + LOG(ERROR) << "Current using camera has been unpluged: " + << device_descriptor_.device_id; + return; +} + +#if defined(TIZEN_NETWORK_CAMERA) +void CameraHandle::GetDeviceDescriptorsFromDeviceManager( + VideoCaptureDeviceDescriptors* device_descriptors) { + int err = 0; + // Not support get VideoCaptureControlSupport info yet + VideoCaptureControlSupport control_support; + memset(&device_list_, 0x0, sizeof(camera_device_list_s)); + if (CAMERA_ERROR_NONE == (err = camera_device_manager_get_device_list( + manager_handle_, &device_list_))) { + LOG(INFO) << "Camera Device list count: " << device_list_.count; + for (unsigned int i = 0; i < device_list_.count; i++) { + VideoCaptureDeviceDescriptor desc( + device_list_.device[i].name, device_list_.device[i].id, + device_list_.device[i].type == CAMERA_DEVICE_TYPE_NETWORK + ? VideoCaptureApi::TIZEN_CAPI_CAMERA_REMOTE + : VideoCaptureApi::TIZEN_CAPI_CAMERA_LOCAL, + control_support, VideoCaptureTransportType::OTHER_TRANSPORT); + LOG(INFO) << i << " name " << device_list_.device[i].name << " type " + << device_list_.device[i].type << " index " + << device_list_.device[i].index << " id " + << device_list_.device[i].id; + device_descriptors->push_back(desc); + } + } +} +#endif + +void CameraHandle::GetDeviceDescriptorsFromUdev( + VideoCaptureDeviceDescriptors* device_descriptors) { + // Camera handle don't support to get get device count and name on TV. So use + // udev to instead of it. + device::ScopedUdevPtr video_udev; + video_udev.reset(device::udev_new()); + if (!video_udev) { + LOG(ERROR) << "Failed to create udev."; + return; + } + + device::ScopedUdevEnumeratePtr enumerate( + device::udev_enumerate_new(video_udev.get())); + + if (!enumerate) { + LOG(ERROR) << "Failed to enumerate devices."; + video_udev.reset(); + return; + } + const char kVideoSubsystem[] = "video4linux"; + int err = device::udev_enumerate_add_match_subsystem(enumerate.get(), + kVideoSubsystem); + if (err) { + LOG(ERROR) << "udev_enumerate_add_match_subsystem fails: " << err; + enumerate.reset(); + video_udev.reset(); + return; + } + + if (device::udev_enumerate_scan_devices(enumerate.get()) != 0) { + LOG(ERROR) << "Failed to enumerate devices."; + enumerate.reset(); + video_udev.reset(); + return; + } + + // Not support get VideoCaptureControlSupport info yet + VideoCaptureControlSupport control_support; + + int device_count = 0; + // This list is managed by |enumerate|. + udev_list_entry* devices = + device::udev_enumerate_get_list_entry(enumerate.get()); + for (udev_list_entry* i = devices; i != nullptr; + i = device::udev_list_entry_get_next(i)) { + device::ScopedUdevDevicePtr device(device::udev_device_new_from_syspath( + video_udev.get(), device::udev_list_entry_get_name(i))); + if (device.get()) { + const std::string subsystem( + device::udev_device_get_subsystem(device.get())); + if (subsystem == kVideoSubsystem) { + const char* vendor = + device::udev_device_get_property_value(device.get(), kVendorID); + const char* model_id = + device::udev_device_get_property_value(device.get(), kModelID); + const char* model = + device::udev_device_get_property_value(device.get(), kModel); + + // If display name only contain model, then once plug multiple same + // model cameras, user will not able to distinguish them by display + // name, let's add serial short as suffix + std::string display_name = (model != nullptr ? model : "UNKNOWN"); + std::string serial_short = + device::UdevDeviceGetPropertyValue(device.get(), kSerialShort); + if (!serial_short.empty()) { + std::string sysname_str; + display_name += '_'; + display_name += serial_short; + } + + // The device id has to be unique, can not move from one device to + // another, or else device cache will get into a wrong state + std::string unique_id = MakeDeviceUniqueIdForUdevDevice(device.get()); + + if ((vendor != nullptr) && (model_id != nullptr)) { + LOG(ERROR) << "GetDevice, device_id = " << unique_id + << ", display_name = " << display_name << ", sysname = " + << device::udev_device_get_sysname(device.get()) + << ", device_count = " << device_count + << ", vendor = " << vendor << ", model id = " << model_id + << ", model = " << model + << ", serial_short = " << serial_short; + VideoCaptureDeviceDescriptor camera( + display_name, unique_id, VideoCaptureApi::UNKNOWN, + control_support, VideoCaptureTransportType::OTHER_TRANSPORT); + if (device_count == 0) + camera.facing = media::MEDIA_VIDEO_FACING_ENVIRONMENT; + else if (device_count == 1) + camera.facing = media::MEDIA_VIDEO_FACING_USER; + else + camera.facing = media::MEDIA_VIDEO_FACING_NONE; + + device_descriptors->push_back(camera); + device_count++; + } + } + } + } + + CheckCurrentHandleChange(device_descriptors); + + // while for platform interface camera_create, we can only use + // CAMERA_DEVICE_CAMERA0 and CAMERA_DEVICE_CAMERA1, then we need + // record relationship between unique device id and camera index + // by storing them in cur_device_list_ later + cur_device_list_.clear(); + for (auto iter = device_descriptors->begin(); + iter != device_descriptors->end(); iter++) + cur_device_list_.push_back(*iter); + + enumerate.reset(); + video_udev.reset(); + if (device_count == 0) { + LOG(ERROR) << "No camera on this device."; + } +} + +void CameraHandle::GetDevicesInfo(GetDevicesInfoCallback callback) { + std::vector devices_info; + VideoCaptureDeviceDescriptors device_descriptors; + +#if defined(TIZEN_NETWORK_CAMERA) + GetDeviceDescriptorsFromDeviceManager(&device_descriptors); +#else + GetDeviceDescriptorsFromUdev(&device_descriptors); +#endif + + for (unsigned int i = 0; i < device_descriptors.size(); i++) { + devices_info.emplace_back(std::move(device_descriptors.at(i))); + + VideoCaptureFormats supported_formats; + GetDeviceSupportedFormats(devices_info.back().descriptor, + supported_formats); + devices_info.back().supported_formats = std::move(supported_formats); + } + + std::move(callback).Run(std::move(devices_info)); +} +#endif // BUILDFLAG(IS_TIZEN_TV) + +#if defined(TIZEN_NETWORK_CAMERA) +void CameraHandle::InitializeDeviceManager() { + LOG(INFO) << "CameraHandle[" << (void*)this << "]::InitializeDeviceManager"; + if (manager_handle_ == nullptr) { + LOG(INFO) + << " CameraHandle[" << (void*)this + << "]::InitializeDeviceManager call camera_device_manager_initialize"; + int ret = camera_device_manager_initialize(&manager_handle_); + if (!manager_handle_ || CAMERA_ERROR_NONE != ret) { + LOG(ERROR) << "Cannot create initialize device manager, Error:" + << media::VideoCaptureDeviceTizen::GetErrorString(ret); + } else { + memset(&device_list_, 0x0, sizeof(camera_device_list_s)); + ret = + camera_device_manager_get_device_list(manager_handle_, &device_list_); + if (CAMERA_ERROR_NONE != ret) { + LOG(ERROR) << "camera_device_manager_get_device_list, Error:" + << media::VideoCaptureDeviceTizen::GetErrorString(ret); + } + + if (device_list_.count == 0) + LOG(WARNING) << "camera device count is 0"; + + LOG(INFO) << "CameraHandle[" << (void*)this + << "]::InitializeDeviceManager call " + "camera_device_manager_add_device_connection_changed_cb"; + ret = camera_device_manager_add_device_connection_changed_cb( + manager_handle_, CameraHandle::OnCameraDeviceConnectionChanged, this, + &camera_device_list_changed_cb_id_); + if (CAMERA_ERROR_NONE != ret) { + LOG(ERROR) + << "camera_device_manager_add_device_connection_changed_cb, Error:" + << media::VideoCaptureDeviceTizen::GetErrorString(ret); + } + } + } +} + +void CameraHandle::DeinitializeDeviceManager() { + LOG(INFO) << "CameraHandle[" << (void*)this + << "]::DeinitializeDeviceManager, cb_id_: " + << camera_device_list_changed_cb_id_ + << ", manager_handle_: " << (void*)manager_handle_; + int err = 0; + if (camera_device_list_changed_cb_id_ != + kInvalidCameraDevicelistChangedCbId) { + if (CAMERA_ERROR_NONE != + (err = camera_device_manager_remove_device_connection_changed_cb( + manager_handle_, camera_device_list_changed_cb_id_))) { + LOG(ERROR) << "camera_device_manager_remove_device_connection_changed_cb " + "error : " + << media::VideoCaptureDeviceTizen::GetErrorString(err); + } + camera_device_list_changed_cb_id_ = kInvalidCameraDevicelistChangedCbId; + } + if (manager_handle_ != nullptr) { + if (CAMERA_ERROR_NONE != + (err = camera_device_manager_deinitialize(manager_handle_))) { + LOG(ERROR) << "camera_device_manager_deinitialize error : " + << media::VideoCaptureDeviceTizen::GetErrorString(err); + } + manager_handle_ = nullptr; + } +} + +void CameraHandle::OnCameraDeviceConnectionChanged(camera_device_s* device, + bool is_connected, + void* user_data) { + if (device && user_data) { + LOG(INFO) << "Camera Device connection changed" + << ", device name: " << device->name + << ", device id: " << device->id + << ", is connected: " << is_connected; + + CameraHandle* camera_handle = static_cast(user_data); + memset(&camera_handle->device_list_, 0x0, sizeof(camera_device_list_s)); + int ret = camera_device_manager_get_device_list( + camera_handle->manager_handle_, &camera_handle->device_list_); + if (CAMERA_ERROR_NONE != ret) { + LOG(ERROR) << "camera_device_manager_get_device_list, Error:" + << media::VideoCaptureDeviceTizen::GetErrorString(ret); + } + if (camera_handle->device_list_.count == 0) + LOG(WARNING) << "Current camera device count changed to 0"; + } + + if (base::SystemMonitor::Get()) { + base::SystemMonitor::Get()->ProcessDevicesChanged( + base::SystemMonitor::DeviceType::DEVTYPE_VIDEO_CAPTURE); + } +} +#endif + // Set Photo Capabilities bool CameraHandle::SetZoom(int value) { return CAMERA_ERROR_NONE == camera_attr_set_zoom(camera_handle_, value); @@ -432,6 +936,34 @@ int CameraHandle::CameraStopPreview() { return camera_stop_preview(camera_handle_); } +#if defined(TIZEN_NETWORK_CAMERA) +int CameraHandle::SetExtraStreamFormat(int stream_id, + camera_pixel_format_e pixel_format, + int width, + int height, + int fps) { + return camera_set_extra_preview_stream_format( + camera_handle_, stream_id, pixel_format, width, height, fps); +} + +int CameraHandle::SetExtraStreamBitrate(int stream_id, int bitrate_bps) { + return camera_attr_set_extra_preview_bitrate(camera_handle_, stream_id, + bitrate_bps); +} + +int CameraHandle::SetExtraStreamGOPInterval(int stream_id, int interval) { + // TODO(m.napiorkows): Uncomment when camera api is ready + // return camera_attr_set_extra_preview_gop_interval( + // camera_handle_, stream_id, interval); + return 0; +} + +int CameraHandle::SetExtraStreamCallback(camera_extra_preview_cb cb, + void* data) { + return camera_set_extra_preview_cb(camera_handle_, cb, data); +} +#endif + camera_attr_fps_e CameraHandle::CameraGetPreviewFps() { camera_attr_fps_e current_fps = static_cast(30); camera_attr_get_preview_fps(camera_handle_, ¤t_fps); diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h index 91c6dda..88eab4b 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h +++ b/tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h @@ -6,16 +6,28 @@ #define MEDIA_CAPTURE_VIDEO_TIZEN_CAMERA_DEVICE_TIZEN_H_ #include +#if defined(TIZEN_NETWORK_CAMERA) +#include +#endif #include #include "base/memory/singleton.h" #include "media/base/video_types.h" #include "media/capture/mojom/image_capture.mojom.h" +#include "media/capture/video/video_capture_device_factory.h" +#include "media/capture/video_capture_types.h" #include "ui/gfx/gpu_memory_buffer.h" using media::mojom::MeteringMode; namespace media { +#ifndef _CAMERA_DEVICE_TIZEN_H +#define _CAMERA_DEVICE_TIZEN_H +// The valid cb id start from 0 +#if defined(TIZEN_NETWORK_CAMERA) +const int kInvalidCameraDevicelistChangedCbId = -1; +#endif +#endif struct VideoCaptureFormat; typedef std::vector VideoCaptureFormats; @@ -78,17 +90,40 @@ class CameraHandleClient { class CameraHandle final { public: - static CameraHandle* GetInstance(); + CameraHandle(); + ~CameraHandle(); - camera_device_e GetDeviceName() { return device_name_; } + camera_device_e GetDeviceIndex(); bool IsValid(); + bool IsInitialized(); + bool Initialize(); + bool SetDefaultCameraToHandle(); bool GetSupportedPreviewPixelFormats( - std::vector& supported_formats) const; - void GetDeviceSupportedFormats(media::VideoCaptureFormats& supported_formats); + std::vector& supported_formats, + camera_h camera_handle = 0) const; + void GetDeviceSupportedFormats( + const VideoCaptureDeviceDescriptor& device_descriptor, + media::VideoCaptureFormats& supported_formats); int GetMaxFrameRate(CameraCapability::Resolution) const; int GetDeviceCounts(); - void ResetHandle(camera_device_e device_name); +#if BUILDFLAG(IS_TIZEN_TV) + using GetDevicesInfoCallback = + VideoCaptureDeviceFactory::GetDevicesInfoCallback; + void GetDevicesInfo(GetDevicesInfoCallback callback); + void GetDeviceDescriptorsFromDeviceManager( + VideoCaptureDeviceDescriptors* device_descriptors); + void GetDeviceDescriptorsFromUdev( + VideoCaptureDeviceDescriptors* device_descriptors); +#endif + void ResetHandle(const VideoCaptureDeviceDescriptor& device_descriptor); +#if defined(TIZEN_NETWORK_CAMERA) + static void OnCameraDeviceConnectionChanged(camera_device_s* device, + bool is_connected, + void* user_data); + void InitializeDeviceManager(); + void DeinitializeDeviceManager(); +#endif void SetClient(CameraHandleClient* client); void UnsetClient(CameraHandleClient* client); @@ -100,6 +135,17 @@ class CameraHandle final { bool SetIso(int value); bool SetExposure(int value); +#if defined(TIZEN_NETWORK_CAMERA) + int SetExtraStreamFormat(int stream_id, + camera_pixel_format_e pixel_format, + int width, + int height, + int fps); + int SetExtraStreamCallback(camera_extra_preview_cb cb, void* data); + int SetExtraStreamBitrate(int stream_id, int bitrate_bps); + int SetExtraStreamGOPInterval(int stream_id, int interval); +#endif + std::unique_ptr capabilities_; int CameraStartCapture(camera_capturing_cb capturingCB, @@ -129,22 +175,33 @@ class CameraHandle final { void* data); int CameraUnsetMediapacketPreviewCb(); - private: - CameraHandle(); - ~CameraHandle(); + std::string GetLowLevelIdFromUniqueId(std::string unique_id); + camera_device_e GetLowLevelIdFromDescriptor( + const VideoCaptureDeviceDescriptor& device_descriptor); CameraHandle(const CameraHandle&) = delete; CameraHandle& operator=(const CameraHandle&) = delete; + private: bool GetSupportedPreviewResolutions( std::vector& supported_resolutions) const; - bool GetSupportedPreviewCapabilities(std::vector&) const; - - camera_h camera_handle_; - camera_device_e device_name_; - CameraHandleClient* client_; - - friend struct base::DefaultSingletonTraits; + bool GetSupportedPreviewCapabilities(std::vector&, + camera_h camera_handle = 0) const; + void CheckCurrentHandleChange( + VideoCaptureDeviceDescriptors* device_descriptors); + + camera_h camera_handle_ = nullptr; + VideoCaptureDeviceDescriptor device_descriptor_; + VideoCaptureDeviceDescriptors cur_device_list_; + + CameraHandleClient* client_ = nullptr; +#if defined(TIZEN_NETWORK_CAMERA) + camera_device_manager_h manager_handle_ = nullptr; + int camera_device_list_changed_cb_id_ = kInvalidCameraDevicelistChangedCbId; + camera_device_list_s device_list_; +#endif + bool is_initialized_ = false; + mutable base::Lock handle_lock_; }; } // namespace media diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc index b3f3bf3..cb3deda 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.cc @@ -6,8 +6,10 @@ #include +#include "base/command_line.h" #include "base/logging.h" #include "base/memory/singleton.h" +#include "content/public/common/content_switches.h" #include "media/capture/video/tizen/camera_device_tizen.h" #include "media/capture/video/tizen/video_capture_device_tizen.h" @@ -15,9 +17,15 @@ namespace media { VideoCaptureDeviceFactoryTizen::VideoCaptureDeviceFactoryTizen( scoped_refptr ui_task_runner) - : ui_task_runner_(ui_task_runner) {} + : ui_task_runner_(ui_task_runner) { + LOG(INFO) << __FUNCTION__ << "[" << (void*)this << "]"; + camera_handle_.reset(new CameraHandle()); +} -VideoCaptureDeviceFactoryTizen::~VideoCaptureDeviceFactoryTizen() {} +VideoCaptureDeviceFactoryTizen::~VideoCaptureDeviceFactoryTizen() { + LOG(INFO) << __FUNCTION__ << "[" << (void*)this << "]"; + camera_handle_.reset(); +} VideoCaptureErrorOrDevice VideoCaptureDeviceFactoryTizen::CreateDevice( const VideoCaptureDeviceDescriptor& device_descriptor) { @@ -25,21 +33,32 @@ VideoCaptureErrorOrDevice VideoCaptureDeviceFactoryTizen::CreateDevice( // FIXME: is device discriptor needed? or just the name is sufficient? std::unique_ptr device( - new VideoCaptureDeviceTizen(device_descriptor)); + new VideoCaptureDeviceTizen(device_descriptor, camera_handle_.get())); return VideoCaptureErrorOrDevice(std::move(device)); } void VideoCaptureDeviceFactoryTizen::GetDevicesInfo( GetDevicesInfoCallback callback) { + if (!camera_handle_->IsInitialized()) { + LOG(INFO) << "Try to initialize camera handle"; + camera_handle_->Initialize(); + } + +#if BUILDFLAG(IS_TIZEN_TV) + camera_handle_->GetDevicesInfo(std::move(callback)); + return; +#endif + std::vector devices_info; - CameraHandle* camera_handle = CameraHandle::GetInstance(); - if (camera_handle == nullptr || !camera_handle->IsValid()) { - LOG(ERROR) << "Cannot use camera"; - return; + + if (!camera_handle_->IsValid()) { + if (!camera_handle_->SetDefaultCameraToHandle()) { + LOG(INFO) << "Can not find a usable camera"; + return; + } } - LOG(INFO) << "Received the camera handle:" << camera_handle; - int device_count = camera_handle->GetDeviceCounts(); + int device_count = camera_handle_->GetDeviceCounts(); if (device_count == 0) { LOG(ERROR) << "No camera on this device."; return; @@ -54,17 +73,23 @@ void VideoCaptureDeviceFactoryTizen::GetDevicesInfo( VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE, control_support, VideoCaptureTransportType::OTHER_TRANSPORT)); + VideoCaptureFormats front_supported_formats; + camera_handle_->GetDeviceSupportedFormats(devices_info.back().descriptor, + front_supported_formats); + devices_info.back().supported_formats = std::move(front_supported_formats); + if (device_count == 2) { devices_info.emplace_back(VideoCaptureDeviceDescriptor( VideoCaptureDeviceTizen::kBackCameraName, VideoCaptureDeviceTizen::GetBackCameraID(), "back_camera", VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE, control_support, VideoCaptureTransportType::OTHER_TRANSPORT)); + VideoCaptureFormats back_supported_formats; + camera_handle_->GetDeviceSupportedFormats(devices_info.back().descriptor, + back_supported_formats); + devices_info.back().supported_formats = std::move(back_supported_formats); } - VideoCaptureFormats supported_formats; - camera_handle->GetDeviceSupportedFormats(supported_formats); - devices_info.back().supported_formats = std::move(supported_formats); std::move(callback).Run(std::move(devices_info)); } diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.h b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.h index 77cfed6..fc601d2 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.h +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_factory_tizen.h @@ -11,6 +11,8 @@ namespace media { +class CameraHandle; + // Extension of VideoCaptureDeviceFactory to create and manipulate Tizen // devices. class MEDIA_EXPORT VideoCaptureDeviceFactoryTizen @@ -31,6 +33,8 @@ class MEDIA_EXPORT VideoCaptureDeviceFactoryTizen private: scoped_refptr ui_task_runner_; + + std::unique_ptr camera_handle_; }; } // namespace media diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc index e57ee7a..1582bce 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc @@ -5,7 +5,12 @@ #include "media/capture/video/tizen/video_capture_device_tizen.h" #include "base/bind.h" +#include "base/synchronization/lock.h" +#include "base/trace_event/trace_event.h" +#include "media/base/video_codecs.h" #include "media/base/video_color_space.h" +#include "media/base/video_frame_metadata.h" +#include "media/base/video_transformation.h" #include "media/capture/mojom/image_capture_types.h" #include "third_party/libyuv/include/libyuv.h" #include "tizen/system_info.h" @@ -19,6 +24,8 @@ namespace { return #x; \ break +constexpr int kDefaultGOPInterval = 1000 * 60 * 5; // 5 minutes + enum { kMjpegWidth = 640 }; enum { kMjpegHeight = 480 }; enum CameraOrientation { @@ -49,13 +56,31 @@ camera_pixel_format_e ToCapiType(media::VideoPixelFormat e) { return CAMERA_PIXEL_FORMAT_YV12; case media::PIXEL_FORMAT_MJPEG: return CAMERA_PIXEL_FORMAT_JPEG; + case media::PIXEL_FORMAT_ENCODED: + return CAMERA_PIXEL_FORMAT_H264; default: NOTREACHED(); } + LOG(ERROR) << __func__ << " " << e; return CAMERA_PIXEL_FORMAT_INVALID; } +#if defined(TIZEN_NETWORK_CAMERA) +camera_pixel_format_e ToCapiType(media::VideoCodec codec) { + switch (codec) { + case media::VideoCodec::kH264: + return CAMERA_PIXEL_FORMAT_H264; + case media::VideoCodec::kVP8: + return CAMERA_PIXEL_FORMAT_VP8; + case media::VideoCodec::kVP9: + return CAMERA_PIXEL_FORMAT_VP9; + default: + return CAMERA_PIXEL_FORMAT_INVALID; + } +} +#endif + struct CameraSpec { const char* device_id_; CameraOrientation orientation_; @@ -75,6 +100,57 @@ const std::vector& GetCameraSpec() { return kCommonCameraSpecs; } +struct FrameTraceInfo : public base::trace_event::ConvertableToTraceFormat { + double capture_timestamp; + int camera_timestamp; + bool is_keyframe; + FrameTraceInfo(double capture_timestamp, + int camera_timestamp, + bool is_keyframe) + : capture_timestamp(capture_timestamp), + camera_timestamp(camera_timestamp), + is_keyframe(is_keyframe) {} + void AppendAsTraceFormat(std::string* out) const override { + std::stringstream ss; + ss << "{\"capture_timestamp\":" << capture_timestamp + << ", \"camera_timestamp\":" << camera_timestamp + << ", \"is_keyframe\":" << (is_keyframe ? "true" : "false") << "}"; + out->append(ss.str()); + } +}; + +const char* CameraPixelFormatToString(camera_pixel_format_e format) { + switch (format) { + ENUM_CASE(CAMERA_PIXEL_FORMAT_INVALID); + ENUM_CASE(CAMERA_PIXEL_FORMAT_NV12); + ENUM_CASE(CAMERA_PIXEL_FORMAT_NV12T); + ENUM_CASE(CAMERA_PIXEL_FORMAT_NV16); + ENUM_CASE(CAMERA_PIXEL_FORMAT_NV21); + ENUM_CASE(CAMERA_PIXEL_FORMAT_YUYV); + ENUM_CASE(CAMERA_PIXEL_FORMAT_UYVY); + ENUM_CASE(CAMERA_PIXEL_FORMAT_422P); + ENUM_CASE(CAMERA_PIXEL_FORMAT_I420); + ENUM_CASE(CAMERA_PIXEL_FORMAT_YV12); + ENUM_CASE(CAMERA_PIXEL_FORMAT_RGB565); + ENUM_CASE(CAMERA_PIXEL_FORMAT_RGB888); + ENUM_CASE(CAMERA_PIXEL_FORMAT_RGBA); + ENUM_CASE(CAMERA_PIXEL_FORMAT_ARGB); + ENUM_CASE(CAMERA_PIXEL_FORMAT_JPEG); + ENUM_CASE(CAMERA_PIXEL_FORMAT_H264); + ENUM_CASE(CAMERA_PIXEL_FORMAT_INVZ); +#if defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT) + ENUM_CASE(CAMERA_PIXEL_FORMAT_MJPEG); +#endif +#if defined(TIZEN_NETWORK_CAMERA) + ENUM_CASE(CAMERA_PIXEL_FORMAT_VP8); + ENUM_CASE(CAMERA_PIXEL_FORMAT_VP9); +#endif + } + + NOTREACHED() << "Unknown camera pixel format #" << format; + return "UNKNOWN"; +} + } // unnamed namespace namespace media { @@ -91,7 +167,7 @@ const std::string VideoCaptureDeviceTizen::kCameraId1 = "1"; // Note : Camera ID for Mobile or Wearable profile > Front : 1 / Back : 0 const char* VideoCaptureDeviceTizen::GetFrontCameraID() { - if (IsMobileProfile()) + if (IsMobileProfile() && !IsCommonProfile()) return VideoCaptureDeviceTizen::kCameraId1.c_str(); else return VideoCaptureDeviceTizen::kCameraId0.c_str(); @@ -99,7 +175,7 @@ const char* VideoCaptureDeviceTizen::GetFrontCameraID() { // static const char* VideoCaptureDeviceTizen::GetBackCameraID() { - if (IsMobileProfile()) + if (IsMobileProfile() && !IsCommonProfile()) return VideoCaptureDeviceTizen::kCameraId0.c_str(); else return VideoCaptureDeviceTizen::kCameraId1.c_str(); @@ -109,7 +185,7 @@ static CameraOrientation GetCameraOrientation(const char* device_id) { auto& camera_spec = GetCameraSpec(); for (size_t i = 0; i < camera_spec.size(); i++) { const CameraSpec& cameraspec = camera_spec.at(i); - if (strcmp(cameraspec.device_id_, device_id) == 0) { + if (device_id && strcmp(cameraspec.device_id_, device_id) == 0) { return cameraspec.orientation_; } } @@ -117,8 +193,9 @@ static CameraOrientation GetCameraOrientation(const char* device_id) { } VideoCaptureDeviceTizen::VideoCaptureDeviceTizen( - const VideoCaptureDeviceDescriptor& device_descriptor) - : camera_instance_(nullptr), + const VideoCaptureDeviceDescriptor& device_descriptor, + CameraHandle* camera_instance) + : camera_instance_(camera_instance), buffer_(), device_descriptor_(device_descriptor), worker_("VideoCapture"), @@ -137,6 +214,10 @@ VideoCaptureDeviceTizen::~VideoCaptureDeviceTizen() { state_ = kIdle; DCHECK(!worker_.IsRunning()); photo_callbacks_.clear(); + +#if TIZEN_MM_DEBUG_VIDEO_DUMP_DECODED_FRAME == 1 + delete frameDumper; +#endif } void VideoCaptureDeviceTizen::OnStreamStopped() { @@ -148,6 +229,7 @@ void VideoCaptureDeviceTizen::AllocateAndStart( std::unique_ptr client) { DCHECK(!worker_.IsRunning()); worker_.Start(); + worker_.task_runner()->PostTask( FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnAllocateAndStart, base::Unretained(this), @@ -166,6 +248,13 @@ void VideoCaptureDeviceTizen::StopAndDeAllocate() { worker_.Stop(); } +void VideoCaptureDeviceTizen::GetPhotoState(GetPhotoStateCallback callback) { + DCHECK(worker_.IsRunning()); + worker_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnGetPhotoState, + base::Unretained(this), std::move(callback))); +} + void VideoCaptureDeviceTizen::OnGetPhotoState(GetPhotoStateCallback callback) { DCHECK(worker_.task_runner()->BelongsToCurrentThread()); @@ -198,27 +287,6 @@ void VideoCaptureDeviceTizen::OnGetPhotoState(GetPhotoStateCallback callback) { std::move(callback).Run(std::move(photo_capabilities)); } -void VideoCaptureDeviceTizen::TakePhoto(TakePhotoCallback callback) { - int err = 0; - if (CAMERA_ERROR_NONE != (err = camera_instance_->CameraSetCaptureFormat( - CAMERA_PIXEL_FORMAT_JPEG))) { - SetErrorState(GetErrorString(err), FROM_HERE); - return; - } - - std::unique_ptr heap_callback( - new TakePhotoCallback(std::move(callback))); - - if (CAMERA_ERROR_NONE != - (err = camera_instance_->CameraStartCapture( - VideoCaptureDeviceTizen::CapturedCb, - VideoCaptureDeviceTizen::CaptureCompletedCb, this))) { - SetErrorState(GetErrorString(err), FROM_HERE); - return; - } - photo_callbacks_.push_back(std::move(heap_callback)); -} - void VideoCaptureDeviceTizen::SetPhotoOptions( mojom::PhotoSettingsPtr settings, SetPhotoOptionsCallback callback) { @@ -244,23 +312,25 @@ void VideoCaptureDeviceTizen::OnSetPhotoOptions( } } -void VideoCaptureDeviceTizen::GetPhotoState(GetPhotoStateCallback callback) { - DCHECK(worker_.IsRunning()); - worker_.task_runner()->PostTask( - FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::OnGetPhotoState, - base::Unretained(this), std::move(callback))); -} +void VideoCaptureDeviceTizen::TakePhoto(TakePhotoCallback callback) { + int err = 0; + if (CAMERA_ERROR_NONE != (err = camera_instance_->CameraSetCaptureFormat( + CAMERA_PIXEL_FORMAT_JPEG))) { + SetErrorState(GetErrorString(err), FROM_HERE); + return; + } -camera_device_e VideoCaptureDeviceTizen::DeviceNameToCameraId( - const VideoCaptureDeviceDescriptor& device_descriptor) { - if (device_descriptor.device_id.compare("0") == 0) { - return CAMERA_DEVICE_CAMERA0; - } else if (device_descriptor.device_id.compare("1") == 0) { - return CAMERA_DEVICE_CAMERA1; - } else { - NOTREACHED(); + std::unique_ptr heap_callback( + new TakePhotoCallback(std::move(callback))); + + if (CAMERA_ERROR_NONE != + (err = camera_instance_->CameraStartCapture( + VideoCaptureDeviceTizen::CapturedCb, + VideoCaptureDeviceTizen::CaptureCompletedCb, this))) { + SetErrorState(GetErrorString(err), FROM_HERE); + return; } - return static_cast(-1); + photo_callbacks_.push_back(std::move(heap_callback)); } bool VideoCaptureDeviceTizen::IsCapturing() { @@ -314,8 +384,10 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { gfx::Size target_resolution(width, height); int target_rotation = - (orientation + - GetCameraOrientation(device_descriptor_.device_id.c_str())) % + (orientation + GetCameraOrientation(camera_instance_ + ->GetLowLevelIdFromUniqueId( + device_descriptor_.device_id) + .c_str())) % DEGREE_360; int src_stride_y = width; @@ -330,9 +402,10 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { int dest_width = width; int dest_height = height; +#if !BUILDFLAG(IS_TIZEN_TV) if (target_rotation == 90 || target_rotation == 270) std::swap(dest_height, dest_width); - +#endif videocaptureformat.frame_size = gfx::Size(dest_width, dest_height); auto reservation_result_code = client_->ReserveOutputBuffer( videocaptureformat.frame_size, media::PIXEL_FORMAT_I420, 0, &buffer_); @@ -373,6 +446,13 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { client_->OnIncomingCapturedBuffer(std::move(buffer_), videocaptureformat, now, now - first_ref_time_); + } else if (mime == MEDIA_FORMAT_H264_SP) { + base::TimeTicks now = base::TimeTicks::Now(); + if (first_ref_time_.is_null()) + first_ref_time_ = now; + + client_->OnIncomingCapturedBuffer(std::move(buffer_), videocaptureformat, + now, now - first_ref_time_); } else if (mime == MEDIA_FORMAT_I420) { // FIXME: Verify if I420 format is working. void *data_y, *data_u, *data_v; @@ -383,8 +463,8 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { if (libyuv::I420Rotate(reinterpret_cast(data_y), src_stride_y, reinterpret_cast(data_u), src_stride_uv, reinterpret_cast(data_v), src_stride_uv, - y_plane, src_stride_y, u_plane, src_stride_uv, - v_plane, src_stride_uv, width, height, mode)) { + y_plane, dest_stride_y, u_plane, dest_stride_uv, + v_plane, dest_stride_uv, width, height, mode)) { LOG(ERROR) << "Failed to I420Rotate buffer"; ChangeCapturingState(false); return; @@ -404,10 +484,29 @@ void VideoCaptureDeviceTizen::PreviewCameraCaptured(ScopedMediaPacket pkt) { ChangeCapturingState(false); } +constexpr bool IsFormatEncoded(camera_pixel_format_e format) { + bool is_format_encoded = format == CAMERA_PIXEL_FORMAT_H264; + + is_format_encoded |= format == CAMERA_PIXEL_FORMAT_MJPEG; + + return is_format_encoded; +} + +constexpr media::VideoPixelFormat ConvertPixelFormat( + camera_pixel_format_e format) { + if (IsFormatEncoded(format)) + return media::PIXEL_FORMAT_ENCODED; + return media::PIXEL_FORMAT_I420; +} + void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, void* data) { CHECK((frame->format == CAMERA_PIXEL_FORMAT_I420) || - (frame->format == CAMERA_PIXEL_FORMAT_NV12)); + (frame->format == CAMERA_PIXEL_FORMAT_NV12) || + (frame->format == CAMERA_PIXEL_FORMAT_H264) || + (frame->format == CAMERA_PIXEL_FORMAT_YUYV) || + (frame->format == CAMERA_PIXEL_FORMAT_MJPEG)); + #if TIZEN_MM_DEBUG_VIDEO_DUMP_DECODED_FRAME == 1 frameDumper->DumpFrame(frame); #endif @@ -425,7 +524,10 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, gfx::Size target_resolution(frame->width, frame->height); int target_rotation = (orientation + - GetCameraOrientation(self->device_descriptor_.device_id.c_str())) % + GetCameraOrientation( + self->camera_instance_ + ->GetLowLevelIdFromUniqueId(self->device_descriptor_.device_id) + .c_str())) % DEGREE_360; int src_stride_y = frame->width; @@ -434,22 +536,30 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, media::VideoCaptureFormat videocaptureformat; videocaptureformat.frame_size = gfx::Size(frame->width, frame->height); videocaptureformat.frame_rate = self->frame_rate_; - videocaptureformat.pixel_format = media::PIXEL_FORMAT_I420; + videocaptureformat.pixel_format = ConvertPixelFormat(frame->format); int dest_width = frame->width; int dest_height = frame->height; +#if !BUILDFLAG(IS_TIZEN_TV) if (target_rotation == 90 || target_rotation == 270) std::swap(dest_height, dest_width); - +#endif videocaptureformat.frame_size = gfx::Size(dest_width, dest_height); + gfx::Size frame_size = (IsFormatEncoded(frame->format) + ? gfx::Size(1, frame->data.encoded_plane.size) + : gfx::Size(frame->width, frame->height)); + auto reservation_result_code = self->client_->ReserveOutputBuffer( - videocaptureformat.frame_size, media::PIXEL_FORMAT_I420, 0, - &self->buffer_); + frame_size, ConvertPixelFormat(frame->format), 0, &self->buffer_); if (reservation_result_code != - VideoCaptureDevice::Client::ReserveResult::kSucceeded) - DLOG(ERROR) << "Couldn't allocate Capture Buffer"; + VideoCaptureDevice::Client::ReserveResult::kSucceeded) { + LOG(ERROR) << "Couldn't allocate Capture Buffer"; + self->client_->OnFrameDropped( + media::VideoCaptureFrameDropReason::kBufferPoolBufferAllocationFailed); + return; + } libyuv::RotationMode mode = static_cast(target_rotation); @@ -466,27 +576,46 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, uint8_t* u_plane = y_plane + dest_stride_y * dest_height; uint8_t* v_plane = u_plane + dest_stride_uv * dest_height / 2; - if (frame->format == CAMERA_PIXEL_FORMAT_NV12) { - src_stride_uv = src_stride_y; + switch (frame->format) { + case CAMERA_PIXEL_FORMAT_NV12: + src_stride_uv = src_stride_y; + libyuv::NV12ToI420Rotate( + reinterpret_cast(frame->data.double_plane.y), src_stride_y, + reinterpret_cast(frame->data.double_plane.uv), + src_stride_uv, y_plane, dest_stride_y, u_plane, dest_stride_uv, + v_plane, dest_stride_uv, frame->width, frame->height, mode); + break; + + case CAMERA_PIXEL_FORMAT_I420: + // FIXME: Verify if I420 format is working. + src_stride_uv = (src_stride_y + 1) / 2; + libyuv::I420Rotate( + reinterpret_cast(frame->data.triple_plane.y), src_stride_y, + reinterpret_cast(frame->data.triple_plane.u), src_stride_uv, + reinterpret_cast(frame->data.triple_plane.v), src_stride_uv, + y_plane, dest_stride_y, u_plane, dest_stride_uv, v_plane, + dest_stride_uv, frame->width, frame->height, mode); + break; + + case CAMERA_PIXEL_FORMAT_YUYV: { + libyuv::YUY2ToI420( + reinterpret_cast(frame->data.single_plane.yuv), + src_stride_y, y_plane, dest_stride_y, u_plane, dest_stride_uv, + v_plane, dest_stride_uv, frame->width, frame->height); + } break; + + case CAMERA_PIXEL_FORMAT_H264: +#if defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT) + case CAMERA_PIXEL_FORMAT_MJPEG: +#endif + memcpy(y_plane, frame->data.encoded_plane.data, + frame->data.encoded_plane.size); + break; - libyuv::NV12ToI420Rotate( - reinterpret_cast(frame->data.double_plane.y), src_stride_y, - reinterpret_cast(frame->data.double_plane.uv), src_stride_uv, - y_plane, dest_stride_y, u_plane, dest_stride_uv, v_plane, - dest_stride_uv, frame->width, frame->height, mode); - } else if (frame->format == CAMERA_PIXEL_FORMAT_I420) { - // FIXME: Verify if I420 format is working. - src_stride_uv = (src_stride_y + 1) / 2; - - libyuv::I420Rotate( - reinterpret_cast(frame->data.triple_plane.y), src_stride_y, - reinterpret_cast(frame->data.triple_plane.u), src_stride_uv, - reinterpret_cast(frame->data.triple_plane.v), src_stride_uv, - y_plane, dest_stride_y, u_plane, dest_stride_uv, v_plane, - dest_stride_uv, frame->width, frame->height, mode); - } else { - LOG(INFO) << "Unsupported Format"; - return; + default: + LOG(INFO) << "Unsupported Format " + << CameraPixelFormatToString(frame->format); + return; } base::TimeTicks now = base::TimeTicks::Now(); @@ -496,6 +625,57 @@ void VideoCaptureDeviceTizen::OnCameraCaptured(camera_preview_data_s* frame, self->client_->OnIncomingCapturedBuffer(std::move(self->buffer_), videocaptureformat, now, now - self->first_ref_time_); + + // statistics & log every seconds + ++(self->frame_total_); + LOG_IF(INFO, + self->frame_rate_ > 0 && (self->frame_total_ % self->frame_rate_ == 1)) + << "total:" << self->frame_total_ + << " frame_timestamp:" << frame->timestamp << " width:" << frame->width + << " height:" << frame->height + << " format: " << CameraPixelFormatToString(frame->format) + << " size: " << frame_size.ToString(); +} + +VideoCodec VideoCaptureDeviceTizen::GetCameraVideoCodec() { + // TODO(p.mirgos): retrieve video codec from camera + switch (format_) { + case media::PIXEL_FORMAT_ENCODED: + return media::VideoCodec::kH264; + default: + return media::VideoCodec::kUnknown; + } +} + +VideoCodecProfile VideoCaptureDeviceTizen::GetCameraVideoCodecProfile() { + // TODO(p.mirgos): retrieve video codec profile from camera + if (format_ == media::PIXEL_FORMAT_ENCODED) + return H264PROFILE_BASELINE; + return media::VIDEO_CODEC_PROFILE_UNKNOWN; +} + +VideoColorSpace VideoCaptureDeviceTizen::GetCameraColorSpace() { + // TODO(p.mirgos): retrieve color space from camera + return VideoColorSpace(media::VideoColorSpace::PrimaryID::UNSPECIFIED, + media::VideoColorSpace::TransferID::UNSPECIFIED, + media::VideoColorSpace::MatrixID::UNSPECIFIED, + gfx::ColorSpace::RangeID::LIMITED); +} + +VideoRotation VideoCaptureDeviceTizen::GetCurrentRotation() const noexcept { + NOTIMPLEMENTED(); + return media::VIDEO_ROTATION_0; +} + +int VideoCaptureDeviceTizen::GetFormatPriority(VideoPixelFormat format) { +#if defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT) + const std::array formats_priority = { + media::PIXEL_FORMAT_MJPEG, media::PIXEL_FORMAT_ENCODED}; + auto it = std::find(formats_priority.begin(), formats_priority.end(), format); + return std::distance(formats_priority.begin(), it); +#else + return format == PIXEL_FORMAT_ENCODED ? 0 : 1; +#endif } bool VideoCaptureDeviceTizen::SetCameraZoom( @@ -574,16 +754,14 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart( client_ = std::move(client); format_ = format; - camera_instance_ = CameraHandle::GetInstance(); - if (camera_instance_ == nullptr) { - SetErrorState("Failed to get camera instance", FROM_HERE); - return; - } + // After Tizen 6.5: Workaround for error in camera FW, where + // camera_set_extra_preview_cb would have no effect after camera state + // decreased to |CAMERA_STATE_CREATED| - if (camera_instance_->GetDeviceName() != - DeviceNameToCameraId(device_descriptor_)) { - camera_instance_->ResetHandle(DeviceNameToCameraId(device_descriptor_)); - } + // Before Tizen 6.5: unplug the first camera (CAMERA_DEVICE_CAMERA0), the + // second camera (CAMERA_DEVICE_CAMERA1) will change to CAMERA_DEVICE_CAMERA1 + // so even the index is same, we still need reset handle + camera_instance_->ResetHandle(device_descriptor_); camera_instance_->SetClient(this); if (!camera_instance_->IsValid()) { @@ -610,7 +788,6 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart( FROM_HERE); return; } - VideoPixelFormat reselected_format = ReselectCameraPreviewFormat(supported_formats); @@ -653,7 +830,7 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart( frame_rate_ = frame_rate; err = camera_instance_->CameraSetPreviewFps( - static_cast(frame_rate)); + static_cast(frame_rate_)); if (CAMERA_ERROR_NONE != err) { LOG(ERROR) << "cameraSetPreviewFps failed. Error# " << err; @@ -664,7 +841,6 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart( FROM_HERE); return; } - frame_rate_ = max_supported_fps; err = camera_instance_->CameraSetPreviewFps( @@ -676,7 +852,7 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart( } if (IsMobileProfile() && !IsEmulatorArch() && - (camera_instance_->GetDeviceName() == CAMERA_DEVICE_CAMERA1)) { + (camera_instance_->GetDeviceIndex() == CAMERA_DEVICE_CAMERA1)) { err = camera_instance_->CameraSetStreamFlip(CAMERA_FLIP_VERTICAL); if (CAMERA_ERROR_NONE != err) { SetErrorState(GetErrorString(err), FROM_HERE); @@ -793,6 +969,26 @@ void VideoCaptureDeviceTizen::OnCaptureCompletedCb() { } } +void VideoCaptureDeviceTizen::MaybeSuspend() { + LOG(INFO) << "VideoCaptureDeviceTizen::MaybeSuspend()"; + if (!IsTvProfile()) + return; + worker_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::StopPreview, + base::Unretained(this))); +} + +void VideoCaptureDeviceTizen::Resume() { + LOG(INFO) << "VideoCaptureDeviceTizen::Resume()"; + worker_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoCaptureDeviceTizen::ResumeStartPreview, + base::Unretained(this))); +} + +void VideoCaptureDeviceTizen::ResumeStartPreview() { + StartPreview(); +} + bool VideoCaptureDeviceTizen::StartPreview() { if (state_ != kAllocated) return false; diff --git a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h index 9b26e82..6980737 100644 --- a/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h +++ b/tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h @@ -8,9 +8,11 @@ #ifndef MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_TIZEN_H_ #define MEDIA_VIDEO_CAPTURE_TIZEN_VIDEO_CAPTURE_DEVICE_TIZEN_H_ +#include "base/synchronization/lock.h" #include "base/threading/thread.h" #include "base/time/time.h" #include "media/base/efl/media_player_util_efl.h" +#include "media/base/video_codecs.h" #include "media/capture/video/tizen/camera_device_tizen.h" #include "media/capture/video/video_capture_device.h" @@ -27,8 +29,9 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, const static char* GetBackCameraID(); explicit VideoCaptureDeviceTizen( - const VideoCaptureDeviceDescriptor& device_descriptor); - virtual ~VideoCaptureDeviceTizen() override; + const VideoCaptureDeviceDescriptor& device_descriptor, + CameraHandle* camera_instance); + ~VideoCaptureDeviceTizen() override; VideoCaptureDeviceTizen() = delete; VideoCaptureDeviceTizen(const VideoCaptureDeviceTizen&) = delete; @@ -40,24 +43,19 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, // Implements VideoCaptureDevice void AllocateAndStart(const VideoCaptureParams& params, std::unique_ptr client) override; - void StopAndDeAllocate() override; - bool StartPreview(); - void StopPreview(); - void GetPhotoState(GetPhotoStateCallback callback) override; void SetPhotoOptions(mojom::PhotoSettingsPtr settings, SetPhotoOptionsCallback callback) override; void TakePhoto(TakePhotoCallback callback) override; - static camera_device_e DeviceNameToCameraId( - const VideoCaptureDeviceDescriptor& device_descriptor); - static std::string GetCameraErrorMessage(int err_code); static void OnCameraCapturedWithMediaPacket(media_packet_h pkt, void* data); static void OnCameraCaptured(camera_preview_data_s* frame, void* data); - + static void OnCameraCaptureExtra(camera_preview_data_s* frame, + int stream_id, + void* data); static const char* GetErrorString(int err_code); static void CapturedCb(camera_image_data_s* image, camera_image_data_s* postview, @@ -65,6 +63,9 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, void* userData); static void CaptureCompletedCb(void* userData); + void MaybeSuspend() override; + void Resume() override; + private: enum InternalState { kIdle, // The device driver is opened but camera is not in use. @@ -81,12 +82,9 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, bool lazy_start, std::unique_ptr client); - // For handling the camera preview callback returning mediapacket - bool IsCapturing(); - void ChangeCapturingState(bool state); - void PreviewCameraCaptured(ScopedMediaPacket pkt); - - void SetErrorState(const char* reason, const base::Location& location); + bool StartPreview(); + void StopPreview(); + void ResumeStartPreview(); void OnStopAndDeAllocate(); @@ -95,6 +93,21 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, SetPhotoOptionsCallback callback); void OnCaptureCompletedCb(); + // For handling the camera preview callback returning mediapacket + bool IsCapturing(); + void ChangeCapturingState(bool state); + void PreviewCameraCaptured(ScopedMediaPacket pkt); + + void SetErrorState(const char* reason, const base::Location& location); + VideoCodec GetCameraVideoCodec(); + VideoCodecProfile GetCameraVideoCodecProfile(); + VideoColorSpace GetCameraColorSpace(); + VideoRotation GetCurrentRotation() const noexcept; + + // Determines the priority of video pixel format requested from camera. + // The lower value returned means the higher priority. + static int GetFormatPriority(VideoPixelFormat format); + bool SetCameraZoom(const mojom::PhotoSettingsPtr& settings); bool SetCameraResolution(const mojom::PhotoSettingsPtr& settings); bool SetCameraExposure(const mojom::PhotoSettingsPtr& settings); @@ -117,11 +130,16 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice, InternalState state_; base::TimeTicks first_ref_time_; + + // Capture parameters int frame_rate_{0}; media::VideoPixelFormat format_{media::PIXEL_FORMAT_UNKNOWN}; // List of |photo_callbacks_| in flight. std::list> photo_callbacks_; + + // statistics + int frame_total_{0}; // normally processed frames }; } // namespace media -- 2.7.4 From c8f452658044dce0f28847493c25dab9b737430b Mon Sep 17 00:00:00 2001 From: "qiang.ji" Date: Thu, 23 Mar 2023 10:17:01 +0800 Subject: [PATCH 12/16] [M108 Migration][VD] Support floating video window Support the new requirement of floating video window for WebBrowser. - Provide an api of ewk_view_floating_window_state_changed. Notify WebEngine the status that floating video window is on/off. If floating video window existed, but not current webView, For tabs switching case, in order to keep floating video window, need to prevent media resume. - Provide "notify,video,resized" for video rect notification. WebEngine notify WebBrowser playing video dimension in normal webview through which mini tab button is displayed at correct location on video. - Appended the document url to the paramater of "video,playing,url". In case video is playing inside an iframe, document URL provides URL loaded in iFrame to identify which document is playing video. - Allow to run the insecure content from localhost, that are http://127.0.0.1 and http://localhost. refs: https://review.tizen.org/gerrit/283144/ Change-Id: I3c8c0f4c2279e4cadcba471250a2e6e1c67729c6 Signed-off-by: qiang.ji --- .../renderer_host/render_widget_host_impl.cc | 6 ++ .../renderer_host/render_widget_host_impl.h | 3 + content/public/renderer/content_renderer_client.h | 3 + .../public/mojom/widget/platform_widget.mojom | 3 + third_party/blink/public/web/web_view.h | 4 ++ third_party/blink/public/web/web_view_client.h | 5 ++ .../blink/renderer/core/exported/web_view_impl.cc | 10 +++ .../blink/renderer/core/exported/web_view_impl.h | 4 ++ .../renderer/core/frame/web_frame_widget_impl.cc | 6 ++ .../renderer/core/frame/web_frame_widget_impl.h | 3 + .../renderer/core/html/media/html_media_element.cc | 72 ++++++++++++++++++++++ .../renderer/core/html/media/html_media_element.h | 17 +++++ third_party/blink/renderer/core/page/page.h | 10 +++ .../blink/renderer/platform/widget/widget_base.cc | 6 ++ .../blink/renderer/platform/widget/widget_base.h | 3 + .../renderer/platform/widget/widget_base_client.h | 9 +++ tizen_src/ewk/efl_integration/eweb_view.cc | 9 +++ tizen_src/ewk/efl_integration/eweb_view.h | 3 + tizen_src/ewk/efl_integration/public/ewk_view.cc | 6 +- .../renderer/content_renderer_client_efl.h | 14 +++++ 20 files changed, 194 insertions(+), 2 deletions(-) diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 84f8aae..02d6156 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1074,6 +1074,12 @@ void RenderWidgetHostImpl::OnGetSelectionRect(const gfx::Rect& rect) { void RenderWidgetHostImpl::ResetLastInteractedElements() { blink_widget_->ResetLastInteractedElements(); } + +#if BUILDFLAG(IS_TIZEN_TV) +void RenderWidgetHostImpl::SetFloatVideoWindowState(bool enabled) { + blink_widget_->SetFloatVideoWindowState(enabled); +} +#endif #endif blink::VisualProperties RenderWidgetHostImpl::GetInitialVisualProperties() { diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index b069615..99f88c4 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -464,6 +464,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl void RequestSelectionRect(); void OnGetSelectionRect(const gfx::Rect& rect); void ResetLastInteractedElements(); +#if BUILDFLAG(IS_TIZEN_TV) + void SetFloatVideoWindowState(bool enabled); +#endif #endif // Returns true if the RenderWidget is hidden. diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index d31fc6b..f89f2da 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h @@ -226,6 +226,9 @@ class CONTENT_EXPORT ContentRendererClient { blink::WebNavigationPolicy default_policy, bool is_redirect); #endif +#if BUILDFLAG(IS_TIZEN_TV) + virtual bool HasFloatingVideoWindowOn() const { return false; } +#endif // Notifies the embedder that the given frame is requesting the resource at // |url|. If the function returns a valid |new_url|, the request must be diff --git a/third_party/blink/public/mojom/widget/platform_widget.mojom b/third_party/blink/public/mojom/widget/platform_widget.mojom index 50071a7..b222ca4 100644 --- a/third_party/blink/public/mojom/widget/platform_widget.mojom +++ b/third_party/blink/public/mojom/widget/platform_widget.mojom @@ -155,6 +155,9 @@ interface Widget { [EnableIf=is_efl] RequestSelectionRect() => (gfx.mojom.Rect rect); + [EnableIf=is_tizen_tv] + SetFloatVideoWindowState(bool enabled); + // 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 5a25218..608a2ee 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h @@ -513,6 +513,10 @@ class BLINK_EXPORT WebView { virtual gfx::Rect CurrentSelectionRect() const = 0; #endif +#if BUILDFLAG(IS_TIZEN_TV) + virtual void SetFloatVideoWindowState(bool enable) = 0; +#endif + protected: ~WebView() = default; }; diff --git a/third_party/blink/public/web/web_view_client.h b/third_party/blink/public/web/web_view_client.h index d551e78..2435c9c 100644 --- a/third_party/blink/public/web/web_view_client.h +++ b/third_party/blink/public/web/web_view_client.h @@ -48,6 +48,11 @@ class WebViewClient { // the layers. virtual void InvalidateContainer() {} +#if BUILDFLAG(IS_TIZEN_TV) + // Floating Video Window + virtual bool HasFloatingVideoWindowOn() const { return false; } +#endif + // UI ------------------------------------------------------------------ // Called when the View has changed size as a result of an auto-resize. 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 316ae20..ad878e5 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc @@ -3565,6 +3565,16 @@ void WebViewImpl::RemoveObserver(WebViewObserver* observer) { observers_.RemoveObserver(observer); } +#if BUILDFLAG(IS_TIZEN_TV) +void WebViewImpl::SetFloatVideoWindowState(bool enable) { + if (!GetPage()) + return; + + LOG(INFO) << __FUNCTION__ << " enable : " << enable; + GetPage()->SetFloatVideoWindowState(enable); +} +#endif + void WebViewImpl::SetIsActive(bool active) { if (GetPage()) GetPage()->GetFocusController().SetActive(active); 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 952342b..18d4dd8 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h @@ -243,6 +243,10 @@ class CORE_EXPORT WebViewImpl final : public WebView, void AddObserver(WebViewObserver* observer); void RemoveObserver(WebViewObserver* observer); +#if defined(OS_TIZEN_TV_PRODUCT) + void SetFloatVideoWindowState(bool) override; +#endif // OS_TIZEN_TV_PRODUCT + // `BaseBackgroundColor()` affects how the document is rendered. // `BackgroundColor()` is what the document computes as its background color // (with `BaseBackgroundColor()` as an input), or `BaseBackgroundColor()` if 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 d6b3018..3f8d61b 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 @@ -4304,6 +4304,12 @@ bool WebFrameWidgetImpl::RequestMainFrameScrollbarVisible(bool& visible) { local_frame->HasVerticalScrollbar(); return true; } + +#if BUILDFLAG(IS_TIZEN_TV) +void WebFrameWidgetImpl::SetFloatVideoWindowState(bool enabled) { + View()->SetFloatVideoWindowState(enabled); +} +#endif #endif #if BUILDFLAG(IS_TIZEN) 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 80cc841..833586a 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 @@ -738,6 +738,9 @@ class CORE_EXPORT WebFrameWidgetImpl void SelectClosestWord(uint32_t x, uint32_t y) override; void SelectFocusedLink() override; gfx::Rect RequestSelectionRect() override; +#if BUILDFLAG(IS_TIZEN_TV) + void SetFloatVideoWindowState(bool enabled) override; +#endif #endif void OrientationChanged() override; diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index c96a6d2..85b1638 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc @@ -501,6 +501,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tag_name, tracks_are_ready_(true), processing_preference_change_(false), was_always_muted_(true), +#if BUILDFLAG(IS_TIZEN_TV) + is_deactivate_(false), +#endif #if defined(TIZEN_MULTIMEDIA) suspended_by_player_(false), #endif @@ -2742,6 +2745,9 @@ absl::optional HTMLMediaElement::Play() { absl::optional exception_code = autoplay_policy_->RequestPlay(); +#if BUILDFLAG(IS_TIZEN_TV) + is_deactivate_ = false; +#endif if (exception_code == DOMExceptionCode::kNotAllowedError) { // If we're already playing, then this play would do nothing anyway. @@ -4969,6 +4975,72 @@ void HTMLMediaElement::OpenerContextObserver::ContextDestroyed() { element_->AttachToNewFrame(); } +#if defined(TIZEN_MULTIMEDIA_SUPPORT) +void HTMLMediaElement::MediaPlayerHidden() { + LOG(INFO) << "Media player hidden: " << this; + // TODO(m.debski): It should store periodic timers and restore on shown. + // Currently they will still fire, but will return immediately. + suppress_events_ = true; +} + +void HTMLMediaElement::MediaPlayerShown() { + LOG(INFO) << "Media player shown: " << this; + suppress_events_ = false; +} + +void HTMLMediaElement::Suspend() { + LOG(INFO) << "Suspend(" << (void*)this << ")"; + if (!GetWebMediaPlayer()) + return; + +#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE) + if (media_source_attachment_) { + // Send suspend event to the source before WebMediaPlayer suspends backend. + media_source_attachment_->OnSuspend(media_source_tracer_); + } +#endif // SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE + + GetWebMediaPlayer()->Suspend(); +} + +void HTMLMediaElement::Resume() { + LOG(INFO) << "Resume(" << (void*)this << ")"; + if (!GetWebMediaPlayer()) + return; + +#if BUILDFLAG(IS_TIZEN_TV) + // IsViewResumedByTabSwitching, return true on the tab which has no + // floatwindow, otherwise it is false + if (GetDocument().GetPage() && + GetDocument().GetPage()->IsViewResumedByTabSwitching()) { + GetWebMediaPlayer()->Deactivate(); + LOG(INFO) << "is_deactivate_ TRUE"; + is_deactivate_ = true; + } else if (is_deactivate_) { + GetWebMediaPlayer()->Activate(); + LOG(INFO) << "is_deactivate_ FALSE"; + is_deactivate_ = false; + } +#endif + + GetWebMediaPlayer()->Resume(); + +#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE) + if (media_source_attachment_) { + // Send suspend event to the source after WebMediaPlayer resumes backend. + media_source_attachment_->OnResume(media_source_tracer_); + } +#endif // SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE +} + +void HTMLMediaElement::ActivatePlayer() { + if (!GetWebMediaPlayer()) + return; + + GetWebMediaPlayer()->Activate(); +} +#endif + STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveNothing, HTMLMediaElement::kHaveNothing); STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveMetadata, diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index 0677124..8a0e3ce 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h @@ -604,6 +604,14 @@ class CORE_EXPORT HTMLMediaElement void SetAudioSinkId(const String&) override; void SuspendForFrameClosed() override; +#if defined(TIZEN_MULTIMEDIA_SUPPORT) + void MediaPlayerHidden() final; + void MediaPlayerShown() final; + void Suspend(); + void Resume(); + void NotifyPlayingUrl(); +#endif + void LoadTimerFired(TimerBase*); void ProgressEventTimerFired(); void PlaybackProgressTimerFired(); @@ -858,6 +866,15 @@ class CORE_EXPORT HTMLMediaElement // playback raters other than 1.0. bool preserves_pitch_ = true; +#if BUILDFLAG(IS_TIZEN_TV) + bool is_deactivate_ : 1; +#endif + +#if defined(TIZEN_MULTIMEDIA_SUPPORT) + // This is to suppress stuff set to JS. Do not use it for other purposes. + bool suppress_events_ : 1; +#endif + #if defined(TIZEN_MULTIMEDIA) bool suspended_by_player_ : 1; #endif diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h index 3d0597b..e165464 100644 --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h @@ -402,6 +402,12 @@ class CORE_EXPORT Page final : public GarbageCollected, // with the 'persisted' property set to 'true'. bool DispatchedPagehidePersistedAndStillHidden(); +#if BUILDFLAG(IS_TIZEN_TV) + // Floating Video Window: record the page that has floating video window. + void SetFloatVideoWindowState(bool enable) { is_floating_page_ = enable; } + bool HasFloatingVideoWindowOn() const { return is_floating_page_; } +#endif + static void PrepareForLeakDetection(); // Fully invalidate paint of all local frames in this page. @@ -507,6 +513,10 @@ class CORE_EXPORT Page final : public GarbageCollected, bool is_painting_ = false; #endif +#if BUILDFLAG(IS_TIZEN_TV) + bool is_floating_page_ = false; +#endif + int subframe_count_; HeapHashSet> plugins_changed_observers_; diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index a699184..63fdc24 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc @@ -531,6 +531,12 @@ void WidgetBase::RequestSelectionRect(RequestSelectionRectCallback callback) { } #endif +#if BUILDFLAG(IS_TIZEN_TV) +void WidgetBase::SetFloatVideoWindowState(bool enabled) { + client_->SetFloatVideoWindowState(enabled); +} +#endif // IS_TIZEN_TV + 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 ad55f28..665bdcf 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.h +++ b/third_party/blink/renderer/platform/widget/widget_base.h @@ -150,6 +150,9 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget, void SetMainFrameScrollbarVisible(bool visible) override; void RequestMainFrameScrollbarVisible( RequestMainFrameScrollbarVisibleCallback callback) override; +#if BUILDFLAG(IS_TIZEN_TV) + void SetFloatVideoWindowState(bool enabled) override; +#endif // IS_TIZEN_TV void QueryInputType(QueryInputTypeCallback) override; void SelectClosestWord(uint32_t x, uint32_t y) override; void SelectFocusedLink() override; 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 d17c30f..4b4bd1e6 100644 --- a/third_party/blink/renderer/platform/widget/widget_base_client.h +++ b/third_party/blink/renderer/platform/widget/widget_base_client.h @@ -186,6 +186,15 @@ class WidgetBaseClient { virtual void SelectFocusedLink() {} virtual gfx::Rect RequestSelectionRect() { return gfx::Rect(); } virtual void ResetLastInteractedElements() {} + +#if BUILDFLAG(IS_TIZEN_TV) + virtual bool IsHitScrollbar() { return false; } + virtual bool IsMouseDownEventSwallowed() { return false; } + virtual void SuspendNetworkLoading() {} + virtual void ResumeNetworkLoading() {} + virtual void SetFloatVideoWindowState(bool enabled) {}; +#endif // IS_TIZEN_TV + #endif // Convert screen coordinates to device emulated coordinates (scaled diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index c0247ca..6df07b9 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -785,6 +785,15 @@ void EWebView::Resume() { #endif } +#if BUILDFLAG(IS_TIZEN_TV) +void EWebView::SetFloatVideoWindowState(bool enabled) { + RenderWidgetHostImpl* rwhi = static_cast( + web_contents_->GetRenderViewHost()->GetWidget()); + + rwhi->SetFloatVideoWindowState(enabled); +} +#endif // IS_TIZEN_TV + double EWebView::GetTextZoomFactor() const { if (text_zoom_factor_ < 0.0) return -1.0; diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index a5b33d5..981217e 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -347,6 +347,9 @@ class EWebView { void Suspend(); void Resume(); void Stop(); +#if BUILDFLAG(IS_TIZEN_TV) + void SetFloatVideoWindowState(bool enabled); +#endif // IS_TIZEN_TV void SetSessionTimeout(uint64_t timeout); double GetTextZoomFactor() const; void SetTextZoomFactor(double text_zoom_factor); diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index af9ed6d..118651a 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -1772,10 +1772,12 @@ void ewk_view_voicemanager_labels_clear(Evas_Object* view) { #endif } -void ewk_view_floating_window_state_changed(const Evas_Object *o, Eina_Bool status) +void ewk_view_floating_window_state_changed(const Evas_Object *view, Eina_Bool status) { #if BUILDFLAG(IS_TIZEN_TV) - EWK_VIEW_IMPL_GET_OR_RETURN(o, impl); + EWK_VIEW_IMPL_GET_OR_RETURN(view, impl); + LOG(INFO) << __FUNCTION__ << ", view: "<< view << ", status: " << status; + impl->SetFloatVideoWindowState(status); #else LOG_EWK_API_MOCKUP(); #endif diff --git a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h index 7ca20ad..f3b57c3 100644 --- a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h +++ b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.h @@ -63,6 +63,16 @@ class ContentRendererClientEfl : public content::ContentRendererClient { blink::WebNavigationPolicy default_policy, bool is_redirect) override; +#if BUILDFLAG(IS_TIZEN_TV) + // Floating Video Window + void SetFloatVideoWindowState(bool enable) { + floating_video_window_on_ = enable; + } + bool HasFloatingVideoWindowOn() const override { + return floating_video_window_on_; + } +#endif + void DidCreateScriptContext(content::RenderFrame* render_frame, v8::Handle context, int world_id); @@ -105,6 +115,10 @@ class ContentRendererClientEfl : public content::ContentRendererClient { std::unique_ptr visited_link_reader_; bool javascript_can_open_windows_ = true; bool shutting_down_ = false; + +#if BUILDFLAG(IS_TIZEN_TV) + bool floating_video_window_on_ = false; +#endif }; #endif // CONTENT_RENDERER_CLIENT_EFL_H -- 2.7.4 From cb26ca73432dddbf195aeda9a72446e35ce64885 Mon Sep 17 00:00:00 2001 From: DongHyun Song Date: Mon, 27 Mar 2023 09:21:03 +0900 Subject: [PATCH 13/16] Add IS_TIZEN guard for XWalkExtension XWalkExtension can be enabled with IS_TIZEN and this will fix build break for the desktop profile. Change-Id: I0edb4a3c33a42a4637bebce0b3c74cd683f8ccf2 Signed-off-by: DongHyun Song --- content/browser/browser_interface_binders.cc | 4 ++-- tizen_src/ewk/efl_integration/content_browser_client_efl.cc | 5 ++++- tizen_src/ewk/efl_integration/content_main_delegate_efl.cc | 8 +++++++- .../efl_integration/renderer/content_renderer_client_efl.cc | 11 ++++++++--- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 1d3cc71..567d15d 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc @@ -210,7 +210,7 @@ #include "content/browser/date_time_chooser_efl.h" #endif -#if defined(ENABLE_WRT_JS) +#if BUILDFLAG(IS_TIZEN) #include "tizen_src/chromium_impl/components/xwalk_extensions/browser/xwalk_extension_manager.h" #endif @@ -1208,7 +1208,7 @@ void PopulateDedicatedWorkerBinders(DedicatedWorkerHost* host, map->Add(BindWorkerReceiverForStorageKey( &RenderProcessHostImpl::BindQuotaManagerHost, host)); -#if defined(ENABLE_WRT_JS) +#if BUILDFLAG(IS_TIZEN) map->Add(base::BindRepeating( &wrt::XWalkExtensionManager::Bind)); #endif 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 e93b875..9810adc 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -24,7 +24,6 @@ #include "components/error_page/common/localized_error.h" #include "components/navigation_interception/intercept_navigation_throttle.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" -#include "components/xwalk_extensions/browser/xwalk_extension_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_process_host.h" @@ -47,6 +46,8 @@ #if BUILDFLAG(IS_TIZEN) #include + +#include "components/xwalk_extensions/browser/xwalk_extension_manager.h" #endif #include "private/ewk_notification_private.h" @@ -652,9 +653,11 @@ void ContentBrowserClientEfl::ExposeInterfacesToRenderer( switches::kXWalkExtensionJsonPath)) { return; } +#if BUILDFLAG(IS_TIZEN) registry->AddInterface( base::BindRepeating(&wrt::XWalkExtensionManager::Bind), content::GetUIThreadTaskRunner({})); +#endif } #if BUILDFLAG(IS_TIZEN_TV) diff --git a/tizen_src/ewk/efl_integration/content_main_delegate_efl.cc b/tizen_src/ewk/efl_integration/content_main_delegate_efl.cc index 7024865..08b3a35 100644 --- a/tizen_src/ewk/efl_integration/content_main_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/content_main_delegate_efl.cc @@ -8,7 +8,6 @@ #include "browser/xwalk_extension_browser_efl.h" #include "command_line_efl.h" #include "common/content_switches_efl.h" -#include "components/xwalk_extensions/browser/xwalk_extension_manager.h" #include "content/browser/gpu/gpu_main_thread_factory.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/common/locale_efl.h" @@ -18,6 +17,11 @@ #include "content_browser_client_efl.h" #include "renderer/content_renderer_client_efl.h" #include "ui/base/resource/resource_bundle.h" + +#if BUILDFLAG(IS_TIZEN) +#include "components/xwalk_extensions/browser/xwalk_extension_manager.h" +#endif + #if BUILDFLAG(IS_TIZEN_TV) #include "content/public/browser/render_process_host.h" #include "devtools_port_manager.h" @@ -94,6 +98,7 @@ void ContentMainDelegateEfl::PreSandboxStartupBrowser() { // needed for gpu thread content::RegisterGpuMainThreadFactory(CreateInProcessGpuThread); +#if BUILDFLAG(IS_TIZEN) // switches::kXWalkExtensionJsonPath SHOULD be set before MainDelegate init. auto json_path = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( @@ -105,6 +110,7 @@ void ContentMainDelegateEfl::PreSandboxStartupBrowser() { extension_manager->SetDelegate( std::make_unique()); } +#endif } void ContentMainDelegateEfl::PreSandboxStartup() { 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 7342715..c55cca8 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 @@ -9,6 +9,8 @@ #if BUILDFLAG(IS_TIZEN) #include + +#include "components/xwalk_extensions/renderer/xwalk_extension_renderer_controller.h" #endif #include "base/command_line.h" @@ -17,7 +19,6 @@ #include "common/content_switches_efl.h" #include "common/render_messages_ewk.h" #include "components/visitedlink/renderer/visitedlink_reader.h" -#include "components/xwalk_extensions/renderer/xwalk_extension_renderer_controller.h" #include "content/common/locale_efl.h" #include "content/common/paths_efl.h" #include "content/public/common/content_switches.h" @@ -169,6 +170,7 @@ void ContentRendererClientEfl::RenderThreadStarted() { if (!command_line.HasSwitch(switches::kSingleProcess)) LocaleEfl::Initialize(); +#if BUILDFLAG(IS_TIZEN) if (command_line.HasSwitch(switches::kXWalkExtensionJsonPath)) { wrt::XWalkExtensionRendererController::GetInstance().SetPrivilegeChecker( base::BindRepeating([]() -> bool { @@ -177,6 +179,7 @@ void ContentRendererClientEfl::RenderThreadStarted() { return true; })); } +#endif } void ContentRendererClientEfl::RenderFrameCreated(content::RenderFrame* render_frame) { @@ -268,9 +271,10 @@ void ContentRendererClientEfl::DidCreateScriptContext( content::RenderFrame* render_frame, v8::Handle context, int world_id) { +#if BUILDFLAG(IS_TIZEN) if (ShouldRegisterXWalkExtension(world_id)) wrt::XWalkExtensionRendererController::DidCreateScriptContext(context); - +#endif if (!widget_) return; @@ -299,9 +303,10 @@ void ContentRendererClientEfl::WillReleaseScriptContext( blink::WebFrame* frame, v8::Handle context, int world_id) { +#if BUILDFLAG(IS_TIZEN) if (ShouldRegisterXWalkExtension(world_id)) wrt::XWalkExtensionRendererController::WillReleaseScriptContext(context); - +#endif if (widget_) widget_->StopSession(context); } -- 2.7.4 From f24ac826223268878f4d2f225174af12e728308c Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 24 Mar 2023 13:20:10 +0530 Subject: [PATCH 14/16] Fix major SVACE issues This patch fixes major SVACE issues. Change-Id: Ie5fbe44a3aa99aa1589718a8d7d64d75453ef5d0 Signed-off-by: Ayush Kumar --- .../browser/renderer_host/rwhv_aura_common_helper_efl.cc | 10 +++++----- .../renderer_host/rwhv_aura_offscreen_helper_efl.cc | 16 +++++++++------- .../chromium_impl/ui/base/clipboard/clipboard_efl.cc | 1 + .../browser/autofill/autofill_client_efl.cc | 1 + tizen_src/ewk/efl_integration/eweb_view.cc | 9 +++++---- tizen_src/ewk/efl_integration/login_delegate_efl.cc | 3 +++ .../efl_integration/public/ewk_media_playback_info.cc | 1 + tizen_src/ewk/efl_integration/public/ewk_view.cc | 1 + .../renderer/plugins/plugin_placeholder_hole.cc | 3 +++ 9 files changed, 29 insertions(+), 16 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc index 0f7e55a..7c3a3d8 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.cc @@ -275,12 +275,12 @@ ui::IMContextEfl* RWHVAuraCommonHelperEfl::GetIMContextEfl() { // im_context_efl_ is always nullptr on desktop efl. #if BUILDFLAG(IS_TIZEN) if (!im_context_efl_) { - if (GetEventHandler() && GetEventHandler()->GetIMContextEfl()) { - im_context_efl_ = GetEventHandler()->GetIMContextEfl(); + im_context_efl_ = + GetEventHandler() ? GetEventHandler()->GetIMContextEfl() : nullptr; + if (im_context_efl_) im_context_efl_->SetRWHHelper(rwh_helper_.get()); - return im_context_efl_; - } - LOG(ERROR) << "im_context_efl_ is not set"; + else + LOG(ERROR) << "im_context_efl_ is not set"; } #endif return im_context_efl_; 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 96feda0..c09f396 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 @@ -1067,13 +1067,15 @@ void RWHVAuraOffscreenHelperEfl::RequestMagnifierSnapshotAsync( gfx::Rect view_rect = GetViewBoundsInPix(); // Adjust snapshot rect for email app - auto visible_viewport_rect = - GetSelectionController()->GetVisibleViewportRect(); - int hidden_view_width = visible_viewport_rect.x() - view_rect.x(); - int hidden_view_height = visible_viewport_rect.y() - view_rect.y(); - if (hidden_view_height || hidden_view_width) { - snapshot_area.set_x(snapshot_area.x() + hidden_view_width); - snapshot_area.set_y(snapshot_area.y() + hidden_view_height); + if (GetSelectionController()) { + auto visible_viewport_rect = + GetSelectionController()->GetVisibleViewportRect(); + int hidden_view_width = visible_viewport_rect.x() - view_rect.x(); + int hidden_view_height = visible_viewport_rect.y() - view_rect.y(); + if (hidden_view_height || hidden_view_width) { + snapshot_area.set_x(snapshot_area.x() + hidden_view_width); + snapshot_area.set_y(snapshot_area.y() + hidden_view_height); + } } magnifier_snapshot_request_ = diff --git a/tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.cc b/tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.cc index 032fc01..dd7325a 100644 --- a/tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.cc +++ b/tizen_src/chromium_impl/ui/base/clipboard/clipboard_efl.cc @@ -232,5 +232,6 @@ std::vector ClipboardEfl::GetStandardFormats( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { NOTIMPLEMENTED(); + return {}; } } //namespace ui diff --git a/tizen_src/ewk/efl_integration/browser/autofill/autofill_client_efl.cc b/tizen_src/ewk/efl_integration/browser/autofill/autofill_client_efl.cc index 2b7103d..de49c85 100644 --- a/tizen_src/ewk/efl_integration/browser/autofill/autofill_client_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/autofill/autofill_client_efl.cc @@ -402,6 +402,7 @@ void AutofillClientEfl::UpdateWebauthnOfferDialogWithError() { bool AutofillClientEfl::CloseWebauthnDialog() { NOTIMPLEMENTED(); + return false; } void AutofillClientEfl::ConfirmSaveUpiIdLocally( diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 6df07b9..f3909f7 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -833,10 +833,11 @@ void EWebView::ExecuteEditCommand(const char* command, const char* value) { optional_value = absl::make_optional(base::ASCIIToUTF16(value)); WebContentsImpl* wc = static_cast(web_contents_.get()); - if (wc && wc->GetFocusedFrameWidgetInputHandler()) { - wc->GetFocusedFrameWidgetInputHandler()->ExecuteEditCommand( - std::string(command), optional_value); - } + if (!wc || !wc->GetFocusedFrameWidgetInputHandler()) + return; + + wc->GetFocusedFrameWidgetInputHandler()->ExecuteEditCommand( + std::string(command), optional_value); } #if BUILDFLAG(IS_TIZEN) diff --git a/tizen_src/ewk/efl_integration/login_delegate_efl.cc b/tizen_src/ewk/efl_integration/login_delegate_efl.cc index 708a1de..ecac7d9 100644 --- a/tizen_src/ewk/efl_integration/login_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/login_delegate_efl.cc @@ -55,6 +55,9 @@ void LoginDelegateEfl::HandleHttpAuthRequestOnUIThread() { web_contents_->GetDelegate()); if (first_auth_attempt_ && auth_info_->is_proxy) { + if (!delegate->web_view() || !delegate->web_view()->context()) + return; + const EWebContext* web_context = delegate->web_view()->context()->GetImpl(); DCHECK(web_context); diff --git a/tizen_src/ewk/efl_integration/public/ewk_media_playback_info.cc b/tizen_src/ewk/efl_integration/public/ewk_media_playback_info.cc index 1d7d318..4f36ddbb 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_media_playback_info.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_media_playback_info.cc @@ -94,6 +94,7 @@ void ewk_media_playback_info_decoder_set( const int ewk_media_playback_info_video_id_get(Ewk_Media_Playback_Info* data) { LOG_EWK_API_MOCKUP(); + return 0; } Ewk_Media_Playback_Info* ewkMediaPlaybackInfoCreate(const int player_id, diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 118651a..14ab2d0 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -1009,6 +1009,7 @@ char* ewk_view_get_cookies_for_url(Evas_Object* view, const char* url) EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(url, 0); EINA_SAFETY_ON_NULL_RETURN_VAL(impl->context(), 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(impl->context()->cookieManager(), 0); std::string cookiesForURL = impl->context()->cookieManager()->GetCookiesForURL(std::string(url)); if (cookiesForURL.empty()) diff --git a/tizen_src/ewk/efl_integration/renderer/plugins/plugin_placeholder_hole.cc b/tizen_src/ewk/efl_integration/renderer/plugins/plugin_placeholder_hole.cc index a78eed8..a5730a6 100644 --- a/tizen_src/ewk/efl_integration/renderer/plugins/plugin_placeholder_hole.cc +++ b/tizen_src/ewk/efl_integration/renderer/plugins/plugin_placeholder_hole.cc @@ -413,6 +413,9 @@ void PluginPlaceholderHole::NotifyGeometryChanged() { v8::Local func_handle = v8::Local::Cast(func_val); v8::TryCatch try_catch(isolate); + if (!plugin() || !plugin()->Container()) + return; + gfx::Point position_in_root_frame = plugin()->Container()->LocalToRootFramePoint(local_rect_.origin()); -- 2.7.4 From 903a554f50298b3404e909343aa370b683911fb1 Mon Sep 17 00:00:00 2001 From: jiangyuwei Date: Thu, 23 Mar 2023 15:43:29 +0800 Subject: [PATCH 15/16] [M108 Migration][VD] Enable Suspend & resume feature Because RenderViewObserverEfl unavailable in M108, so need to implement in widget.mojom References: - https://review.tizen.org/gerrit/284921/ Change-Id: Ib558fcb5a21f34c0aaf7946b07c161342ee74e1a Signed-off-by: jiangyuwei --- .../renderer_host/render_widget_host_impl.cc | 10 +++++ .../renderer_host/render_widget_host_impl.h | 5 +++ content/public/browser/render_view_host.h | 5 +++ .../public/mojom/widget/platform_widget.mojom | 6 +++ third_party/blink/public/web/web_view.h | 5 +++ .../blink/renderer/core/exported/web_view_impl.cc | 49 ++++++++++++++++++++++ .../blink/renderer/core/exported/web_view_impl.h | 5 +++ .../renderer/core/frame/web_frame_widget_impl.cc | 10 +++++ .../renderer/core/frame/web_frame_widget_impl.h | 5 +++ third_party/blink/renderer/core/page/page.cc | 9 ++++ third_party/blink/renderer/core/page/page.h | 24 +++++++++++ .../blink/renderer/platform/widget/widget_base.cc | 10 +++++ .../blink/renderer/platform/widget/widget_base.h | 6 +++ .../renderer/platform/widget/widget_base_client.h | 5 +++ .../efl_integration/common/render_messages_ewk.h | 2 - tizen_src/ewk/efl_integration/eweb_view.cc | 21 +++------- 16 files changed, 160 insertions(+), 17 deletions(-) diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 02d6156..05c1be4 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -592,6 +592,16 @@ void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) { } } +#if BUILDFLAG(IS_TIZEN) +void RenderWidgetHostImpl::PauseScheduledTasks() { + blink_widget_->PauseScheduledTasks(); +} + +void RenderWidgetHostImpl::UnPauseScheduledTasks() { + blink_widget_->UnPauseScheduledTasks(); +} +#endif + // static const base::TimeDelta RenderWidgetHostImpl::kActivationNotificationExpireTime = base::Milliseconds(300); diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 99f88c4..937c437 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -469,6 +469,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl #endif #endif +#if BUILDFLAG(IS_TIZEN) + void PauseScheduledTasks(); + void UnPauseScheduledTasks(); +#endif + // Returns true if the RenderWidget is hidden. bool is_hidden() const { return is_hidden_; } diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h index 9979c25..821d751 100644 --- a/content/public/browser/render_view_host.h +++ b/content/public/browser/render_view_host.h @@ -71,6 +71,11 @@ class CONTENT_EXPORT RenderViewHost { // Instructs the `blink::WebView` to send back updates to the preferred size. virtual void EnablePreferredSizeMode() = 0; +#if BUILDFLAG(IS_TIZEN) + // Returns true if the RenderView is active and has not crashed. + virtual bool IsRenderViewLive() const = 0; +#endif + using TraceProto = perfetto::protos::pbzero::RenderViewHost; // Write a representation of this object into a trace. virtual void WriteIntoTrace( diff --git a/third_party/blink/public/mojom/widget/platform_widget.mojom b/third_party/blink/public/mojom/widget/platform_widget.mojom index b222ca4..1e348d4 100644 --- a/third_party/blink/public/mojom/widget/platform_widget.mojom +++ b/third_party/blink/public/mojom/widget/platform_widget.mojom @@ -143,6 +143,12 @@ interface Widget { [EnableIf=is_efl] PrintToPdf(uint32 width, uint32 height, mojo_base.mojom.FilePath filename); + [EnableIf=is_tizen] + PauseScheduledTasks(); + + [EnableIf=is_tizen] + UnPauseScheduledTasks(); + [EnableIf=is_efl] QueryInputType() => (bool input_type); diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index 608a2ee..3f8f71a 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h @@ -412,6 +412,11 @@ class BLINK_EXPORT WebView { // Freezes or unfreezes the page and all the local frames. virtual void SetPageFrozen(bool frozen) = 0; +#if BUILDFLAG(IS_TIZEN) + virtual void PauseScheduledTasks() = 0; + virtual void UnpauseScheduledTasks() = 0; +#endif + // Autoplay configuration ----------------------------------------------- // Sets the autoplay flags for this webview's page. 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 ad878e5..ef2abd1 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc @@ -184,6 +184,10 @@ #include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/skia_conversions.h" +#if BUILDFLAG(IS_TIZEN_TV) +#include "third_party/blink/public/platform/web_application_type.h" +#endif + #if !BUILDFLAG(IS_MAC) #include "skia/ext/legacy_display_globals.h" #include "third_party/blink/public/platform/web_font_render_style.h" @@ -1287,6 +1291,51 @@ void WebViewImpl::DidUpdateBrowserControls() { } } +#if BUILDFLAG(IS_TIZEN) +void WebViewImpl::PauseScheduledTasks() { + if (!MainFrameImpl()) + return; + + if (Page* page = GetPage()) { + page->SetIsSuspended(true); + page->SetPaused(true); + } + +#if BUILDFLAG(IS_TIZEN_TV) + // when browser/app switch to BG and did not hidden webview ,the behavior cause + // high cpu issue.So we need to suspend compositor thread. + LOG(INFO) << "APP now suspend"; + MainFrameImpl()->FrameWidgetImpl()->SetCompositorVisible(false); +#endif +} + +void WebViewImpl::UnpauseScheduledTasks() { + if (!MainFrameImpl()) + return; + Page* page = GetPage(); + if (!page) + return; +#if BUILDFLAG(IS_TIZEN_TV) + // If floating video window existed and not current page, need to prevent + // media resume + LOG(INFO) << "APP now resume"; + if (IsWebBrowser()) { + if (Client()->HasFloatingVideoWindowOn() && + page->IsFloatingPage()) { + LOG(INFO) << "Floating video window existed, but not current page"; + page->NotifyViewResumedByTabSwitching(true); + } else { + page->NotifyViewResumedByTabSwitching(false); + } + } + MainFrameImpl()->FrameWidgetImpl()->SetCompositorVisible(true); +#endif + + page->SetIsSuspended(false); + page->SetPaused(false); +} +#endif + BrowserControls& WebViewImpl::GetBrowserControls() { return GetPage()->GetBrowserControls(); } 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 18d4dd8..3c1075a 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h @@ -522,6 +522,11 @@ class CORE_EXPORT WebViewImpl final : public WebView, WebSettingsImpl* SettingsImpl(); +#if BUILDFLAG(IS_TIZEN) + virtual void PauseScheduledTasks(); + virtual void UnpauseScheduledTasks(); +#endif + BrowserControls& GetBrowserControls(); // Called anytime browser controls layout height or content offset have // changed. 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 3f8d61b..8b057e4 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 @@ -4328,6 +4328,16 @@ void WebFrameWidgetImpl::OrientationChanged() { local_root_->SendOrientationChangeEvent(); } +#if BUILDFLAG(IS_TIZEN) +void WebFrameWidgetImpl::PauseScheduledTasks() { + View()->PauseScheduledTasks(); +} + +void WebFrameWidgetImpl::UnPauseScheduledTasks() { + View()->UnpauseScheduledTasks(); +} +#endif + void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen( const display::ScreenInfos& previous_original_screen_infos) { display::ScreenInfo screen_info = widget_base_->GetScreenInfo(); 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 833586a..b97c4a9 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 @@ -743,6 +743,11 @@ class CORE_EXPORT WebFrameWidgetImpl #endif #endif +#if BUILDFLAG(IS_TIZEN) + void PauseScheduledTasks() override; + void UnPauseScheduledTasks() override; +#endif + void OrientationChanged() override; void DidUpdateSurfaceAndScreen( const display::ScreenInfos& previous_original_screen_infos) override; diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 2ad0cb0..2985dc4 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc @@ -229,6 +229,9 @@ Page::Page(base::PassKey, next_related_page_(this), prev_related_page_(this), autoplay_flags_(0), +#if BUILDFLAG(IS_TIZEN) + m_isSuspended(false), +#endif web_text_autosizer_page_info_({0, 0, 1.f}) { DCHECK(!AllPages().Contains(this)); AllPages().insert(this); @@ -1144,6 +1147,12 @@ void Page::SetVisionDeficiency(VisionDeficiency new_vision_deficiency) { } } +#if BUILDFLAG(IS_TIZEN) +void Page::SetIsSuspended(bool isSuspended) { + m_isSuspended = isSuspended; +} +#endif + void Page::Animate(base::TimeTicks monotonic_frame_begin_time) { GetAutoscrollController().Animate(); Animator().ServiceScriptedAnimations(monotonic_frame_begin_time); diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h index e165464..0414e1f 100644 --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h @@ -361,6 +361,12 @@ class CORE_EXPORT Page final : public GarbageCollected, const mojom::blink::TextAutosizerPageInfo& page_info) { web_text_autosizer_page_info_ = page_info; } + +#if BUILDFLAG(IS_TIZEN) + void SetIsSuspended(bool); + bool IsSuspended() const { return m_isSuspended; }; +#endif + const mojom::blink::TextAutosizerPageInfo& TextAutosizerPageInfo() const { return web_text_autosizer_page_info_; } @@ -410,6 +416,16 @@ class CORE_EXPORT Page final : public GarbageCollected, static void PrepareForLeakDetection(); +#if BUILDFLAG(IS_TIZEN_TV) + bool IsFloatingPage() const { return is_floating_page_; } + void NotifyViewResumedByTabSwitching(bool enable) { + is_view_resumed_by_tab_switching_ = enable; + } + bool IsViewResumedByTabSwitching() const { + return is_view_resumed_by_tab_switching_; + } +#endif + // Fully invalidate paint of all local frames in this page. void InvalidatePaint(); @@ -519,6 +535,10 @@ class CORE_EXPORT Page final : public GarbageCollected, int subframe_count_; +#if BUILDFLAG(IS_TIZEN_TV) + bool is_view_resumed_by_tab_switching_ = false; +#endif + HeapHashSet> plugins_changed_observers_; // A circular, double-linked list of pages that are related to the current @@ -538,6 +558,10 @@ class CORE_EXPORT Page final : public GarbageCollected, // Emulated vision deficiency, set from DevTools. VisionDeficiency vision_deficiency_ = VisionDeficiency::kNoVisionDeficiency; +#if BUILDFLAG(IS_TIZEN) + bool m_isSuspended; +#endif + int32_t autoplay_flags_; // Accessed by frames to determine whether to expose the PortalHost object. diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index 63fdc24..e585cd2 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc @@ -552,6 +552,16 @@ void WidgetBase::WasHidden() { client_->WasHidden(); } +#if BUILDFLAG(IS_TIZEN) +void WidgetBase::PauseScheduledTasks() { + client_->PauseScheduledTasks(); +} + +void WidgetBase::UnPauseScheduledTasks() { + client_->UnPauseScheduledTasks(); +} +#endif + void WidgetBase::WasShown(bool was_evicted, mojom::blink::RecordContentToVisibleTimeRequestPtr record_tab_switch_time_request) { diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h index 665bdcf..9c9b39e 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.h +++ b/third_party/blink/renderer/platform/widget/widget_base.h @@ -159,6 +159,12 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget, void RequestSelectionRect(RequestSelectionRectCallback callback) override; void ResetLastInteractedElements() override; #endif + +#if BUILDFLAG(IS_TIZEN) + void PauseScheduledTasks() override; + void UnPauseScheduledTasks() 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 4b4bd1e6..51910af 100644 --- a/third_party/blink/renderer/platform/widget/widget_base_client.h +++ b/third_party/blink/renderer/platform/widget/widget_base_client.h @@ -197,6 +197,11 @@ class WidgetBaseClient { #endif +#if BUILDFLAG(IS_TIZEN) + virtual void PauseScheduledTasks() {} + virtual void UnPauseScheduledTasks() {} +#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/ewk/efl_integration/common/render_messages_ewk.h b/tizen_src/ewk/efl_integration/common/render_messages_ewk.h index b2ed7f2..b211d96 100644 --- a/tizen_src/ewk/efl_integration/common/render_messages_ewk.h +++ b/tizen_src/ewk/efl_integration/common/render_messages_ewk.h @@ -147,8 +147,6 @@ IPC_MESSAGE_ROUTED4(EwkViewMsg_DoHitTestAsync, // Tells the renderer to clear the cache. IPC_MESSAGE_ROUTED0(EwkViewMsg_UseSettingsFont) IPC_MESSAGE_ROUTED0(EwkViewMsg_SetBrowserFont) -IPC_MESSAGE_ROUTED0(EwkViewMsg_SuspendScheduledTask) -IPC_MESSAGE_ROUTED0(EwkViewMsg_ResumeScheduledTasks) IPC_MESSAGE_ROUTED2(EwkViewMsg_SetScroll, int, /* horizontal position */ diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index f3909f7..5ba9fd0 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -757,13 +757,10 @@ void EWebView::Suspend() { #if !defined(EWK_BRINGUP) // FIXME: m69 bringup rfh->BlockRequestsForFrame(); #endif -#if 0 - content::GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce( - &content::ResourceDispatcherHost::BlockRequestsForFrameFromUI, rfh)); - - if (rvh) - rvh->Send(new EwkViewMsg_SuspendScheduledTask(rvh->GetRoutingID())); -#endif + if (rvh->IsRenderViewLive()) { + RenderWidgetHostImpl* rwhi = static_cast(rvh->GetWidget()); + rwhi->PauseScheduledTasks(); + } } void EWebView::Resume() { @@ -775,14 +772,8 @@ void EWebView::Resume() { #if !defined(EWK_BRINGUP) // FIXME: m69 bringup rfh->ResumeBlockedRequestsForFrame(); #endif -#if 0 - content::GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce( - &content::ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI, - rfh)); - - if (rvh) - rvh->Send(new EwkViewMsg_ResumeScheduledTasks(rvh->GetRoutingID())); -#endif + if (rvh->IsRenderViewLive() && rwhva()) + rwhva()->host()->UnPauseScheduledTasks(); } #if BUILDFLAG(IS_TIZEN_TV) -- 2.7.4 From 93499dc65a8b237c3a21e873db49bf4286fa9705 Mon Sep 17 00:00:00 2001 From: v-saha Date: Fri, 24 Mar 2023 18:32:47 +0530 Subject: [PATCH 16/16] Fix critical SVACE issue This patch fixes some critical SVACE issues. Change-Id: I48296ccf49643421f7210d8d8d0502f31f38705a Signed-off-by: v-saha --- .../renderer/xwalk_extension_renderer_controller.cc | 2 +- tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h | 4 ++-- .../chromium_impl/content/browser/selection/selection_handle_efl.h | 2 +- .../content/browser/selection/selection_magnifier_efl.h | 6 +++--- .../content/browser/web_contents/web_contents_impl_efl.cc | 6 +++--- .../ewk/efl_integration/browser/web_view_browser_message_filter.cc | 2 ++ tizen_src/ewk/efl_integration/eweb_context.h | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tizen_src/chromium_impl/components/xwalk_extensions/renderer/xwalk_extension_renderer_controller.cc b/tizen_src/chromium_impl/components/xwalk_extensions/renderer/xwalk_extension_renderer_controller.cc index 71ac916..37c5198 100644 --- a/tizen_src/chromium_impl/components/xwalk_extensions/renderer/xwalk_extension_renderer_controller.cc +++ b/tizen_src/chromium_impl/components/xwalk_extensions/renderer/xwalk_extension_renderer_controller.cc @@ -210,7 +210,7 @@ int32_t XWalkExtensionRendererController::CreateInstance( return 0; } - int32_t id; + int32_t id = 0; browser_->CreateInstance(module->GetName(), &id, &jscode); instance_map_[id] = module; return id; diff --git a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h index f11164e..532b99d 100644 --- a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h +++ b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h @@ -165,8 +165,8 @@ class CONTENT_EXPORT TizenRendererImpl // Identifiers to find the RenderFrameHost that created |this|. // NOTE: We store these IDs rather than a RenderFrameHost* because we do not // know when the RenderFrameHost is destroyed. - int render_process_id_; - int routing_id_; + int render_process_id_ = 0; + int routing_id_ = 0; // Temporary callback used for Initialize(). media::PipelineStatusCallback init_cb_; diff --git a/tizen_src/chromium_impl/content/browser/selection/selection_handle_efl.h b/tizen_src/chromium_impl/content/browser/selection/selection_handle_efl.h index a886fbf..5fe2795 100644 --- a/tizen_src/chromium_impl/content/browser/selection/selection_handle_efl.h +++ b/tizen_src/chromium_impl/content/browser/selection/selection_handle_efl.h @@ -85,7 +85,7 @@ class SelectionHandleEfl { SelectionControllerEfl& controller_; // Handle object - Evas_Object* handle_; + Evas_Object* handle_ = nullptr; // Is pressed bool pressed_; diff --git a/tizen_src/chromium_impl/content/browser/selection/selection_magnifier_efl.h b/tizen_src/chromium_impl/content/browser/selection/selection_magnifier_efl.h index a693783..50dd9af 100644 --- a/tizen_src/chromium_impl/content/browser/selection/selection_magnifier_efl.h +++ b/tizen_src/chromium_impl/content/browser/selection/selection_magnifier_efl.h @@ -42,16 +42,16 @@ class SelectionMagnifierEfl { SelectionControllerEfl* controller_; // Magnifier - Evas_Object* container_; + Evas_Object* container_ = nullptr; // Image displayed on popup Evas_Object* content_image_; // Magnifier Height - int height_; + int height_ = 0; // Magnifier width - int width_; + int width_ = 0; // Is magnifier showing bool shown_; diff --git a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc index b122681..d61070d 100644 --- a/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc +++ b/tizen_src/chromium_impl/content/browser/web_contents/web_contents_impl_efl.cc @@ -135,9 +135,9 @@ FrameTree* WebContentsImplEfl::CreateNewWindow( if (efl_delegate_) { if (efl_delegate_->WebContentsCreateAsync(std::move(callback))) { - DCHECK(new_contents); - return &( - static_cast(new_contents)->GetPrimaryFrameTree()); + return new_contents ? &(static_cast(new_contents) + ->GetPrimaryFrameTree()) + : nullptr; } else { return nullptr; } diff --git a/tizen_src/ewk/efl_integration/browser/web_view_browser_message_filter.cc b/tizen_src/ewk/efl_integration/browser/web_view_browser_message_filter.cc index 96a0cd3..139d271 100644 --- a/tizen_src/ewk/efl_integration/browser/web_view_browser_message_filter.cc +++ b/tizen_src/ewk/efl_integration/browser/web_view_browser_message_filter.cc @@ -41,6 +41,8 @@ class WebViewBrowserMessageFilterPrivate CHECK(web_view_); } + virtual ~WebViewBrowserMessageFilterPrivate() = default; + void OnReceivedHitTestData(int render_view, const Hit_Test_Params& params) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); diff --git a/tizen_src/ewk/efl_integration/eweb_context.h b/tizen_src/ewk/efl_integration/eweb_context.h index dab08bc..eb910a2 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.h +++ b/tizen_src/ewk/efl_integration/eweb_context.h @@ -216,7 +216,7 @@ class EWebContext { private: EWebContext(bool incognito, const std::string& injectedBundlePath); - ~EWebContext(); + virtual ~EWebContext(); friend class Ewk_Context; static void LocalStorageUsageForOrigin( const GURL& origin, -- 2.7.4