From 98f11ec6b5abdba1b5fb22a59da3a9f1ccf7d6a8 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Thu, 19 Jan 2023 11:00:29 +0530 Subject: [PATCH 01/16] [M108 Migration][API] Migrate favicon related patches This change adds modification related to favicon. References: https://review.tizen.org/gerrit/273261/ Change-Id: I0e72acea7c54565aef4eeb76194e73e8320b3d94 Signed-off-by: Ayush Kumar --- tizen_src/ewk/efl_integration/BUILD.gn | 2 + .../browser/favicon/favicon_commands.cc | 70 +++++++++++++++------- .../browser/favicon/favicon_commands.h | 30 +--------- .../browser/favicon/favicon_database.cc | 23 ++++--- .../browser/favicon/favicon_database_p.cc | 30 +++++----- .../browser/favicon/favicon_database_p.h | 8 ++- .../efl_integration/common/skia_bitmap_utils.cc | 23 +++++++ .../ewk/efl_integration/common/skia_bitmap_utils.h | 16 +++++ tizen_src/ewk/efl_integration/eweb_context.cc | 9 +-- .../private/ewk_notification_private.cc | 9 +-- .../ewk/efl_integration/public/ewk_context.cc | 4 +- .../efl_integration/web_contents_delegate_efl.cc | 49 +++++++-------- 12 files changed, 149 insertions(+), 124 deletions(-) create mode 100644 tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc create mode 100644 tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index 8965db0..c04d0c6 100755 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -353,6 +353,8 @@ shared_library("chromium-ewk") { "common/print_pages_params.cc", "common/print_pages_params.h", "common/render_messages_ewk.h", + "common/skia_bitmap_utils.cc", + "common/skia_bitmap_utils.h", "common/version_info.cc", "common/version_info.h", "common/version_info_efl.h", diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc index a636ca4..29cee94 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.cc @@ -3,9 +3,13 @@ // found in the LICENSE file. #include "browser/favicon/favicon_commands.h" -#include "browser/favicon/favicon_database_p.h" -#include "third_party/sqlite/sqlite3.h" + #include +#include + +#include "browser/favicon/favicon_database_p.h" +#include "common/skia_bitmap_utils.h" +#include "url/gurl.h" #define CHECK_RESULT(qry, var, res, st, ret) if (var != res) {\ sqlite3_finalize(st);\ @@ -28,21 +32,31 @@ return ret;\ } +namespace { -std::string Command::lastError() const { - return std::string("[") + m_name + "] :: " + m_lastError; -} +struct SerializedBitmap { + SerializedBitmap() : data(0), size(0) {} + ~SerializedBitmap() { free(); } -std::string Command::name() const { - return m_name; -} + void alloc(size_t n) { + data = ::operator new(n); + size = n; + } -void Command::setError(const std::string &err) { - m_lastError = err; -} + void free() { + if (data) { + ::operator delete(data); + data = nullptr; + size = 0; + } + } -scoped_refptr Command::serialize(const SkBitmap &bitmap) { - scoped_refptr res(new SerializedBitmap); + void* data; + size_t size; +}; + +std::unique_ptr serialize(const SkBitmap& bitmap) { + std::unique_ptr res(new SerializedBitmap); if (bitmap.isNull()) { return res; } @@ -51,15 +65,14 @@ scoped_refptr Command::serialize(const SkBitmap &bitmap) { static_cast(res->data)[1] = static_cast(bitmap.alphaType()); static_cast(res->data)[2] = bitmap.width(); static_cast(res->data)[3] = bitmap.height(); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - if (!bitmap.copyPixelsTo(static_cast(res->data) + 4, bitmap.getSize())) { + if (!skia_bitmap_utils::CopyPixels(static_cast(res->data) + 4, + bitmap.getPixels(), bitmap.info())) { res->free(); } -#endif return res; } -SkBitmap Command::deserialize(const void *data) { +SkBitmap deserialize(const void* data) { if (!data) { return SkBitmap(); } @@ -77,12 +90,25 @@ SkBitmap Command::deserialize(const void *data) { // the deserialized SkBitmap owns and holds it's internal image data // for it's whole lifetime, we create a deep copy of the |bitmap|. SkBitmap copy; -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - bitmap.copyTo(©, colorType); -#endif + if (copy.tryAllocPixels(bitmap.info())) + bitmap.readPixels(copy.info(), copy.getPixels(), copy.rowBytes(), 0, 0); return copy; } +} // namespace + +std::string Command::lastError() const { + return std::string("[") + m_name + "] :: " + m_lastError; +} + +std::string Command::name() const { + return m_name; +} + +void Command::setError(const std::string& err) { + m_lastError = err; +} + const char *Command::sqlite3ErrStr(int rc) { static const char* const aMsg[] = { /* SQLITE_OK */ "not an error", @@ -322,7 +348,7 @@ bool InsertBitmapCommand::sqlExecute() { result = sqlite3_bind_text(stmt, 1, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC); CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false); - scoped_refptr serializedBitmap = serialize(m_bitmap); + std::unique_ptr serializedBitmap = serialize(m_bitmap); if (!serializedBitmap->data) { sqlite3_finalize(stmt); sqlite3_free(query); @@ -363,7 +389,7 @@ bool UpdateBitmapCommand::sqlExecute() { int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0); CHECK_PREP_MSG(query, result, SQLITE_OK, false); - scoped_refptr serializedBitmap = serialize(m_bitmap); + std::unique_ptr serializedBitmap = serialize(m_bitmap); if (!serializedBitmap->data) { sqlite3_finalize(stmt); return false; diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h index b6c5bfd..509c859 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_commands.h @@ -5,36 +5,12 @@ #ifndef FAVICON_COMMANDS_H #define FAVICON_COMMANDS_H -#include "url/gurl.h" -#include "base/memory/ref_counted.h" +#include #include "third_party/skia/include/core/SkBitmap.h" +class GURL; class FaviconDatabasePrivate; -struct SerializedBitmap : public base::RefCounted { - SerializedBitmap() : data(0), size(0) {} - ~SerializedBitmap() { - free(); - } - - void alloc(size_t n) { - free(); - data = ::operator new(n); - size = n; - } - - void free() { - if (data) { - ::operator delete(data); - data = 0; - size = 0; - } - } - - void *data; - size_t size; -}; - class Command { public: Command(const std::string &cmdName, FaviconDatabasePrivate *db) @@ -47,8 +23,6 @@ class Command { std::string name() const; protected: - static scoped_refptr serialize(const SkBitmap &bitmap); - static SkBitmap deserialize(const void *data); static const char *sqlite3ErrStr(int rc); FaviconDatabasePrivate *db() const { diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc index 3e52dbf..e35d7c8 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database.cc @@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/task/bind_post_task.h" #include "base/task/thread_pool.h" -#include "content/public/browser/browser_task_traits.h" #include "favicon_commands.h" #include "favicon_database_p.h" @@ -201,6 +200,14 @@ bool FaviconDatabase::Open() { } g_sqlite3_initialized = true; } + + if (d->path.empty()) + return false; + + base::FilePath dir = d->path.DirName(); + if (!base::DirectoryExists(dir) && !base::CreateDirectory(dir)) + return false; + result_code = sqlite3_open(d->path.value().c_str(), &d->sqlite); if (result_code != SQLITE_OK) { LOG(ERROR) << "[FaviconDatabase] :: Error opening SQLite database (" @@ -225,17 +232,9 @@ void FaviconDatabase::Close() { } void FaviconDatabase::SyncSQLite() { -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - scoped_refptr ptr = - content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::DB); -#else - scoped_refptr ptr = - base::ThreadPool::CreateSingleThreadTaskRunner( - {content::BrowserThread::UI}); -#endif - ptr->PostTask(FROM_HERE, base::BindOnce(&FaviconDatabasePrivate::performSync, - d->weakPtrFactory.GetWeakPtr())); + d->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&FaviconDatabasePrivate::performSync, + d->weakPtrFactory.GetWeakPtr())); } void FaviconDatabase::ScheduleSync() { diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc index 55d72c5..3c7faf1 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.cc @@ -3,10 +3,14 @@ // found in the LICENSE file. #include "favicon_database_p.h" + #include + +#include "base/logging.h" +#include "base/path_service.h" #include "base/task/bind_post_task.h" #include "base/task/thread_pool.h" -#include "content/public/browser/browser_task_traits.h" +#include "content/common/paths_efl.h" #include "favicon_commands.h" const char * const FaviconDatabasePrivate::pageUrlToFaviconUrlTable = "url_to_favicon_url"; @@ -18,11 +22,17 @@ const char * const FaviconDatabasePrivate::defaultDirSuffix = ".config/chromium- const char * const FaviconDatabasePrivate::defaultFilename = "WebpageIcons.db"; FaviconDatabasePrivate::FaviconDatabasePrivate() - : path(ewk_home_directory_get()), + : task_runner_(base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), privateBrowsing(false), sqlite(0), weakPtrFactory(this) { - path.Append(defaultDirSuffix).Append(defaultFilename); + base::FilePath db_path; + if (base::PathService::Get(PathsEfl::WEB_DATABASE_DIR, &db_path)) + path = db_path.Append(FILE_PATH_LITERAL(defaultFilename)); + else + LOG(ERROR) << "[favicon] Could not get web database directory"; } GURL FaviconDatabasePrivate::faviconUrlForPageUrl(const GURL &pageUrl) const { @@ -47,24 +57,14 @@ bool FaviconDatabasePrivate::existsForFaviconURL(const GURL &faviconUrl) const { return it != faviconUrlToBitmap.end(); } -scoped_refptr FaviconDatabasePrivate::taskRunner() const { -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - return content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::DB); -#else - return base::ThreadPool::CreateSingleThreadTaskRunner( - {content::BrowserThread::UI}); -#endif -} - void FaviconDatabasePrivate::performSync() { - std::cerr << "[FaviconDatabasePrivate::performSync()]" << std::endl; base::AutoLock locker(mutex); timer.Stop(); while (!commands.empty()) { Command *cmd = commands.front(); if (!cmd->sqlExecute()) { - std::cerr << "[FaviconDatabasePrivate::performSync] :: " << "Error while executing command:\n\t" << cmd->lastError() << std::endl; + LOG(ERROR) << "[FaviconDatabasePrivate::performSync] :: " + << "Error while executing command: " << cmd->lastError(); // abort or what? } commands.pop(); diff --git a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h index a9dd774..01c2de4 100644 --- a/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h +++ b/tizen_src/ewk/efl_integration/browser/favicon/favicon_database_p.h @@ -10,7 +10,7 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" -#include "base/task/single_thread_task_runner.h" +#include "base/task/sequenced_task_runner.h" #include "base/timer/timer.h" #include "content/public/browser/browser_thread.h" #include "favicon_database.h" @@ -29,12 +29,16 @@ struct FaviconDatabasePrivate : public base::RefCountedThreadSafe taskRunner() const; + scoped_refptr task_runner() const { + return task_runner_; + } + void performSync(); std::map pageToFaviconUrl; std::map faviconUrlToBitmap; base::FilePath path; + scoped_refptr task_runner_; bool privateBrowsing; sqlite3 *sqlite; diff --git a/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc new file mode 100644 index 0000000..11b33bf --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.cc @@ -0,0 +1,23 @@ +// Copyright 2018 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "skia_bitmap_utils.h" + +namespace skia_bitmap_utils { + +bool CopyPixels(void* dst_addr, const void* src_addr, const SkImageInfo& info) { + if (!dst_addr || !src_addr) + return false; + + size_t row_bytes = info.bytesPerPixel() * info.width(); + for (int y = 0; y < info.height(); ++y) { + memcpy(dst_addr, src_addr, row_bytes); + src_addr = static_cast(src_addr) + row_bytes; + dst_addr = static_cast(dst_addr) + row_bytes; + } + + return true; +} + +} // namespace skia_bitmap_utils diff --git a/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h new file mode 100644 index 0000000..08bd3fb --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/skia_bitmap_utils.h @@ -0,0 +1,16 @@ +// Copyright 2018 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_SKIA_BITMAP_UTILS_H +#define TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_SKIA_BITMAP_UTILS_H + +#include "third_party/skia/include/core/SkBitmap.h" + +namespace skia_bitmap_utils { + +bool CopyPixels(void* dst_addr, const void* src_addr, const SkImageInfo& info); + +} // namespace skia_bitmap_utils + +#endif // TIZEN_SRC_EWK_EFL_INTEGRATION_COMMON_SKIA_BITMAP_UTILS_H diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index fca6eeb..8951e30 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -717,14 +717,7 @@ Evas_Object* EWebContext::AddFaviconObject(const char* uri, evas_object_image_fill_set(favicon, 0, 0, bitmap.width(), bitmap.height()); evas_object_image_filled_set(favicon, EINA_TRUE); evas_object_image_alpha_set(favicon, EINA_TRUE); - -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - void* pixels = evas_object_image_data_get(favicon, EINA_TRUE); - if (pixels) { - bitmap.copyPixelsTo(pixels, bitmap.getSize()); - evas_object_image_data_set(favicon, pixels); - } -#endif + evas_object_image_data_copy_set(favicon, bitmap.getPixels()); return favicon; } diff --git a/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc b/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc index 1378ac6..cf3aec0 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_notification_private.cc @@ -46,14 +46,7 @@ Evas_Object* Ewk_Notification::GetIcon(Evas* evas) const { evas_object_image_size_set(icon, icon_.width(), icon_.height()); evas_object_image_colorspace_set(icon, EVAS_COLORSPACE_ARGB8888); evas_object_image_alpha_set(icon, EINA_TRUE); - void* pixels = evas_object_image_data_get(icon, EINA_TRUE); - -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - if (pixels) { - icon_.copyPixelsTo(pixels, icon_.getSize()); - evas_object_image_data_set(icon, pixels); - } -#endif + evas_object_image_data_copy_set(icon, icon_.getPixels()); return icon; } diff --git a/tizen_src/ewk/efl_integration/public/ewk_context.cc b/tizen_src/ewk/efl_integration/public/ewk_context.cc index 8fa3ea0..3e3d06f 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_context.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_context.cc @@ -627,8 +627,8 @@ Eina_Bool ewk_context_favicon_database_directory_set(Ewk_Context* ewkContext, co EINA_SAFETY_ON_NULL_RETURN_VAL(ewkContext, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(directoryPath, EINA_FALSE); base::FilePath path(directoryPath); - path.Append(FaviconDatabasePrivate::defaultFilename); - return ewkContext->SetFaviconDatabasePath(path) ? EINA_TRUE : EINA_FALSE; + path = path.Append(FaviconDatabasePrivate::defaultFilename); + return ewkContext->SetFaviconDatabasePath(path); } void ewk_context_preferred_languages_set(Eina_List* languages) diff --git a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc index 097edfe..2d6149d 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -401,31 +401,6 @@ void WebContentsDelegateEfl::DidFinishLoad(RenderFrameHost* render_frame_host, return; web_view_->SmartCallback().call(); - NavigationEntry* entry = web_contents().GetController().GetVisibleEntry(); - if (!entry) - return; - - FaviconStatus& favicon = entry->GetFavicon(); - - if (favicon.valid) { - // check/update the url and favicon url in favicon database - FaviconDatabase::Instance()->SetFaviconURLForPageURL(favicon.url, - validated_url); - - // download favicon if there is no such in database - if (!FaviconDatabase::Instance()->ExistsForFaviconURL(favicon.url)) { - LOG(ERROR) << "[DidFinishLoad] :: no favicon in database for URL: " - << favicon.url.spec(); - favicon_downloader_.reset(new FaviconDownloader( - &web_contents_, favicon.url, - base::BindOnce(&WebContentsDelegateEfl::DidDownloadFavicon, - weak_ptr_factory_.GetWeakPtr()))); - favicon_downloader_->Start(); - } else { - web_view_->SmartCallback().call(); - } - } - web_contents_.Focus(); } @@ -444,13 +419,33 @@ void WebContentsDelegateEfl::DidUpdateFaviconURL( const std::vector& candidates) { // select and set proper favicon for (const auto& favicon : candidates) { - if (favicon->icon_type == blink::mojom::FaviconIconType::kFavicon && - !favicon->icon_url.is_valid()) { + if (!favicon->icon_url.is_valid()) + continue; + + if (favicon->icon_type == blink::mojom::FaviconIconType::kFavicon) { NavigationEntry* entry = web_contents_.GetController().GetVisibleEntry(); if (!entry) return; entry->GetFavicon().url = favicon->icon_url; entry->GetFavicon().valid = true; + + // check/update the url and favicon url in favicon database + FaviconDatabase::Instance()->SetFaviconURLForPageURL(favicon->icon_url, + entry->GetURL()); + + // download favicon if there is no such in database + if (!FaviconDatabase::Instance()->ExistsForFaviconURL( + favicon->icon_url)) { + LOG(INFO) << "No favicon in database for URL: " + << favicon->icon_url.spec(); + favicon_downloader_.reset(new FaviconDownloader( + &web_contents_, favicon->icon_url, + base::BindOnce(&WebContentsDelegateEfl::DidDownloadFavicon, + weak_ptr_factory_.GetWeakPtr()))); + favicon_downloader_->Start(); + } else { + web_view_->SmartCallback().call(); + } return; } } -- 2.7.4 From 3e70c4ff2e01bf9f0112e83c79fdbdfdd9a9bd50 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Mon, 23 Jan 2023 11:09:52 +0530 Subject: [PATCH 02/16] [M108 Migration] Enable proper functionality for ewk_view_text_selection_clear API This patch enables proper functionality of ewk_view_text_selection_clear api. Reference: https://review.tizen.org/gerrit/c/274274/ Change-Id: Idbcdc8e50fbde018aefb3ca576597508a3978a97 Signed-off-by: Ayush Kumar --- .../browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc | 8 ++++++++ .../browser/renderer_host/rwhv_aura_offscreen_helper_efl.h | 5 +++++ tizen_src/ewk/efl_integration/eweb_view.cc | 11 ++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc index 30492b0..edf0ed4 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc @@ -602,6 +602,14 @@ void RWHVAuraOffscreenHelperEfl::SelectionChanged(const std::u16string& text, const gfx::Range& range) { if (range.start() == range.end() && GetIMContextEfl()) GetIMContextEfl()->SetCaretPosition(range.start()); + + if (!GetSelectionController()) + return; + + std::u16string selectedText; + if (!text.empty() && !range.is_empty()) + selectedText = rwhv_aura_->GetSelectedText(); + GetSelectionController()->UpdateSelectionData(selectedText); } void RWHVAuraOffscreenHelperEfl::EvasToBlinkCords(int x, diff --git a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h index a4264d1..1f24974 100644 --- a/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h +++ b/tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h @@ -19,6 +19,7 @@ #include "base/callback.h" #include "base/containers/id_map.h" #include "base/timer/timer.h" +#include "content/browser/selection/selection_controller_efl.h" #include "content/common/cursors/webcursor.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "ui/base/ime/mojom/text_input_state.mojom-forward.h" @@ -103,6 +104,9 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { void SelectionChanged(const std::u16string& text, size_t offset, const gfx::Range& range); + SelectionControllerEfl* GetSelectionController() const { + return selection_controller_.get(); + } void EvasToBlinkCords(int x, int y, int* view_x, int* view_y); Evas_Object* ewk_view() const; @@ -180,6 +184,7 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl { ui::IMContextEfl* im_context_efl_ = nullptr; RenderWidgetHostViewAura* rwhv_aura_ = nullptr; WebContents* web_contents_ = nullptr; + std::unique_ptr selection_controller_; std::unique_ptr rwh_helper_; diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index fcad346..015f775 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -1366,14 +1366,10 @@ void EWebView::OnQuerySelectionStyleReply(const SelectionStylePrams& params) { } SelectionControllerEfl* EWebView::GetSelectionController() const { -#if !defined(USE_AURA) RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); - RenderWidgetHostViewEfl* view = static_cast( + RenderWidgetHostViewAura* view = static_cast( render_view_host->GetWidget()->GetView()); - return view ? view->GetSelectionController() : 0; -#else - return nullptr; -#endif + return view ? view->offscreen_helper()->GetSelectionController() : 0; } void EWebView::SelectLinkText(const gfx::Point& touch_point) { @@ -1407,7 +1403,8 @@ Eina_Bool EWebView::ClearSelection() { return EINA_FALSE; ResetContextMenuController(); - rwhva()->SelectionChanged(std::u16string(), 0, gfx::Range()); + rwhva()->offscreen_helper()->SelectionChanged(std::u16string(), 0, + gfx::Range()); if (GetSelectionController()) return GetSelectionController()->ClearSelectionViaEWebView(); -- 2.7.4 From 831fe49d8a7ee0a975936d22ac73f3550c454e65 Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Sun, 22 Jan 2023 23:24:02 +0530 Subject: [PATCH 03/16] [M108 Migration] Implement ewk_settings_use_system_font_set API Added needed to support to control the font setting for browser. Reference: https://review.tizen.org/gerrit/c/277844 Change-Id: I051d586183dadfa928f97415dfb246e4b32b361a Signed-off-by: Bakka Uday Kiran --- third_party/blink/renderer/platform/fonts/font_cache.h | 9 +++++++++ .../blink/renderer/platform/fonts/skia/font_cache_skia.cc | 11 +++++++++++ tizen_src/ewk/efl_integration/eweb_view.cc | 12 +++++++++--- tizen_src/ewk/efl_integration/public/ewk_settings.cc | 13 +++++++++++-- 4 files changed, 40 insertions(+), 5 deletions(-) mode change 100644 => 100755 third_party/blink/renderer/platform/fonts/font_cache.h diff --git a/third_party/blink/renderer/platform/fonts/font_cache.h b/third_party/blink/renderer/platform/fonts/font_cache.h old mode 100644 new mode 100755 index af9f3af..1d64d43 --- a/third_party/blink/renderer/platform/fonts/font_cache.h +++ b/third_party/blink/renderer/platform/fonts/font_cache.h @@ -290,6 +290,11 @@ class PLATFORM_EXPORT FontCache final { FontCache& operator=(const FontCache&) = delete; ~FontCache(); +#if BUILDFLAG(IS_EFL) + void SetFontFamilyTizenBrowser() { tizen_browser_font_family = true; } + bool IsFontFamilyTizenBrowser() const { return tizen_browser_font_family; } +#endif + private: // BCP47 list used when requesting fallback font for a character. // inlineCapacity is set to 4: the array vector not need to hold more than 4 @@ -404,6 +409,10 @@ class PLATFORM_EXPORT FontCache final { void PurgePlatformFontDataCache(); void PurgeFallbackListShaperCache(); +#if BUILDFLAG(IS_EFL) + bool tizen_browser_font_family = false; +#endif + friend class SimpleFontData; // For fontDataFromFontPlatformData friend class FontFallbackList; friend class FontPlatformDataCache; diff --git a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc index 9a458ca..3bcff7b 100644 --- a/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc +++ b/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc @@ -53,6 +53,9 @@ #include "third_party/skia/include/core/SkFontMgr.h" #include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/core/SkTypeface.h" +#if BUILDFLAG(IS_TIZEN) +#include "tizen_src/chromium_impl/tizen/system_info.h" +#endif namespace blink { @@ -226,6 +229,14 @@ sk_sp FontCache::CreateTypeface( } #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_TIZEN) + if (IsMobileProfile() && Get().IsFontFamilyTizenBrowser()) + name = "SamsungOneUI"; + else if (!name.length() || (DeprecatedEqualIgnoringCase( + String(name.data()), "standardFontFamily"))) + name = "Tizen"; +#endif + #if BUILDFLAG(IS_WIN) // TODO(vmpstr): Deal with paint typeface here. if (sideloaded_fonts_) { diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 015f775..a9f9686 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -2057,9 +2057,15 @@ bool EWebView::RestoreFromSessionData(const char* data, unsigned length) { void EWebView::SetBrowserFont() { #if !defined(EWK_BRINGUP) // FIXME: m94 bringup RenderViewHost* render_view_host = web_contents_->GetRenderViewHost(); - if (render_view_host) - render_view_host->Send( - new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID())); + if (render_view_host) { + IPC::Message* message = + new EwkViewMsg_SetBrowserFont(render_view_host->GetRoutingID()); + + if (render_view_host->IsRenderViewLive()) + render_view_host->Send(message); + else + delayed_messages_.push_back(message); + } #endif } diff --git a/tizen_src/ewk/efl_integration/public/ewk_settings.cc b/tizen_src/ewk/efl_integration/public/ewk_settings.cc index 8ce40cd..1a8b3e8 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_settings.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_settings.cc @@ -865,8 +865,17 @@ Eina_Bool ewk_settings_legacy_font_size_enabled_get(Ewk_Settings* settings) Eina_Bool ewk_settings_use_system_font_set(Ewk_Settings* settings, Eina_Bool use) { - LOG_EWK_API_MOCKUP(); - return false; + if (IsMobileProfile()) { + EWebView* impl = EWebView::FromEvasObject(settings->getEvasObject()); + if (impl) { + if (use) + impl->UseSettingsFont(); + else + impl->SetBrowserFont(); + return EINA_TRUE; + } + } + return EINA_FALSE; } Eina_Bool ewk_settings_use_system_font_get(Ewk_Settings* settings) -- 2.7.4 From 9fd673f36281ac23d6a0122c19ce7ad37606f82f Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Tue, 17 Jan 2023 13:53:20 +0530 Subject: [PATCH 04/16] [M108 Migration] Patch migration for BrowsingDataRemoverEfl This patch -Migrates Session storage related changes from M94. -Fixes build error caused by accessing StoragePartition -Migrates the below patch for BrowsingDataRemoverEfl. -Removes EWK_BRINGUP caused by M94 upversion by changing to use QuotaManager instead of AppCacheService References: https://review.tizen.org/gerrit/c/273503 https://review.tizen.org/gerrit/c/283349 Change-Id: Ibaa832abd99f41f2bbb1f6ec98fe26dab4ba3fc7 Signed-off-by: Bakka Uday Kiran --- .../browser/browsing_data_remover_efl.cc | 340 ++++++--------------- .../browser/browsing_data_remover_efl.h | 116 ++++--- tizen_src/ewk/efl_integration/eweb_context.cc | 9 +- 3 files changed, 146 insertions(+), 319 deletions(-) diff --git a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc index 5f14fec..17b2a62 100644 --- a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.cc @@ -18,39 +18,39 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/session_storage_usage_info.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_usage_info.h" -#include "net/base/completion_repeating_callback.h" -#include "net/base/net_errors.h" -#include "net/disk_cache/disk_cache.h" -#include "net/http/http_cache.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" #include "storage/browser/quota/quota_manager.h" using content::BrowserThread; -// Static. -BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForUnboundedRange(content::BrowserContext* profile) { - return new BrowsingDataRemoverEfl(profile, base::Time(), base::Time::Max()); +// static +BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForUnboundedRange( + content::BrowserContext* browser_context) { + return new BrowsingDataRemoverEfl(browser_context, base::Time(), + base::Time::Max()); } -BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForRange(content::BrowserContext* browser_context, - base::Time start, base::Time end) { +// static +BrowsingDataRemoverEfl* BrowsingDataRemoverEfl::CreateForRange( + content::BrowserContext* browser_context, + base::Time start, + base::Time end) { return new BrowsingDataRemoverEfl(browser_context, start, end); } -int BrowsingDataRemoverEfl::GenerateQuotaClientMask(int remove_mask) { - int quota_client_mask = 0; -#if !defined(EWK_BRINGUP) // FIXME: m85 bringup +// static +storage::QuotaClientTypes BrowsingDataRemoverEfl::GenerateQuotaClientTypes( + int remove_mask) { + storage::QuotaClientTypes quota_client_types; if (remove_mask & BrowsingDataRemoverEfl::REMOVE_FILE_SYSTEMS) - quota_client_mask |= storage::QuotaClient::kFileSystem; + quota_client_types.insert(storage::QuotaClientType::kFileSystem); if (remove_mask & BrowsingDataRemoverEfl::REMOVE_WEBSQL) - quota_client_mask |= storage::QuotaClient::kDatabase; + quota_client_types.insert(storage::QuotaClientType::kDatabase); if (remove_mask & BrowsingDataRemoverEfl::REMOVE_INDEXEDDB) - quota_client_mask |= storage::QuotaClient::kIndexedDatabase; -#endif - return quota_client_mask; + quota_client_types.insert(storage::QuotaClientType::kIndexedDatabase); + return quota_client_types; } BrowsingDataRemoverEfl::BrowsingDataRemoverEfl( @@ -58,144 +58,22 @@ BrowsingDataRemoverEfl::BrowsingDataRemoverEfl( base::Time delete_begin, base::Time delete_end) : browser_context_(browser_context), - app_cache_service_(nullptr), - quota_manager_(nullptr), - dom_storage_context_(nullptr), delete_begin_(delete_begin), - delete_end_(delete_end), - next_cache_state_(STATE_NONE), - cache_(nullptr), - main_context_getter_(nullptr), - media_context_getter_(nullptr), - waiting_for_clear_cache_(false), - waiting_for_clear_local_storage_(false), - waiting_for_clear_quota_managed_data_(false), - quota_managed_origins_to_delete_count_(0), - quota_managed_storage_types_to_delete_count_(0), - remove_mask_(0) { -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - if (browser_context_) { - app_cache_service_ = browser_context->GetStoragePartition(browser_context_, NULL)->GetAppCacheService(); - main_context_getter_ = - content::BrowserContext::GetDefaultStoragePartition(browser_context_)->GetURLRequestContext(); - media_context_getter_ = browser_context->CreateMediaRequestContext(); - } -#endif -} + delete_end_(delete_end) {} BrowsingDataRemoverEfl::~BrowsingDataRemoverEfl() { DCHECK(AllDone()); } void BrowsingDataRemoverEfl::ClearNetworkCache() { - waiting_for_clear_cache_ = true; DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&BrowsingDataRemoverEfl::ClearNetworkCacheOnIOThread, - base::Unretained(this))); -} - -void BrowsingDataRemoverEfl::ClearNetworkCacheOnIOThread() { - // This function should be called on the IO thread. - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - DCHECK_EQ(STATE_NONE, next_cache_state_); - DCHECK(main_context_getter_.get()); - DCHECK(media_context_getter_.get()); - - next_cache_state_ = STATE_CREATE_MAIN; - DoClearCache(net::OK); -} - -// The expected state sequence is STATE_NONE --> STATE_CREATE_MAIN --> -// STATE_DELETE_MAIN --> STATE_CREATE_MEDIA --> STATE_DELETE_MEDIA --> -// STATE_DONE, and any errors are ignored. -void BrowsingDataRemoverEfl::DoClearCache(int rv) { - DCHECK_NE(STATE_NONE, next_cache_state_); - - while (rv != net::ERR_IO_PENDING && next_cache_state_ != STATE_NONE) { - switch (next_cache_state_) { - case STATE_CREATE_MAIN: - case STATE_CREATE_MEDIA: { - // Get a pointer to the cache. - net::URLRequestContextGetter* getter = nullptr; - if (next_cache_state_ == STATE_CREATE_MAIN) { - if (main_context_getter_) - getter = main_context_getter_.get(); - } else { - if (media_context_getter_) - getter = media_context_getter_.get(); - } - if (getter && getter->GetURLRequestContext()) { - net::HttpTransactionFactory* factory = - getter->GetURLRequestContext()->http_transaction_factory(); - if (factory) { - next_cache_state_ = (next_cache_state_ == STATE_CREATE_MAIN) - ? STATE_DELETE_MAIN - : STATE_DELETE_MEDIA; - rv = factory->GetCache()->GetBackend( - &cache_, base::BindOnce(&BrowsingDataRemoverEfl::DoClearCache, - base::Unretained(this))); - } else { - LOG(ERROR) << "Could not get HttpTransactionFactory."; - next_cache_state_ = STATE_NONE; - } - } else { - LOG(ERROR) << "Could not get URLRequestContext."; - next_cache_state_ = STATE_NONE; - } - break; - } - case STATE_DELETE_MAIN: - case STATE_DELETE_MEDIA: { - next_cache_state_ = (next_cache_state_ == STATE_DELETE_MAIN) ? - STATE_CREATE_MEDIA : STATE_DONE; - - // |cache_| can be null if it cannot be initialized. - if (cache_) { - if (delete_begin_.is_null()) { - rv = cache_->DoomAllEntries(base::BindOnce( - &BrowsingDataRemoverEfl::DoClearCache, base::Unretained(this))); - } else { - rv = cache_->DoomEntriesBetween( - delete_begin_, delete_end_, - base::BindOnce(&BrowsingDataRemoverEfl::DoClearCache, - base::Unretained(this))); - } - cache_ = NULL; - } - break; - } - case STATE_DONE: { - cache_ = NULL; - next_cache_state_ = STATE_NONE; - - // Notify the UI thread that we are done. - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&BrowsingDataRemoverEfl::ClearedCache, - base::Unretained(this))); - return; - } - default: { - NOTREACHED() << "bad state"; - next_cache_state_ = STATE_NONE; // Stop looping. - return; - } - } - } -} - -void BrowsingDataRemoverEfl::ClearedCache() { - waiting_for_clear_cache_ = false; DeleteIfDone(); } // just to keep same overall structure of Chrome::BrowsingDataRemover bool BrowsingDataRemoverEfl::AllDone() { - return !waiting_for_clear_cache_ && - !waiting_for_clear_local_storage_ && + return !waiting_for_clear_local_storage_ && + !waiting_for_clear_session_storage_ && !waiting_for_clear_quota_managed_data_; } @@ -207,90 +85,42 @@ void BrowsingDataRemoverEfl::DeleteIfDone() { base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); } -typedef void (*Application_Cache_Origins_Get_Callback)(void* origins, void* user_data); -#if !defined(EWK_BRINGUP) // FIXME: m108 bringup -void OnGotOriginsWithApplicationCache(Application_Cache_Origins_Get_Callback callback, - void* user_data, - scoped_refptr collection, - int result){ - BrowsingDataRemoverEfl* bdre = - static_cast(user_data); - // information about end of process is not needed so cb left empty - net::CompletionRepeatingCallback cb; - if (collection.get()) { - for (const auto& origin : collection->infos_by_origin) - bdre->DeleteAppCachesForOrigin(origin.first); - } -} -#endif void BrowsingDataRemoverEfl::RemoveImpl(int remove_mask, const GURL& origin) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); remove_mask_ = remove_mask; - remove_origin_ = origin; + remove_origin_ = url::Origin::Create(origin); if (remove_mask & REMOVE_LOCAL_STORAGE) { waiting_for_clear_local_storage_ = true; -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup if (!dom_storage_context_) { - dom_storage_context_ = content::BrowserContext::GetStoragePartition(browser_context_, NULL)->GetDOMStorageContext(); + dom_storage_context_ = + browser_context_->GetStoragePartition(NULL)->GetDOMStorageContext(); } -#endif ClearLocalStorageOnUIThread(); } + if (remove_mask & REMOVE_SESSION_STORAGE) { + waiting_for_clear_session_storage_ = true; + if (!dom_storage_context_) { + dom_storage_context_ = + browser_context_->GetStoragePartition(NULL)->GetDOMStorageContext(); + } + ClearSessionStorageOnUIThread(); + } + if (remove_mask & REMOVE_INDEXEDDB || remove_mask & REMOVE_WEBSQL || - remove_mask & REMOVE_FILE_SYSTEMS) { -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup + remove_mask & REMOVE_FILE_SYSTEMS || remove_mask & REMOVE_APPCACHE) { if (!quota_manager_) { - quota_manager_ = content::BrowserContext::GetStoragePartition(browser_context_, NULL)->GetQuotaManager(); + quota_manager_ = + browser_context_->GetStoragePartition(NULL)->GetQuotaManager(); } -#endif waiting_for_clear_quota_managed_data_ = true; base::ThreadPool::PostTask( FROM_HERE, {BrowserThread::IO}, base::BindOnce(&BrowsingDataRemoverEfl::ClearQuotaManagedDataOnIOThread, base::Unretained(this))); } - if (remove_mask & REMOVE_APPCACHE) { - DCHECK(app_cache_service_); - if (!app_cache_service_) { - return; - } - - if (origin.is_valid()) { - DeleteAppCachesForOrigin(url::Origin::Create(origin)); - } - else { -#if !defined(EWK_BRINGUP) // FIXME: m108 bringup - //if origin is empty delete all app cache (actual deletion in OnGotOriginsWithApplicationCache) - Application_Cache_Origins_Get_Callback cb = NULL; - scoped_refptr collection(new content::AppCacheInfoCollection()); - app_cache_service_->GetAllAppCacheInfo( - collection.get(), base::BindOnce(&OnGotOriginsWithApplicationCache, - cb, this, collection)); -#endif - } - } -} - -void BrowsingDataRemoverEfl::DeleteAppCachesForOrigin( - const url::Origin& origin) { - if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { - // TODO: Using base::Unretained is not thread safe - // It may happen that on IO thread this ptr will be already deleted - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&BrowsingDataRemoverEfl::DeleteAppCachesForOrigin, - base::Unretained(this), origin)); - return; - } - - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); -#if !defined(EWK_BRINGUP) // FIXME: m108 bringup - net::CompletionRepeatingCallback rm_app_catche_cb; - static_cast(app_cache_service_)->DeleteAppCachesForOrigin(origin, rm_app_catche_cb); -#endif } void BrowsingDataRemoverEfl::ClearLocalStorageOnUIThread() { @@ -316,78 +146,92 @@ void BrowsingDataRemoverEfl::OnGotLocalStorageUsageInfo( DeleteIfDone(); } +void BrowsingDataRemoverEfl::ClearSessionStorageOnUIThread() { + DCHECK(waiting_for_clear_session_storage_); + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + dom_storage_context_->GetSessionStorageUsage( + base::BindOnce(&BrowsingDataRemoverEfl::OnGotSessionStorageUsageInfo, + base::Unretained(this))); +} + +void BrowsingDataRemoverEfl::OnGotSessionStorageUsageInfo( + const std::vector& infos) { + DCHECK(waiting_for_clear_session_storage_); + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + for (size_t i = 0; i < infos.size(); ++i) + dom_storage_context_->DeleteSessionStorage(infos[i], base::DoNothing()); + waiting_for_clear_session_storage_ = false; + DeleteIfDone(); +} + void BrowsingDataRemoverEfl::ClearQuotaManagedDataOnIOThread() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup // Ask the QuotaManager for all origins with temporary quota modified within // the user-specified timeframe, and deal with the resulting set in // OnGotQuotaManagedOrigins(). quota_managed_origins_to_delete_count_ = 0; quota_managed_storage_types_to_delete_count_ = 0; - if (delete_begin_ == base::Time()) { - ++quota_managed_storage_types_to_delete_count_; - quota_manager_->GetOriginsModifiedSince( - storage::kStorageTypePersistent, delete_begin_, - base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins, - base::Unretained(this))); - } + if (delete_begin_.is_null()) + ClearQuotaManagedDataInternal(blink::mojom::StorageType::kPersistent); // Do the same for temporary quota. - ++quota_managed_storage_types_to_delete_count_; - quota_manager_->GetOriginsModifiedSince( - storage::kStorageTypeTemporary, delete_begin_, - base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins, - base::Unretained(this))); + ClearQuotaManagedDataInternal(blink::mojom::StorageType::kTemporary); // Do the same for syncable quota. + ClearQuotaManagedDataInternal(blink::mojom::StorageType::kSyncable); +} + +void BrowsingDataRemoverEfl::ClearQuotaManagedDataInternal( + blink::mojom::StorageType type) { ++quota_managed_storage_types_to_delete_count_; - quota_manager_->GetOriginsModifiedSince( - storage::kStorageTypeSyncable, delete_begin_, - base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins, + quota_manager_->GetBucketsModifiedBetween( + type, delete_begin_, delete_end_, + base::BindOnce(&BrowsingDataRemoverEfl::OnGotQuotaManagedBuckets, base::Unretained(this))); -#endif } -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup -void BrowsingDataRemoverEfl::OnGotQuotaManagedOrigins( - const std::set& origins, storage::StorageType type) { +void BrowsingDataRemoverEfl::OnGotQuotaManagedBuckets( + const std::set& buckets, + blink::mojom::StorageType type) { DCHECK_GT(quota_managed_storage_types_to_delete_count_, 0); - // Walk through the origins passed in, delete quota of |type| from each that - // matches the |origin_set_mask_|. - std::set::const_iterator origin; - for (origin = origins.begin(); origin != origins.end(); ++origin) { - if (!remove_origin_.is_empty()) { // delete all origins if remove_origin is empty - if (remove_origin_ != origin->GetOrigin()) - continue; - } + storage::QuotaClientTypes quota_client_types = + BrowsingDataRemoverEfl::GenerateQuotaClientTypes(remove_mask_); + + for (const auto& bucket : buckets) { + // delete all origins if |remove_origin_| is opaque. + if (!remove_origin_.opaque() && + remove_origin_ != bucket.storage_key.origin()) + continue; ++quota_managed_origins_to_delete_count_; - quota_manager_->DeleteOriginData( - origin->GetOrigin(), type, - BrowsingDataRemoverEfl::GenerateQuotaClientMask(remove_mask_), - base::BindOnce(&BrowsingDataRemoverEfl::OnQuotaManagedOriginDeletion, - base::Unretained(this), origin->GetOrigin(), type)); + quota_manager_->DeleteBucketData( + bucket, quota_client_types, + base::BindOnce(&BrowsingDataRemoverEfl::OnQuotaManagedBucketDeleted, + base::Unretained(this), bucket)); } --quota_managed_storage_types_to_delete_count_; CheckQuotaManagedDataDeletionStatus(); } -void BrowsingDataRemoverEfl::OnQuotaManagedOriginDeletion( - const GURL& origin, - storage::StorageType type, - storage::QuotaStatusCode status) { +void BrowsingDataRemoverEfl::OnQuotaManagedBucketDeleted( // LCOV_EXCL_LINE + const storage::BucketLocator& bucket, + blink::mojom::QuotaStatusCode status) { DCHECK_GT(quota_managed_origins_to_delete_count_, 0); - if (status != storage::kQuotaStatusOk) - DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin " - << origin << ". Status: " << status; + if (status != blink::mojom::QuotaStatusCode::kOk) { + DLOG(ERROR) << "Couldn't remove data type " << static_cast(bucket.type) + << " with storage key " << bucket.storage_key.GetDebugString() + << " and bucket id " << bucket.id + << ". Status: " << static_cast(status); + } --quota_managed_origins_to_delete_count_; CheckQuotaManagedDataDeletionStatus(); } -#endif void BrowsingDataRemoverEfl::CheckQuotaManagedDataDeletionStatus() { if (quota_managed_storage_types_to_delete_count_ != 0 || diff --git a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h index c30d2be..6c8885a 100644 --- a/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h +++ b/tizen_src/ewk/efl_integration/browser/browsing_data_remover_efl.h @@ -10,81 +10,89 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "storage/browser/quota/quota_client_type.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" #include "url/origin.h" -namespace net { -class URLRequestContextGetter; -} namespace content { -class AppCacheService; class BrowserContext; class DOMStorageContext; +struct SessionStorageUsageInfo; struct StorageUsageInfo; -class StoragePartition; -} -namespace disk_cache { -class Backend; -} +} // namespace content + namespace storage { class QuotaManager; +struct BucketLocator; } class BrowsingDataRemoverEfl { public: // Mask used for Remove. enum RemoveDataMask { - REMOVE_LOCAL_STORAGE = 1 << 0, - REMOVE_INDEXEDDB = 1 << 1, - REMOVE_WEBSQL = 1 << 2, - REMOVE_FILE_SYSTEMS = 1 << 3, - REMOVE_APPCACHE = 1 << 4, + REMOVE_LOCAL_STORAGE = 1 << 0, + REMOVE_INDEXEDDB = 1 << 1, + REMOVE_WEBSQL = 1 << 2, + REMOVE_FILE_SYSTEMS = 1 << 3, + REMOVE_APPCACHE = 1 << 4, + REMOVE_SESSION_STORAGE = 1 << 5, }; - static BrowsingDataRemoverEfl* CreateForUnboundedRange(content::BrowserContext*); - static BrowsingDataRemoverEfl* CreateForRange(content::BrowserContext*, base::Time, base::Time); - void RemoveImpl(int, const GURL&); + static BrowsingDataRemoverEfl* CreateForUnboundedRange( + content::BrowserContext* browser_context); + static BrowsingDataRemoverEfl* CreateForRange( + content::BrowserContext* browser_context, + base::Time start, + base::Time end); + void RemoveImpl(int remove_mask, const GURL& origin); virtual ~BrowsingDataRemoverEfl(); void ClearNetworkCache(); - // deletes app cache for given origin - void DeleteAppCachesForOrigin(const url::Origin& origin); + BrowsingDataRemoverEfl(const BrowsingDataRemoverEfl&) = delete; + BrowsingDataRemoverEfl& operator=(const BrowsingDataRemoverEfl&) = delete; protected: - BrowsingDataRemoverEfl(content::BrowserContext*, base::Time start, base::Time end); + BrowsingDataRemoverEfl(content::BrowserContext* browser_context, + base::Time start, + base::Time end); - // Quota managed data uses a different bitmask for types than - // BrowsingDataRemover uses. This method generates that mask. - static int GenerateQuotaClientMask(int); + // Quota managed data uses a different representation for storage types than + // BrowsingDataRemover uses. This method generates that representation. + static storage::QuotaClientTypes GenerateQuotaClientTypes(int remove_mask); private: - void ClearNetworkCacheOnIOThread(); - - // Callback when the cache has been cleared. - void DoClearCache(int); - // Invoked on the UI thread to delete local storage. void ClearLocalStorageOnUIThread(); // Callback to deal with the list gathered in ClearLocalStorageOnUIThread. void OnGotLocalStorageUsageInfo( - const std::vector&); + const std::vector& infos); + + // Invoked on the UI thread to delete session storage. + void ClearSessionStorageOnUIThread(); + + // Callback to deal with the list gathered in ClearSessionStorageOnUIThread. + void OnGotSessionStorageUsageInfo( + const std::vector& infos); // Invoked on the IO thread to delete all storage types managed by the quota // system: AppCache, Databases, FileSystems. void ClearQuotaManagedDataOnIOThread(); - // Callback to respond to QuotaManager::GetOriginsModifiedSince, which is the - // core of 'ClearQuotaManagedDataOnIOThread'. -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - void OnGotQuotaManagedOrigins(const std::set&, storage::StorageType); + void ClearQuotaManagedDataInternal(blink::mojom::StorageType type); + // Callback to respond to QuotaManager::GetBucketsModifiedBetween, + // which is the core of 'ClearQuotaManagedDataOnIOThread'. + void OnGotQuotaManagedBuckets(const std::set& buckets, + blink::mojom::StorageType type); // Callback responding to deletion of a single quota managed origin's // persistent data - void OnQuotaManagedOriginDeletion(const GURL&, storage::StorageType, storage::QuotaStatusCode); -#endif + void OnQuotaManagedBucketDeleted(const storage::BucketLocator& bucket, + blink::mojom::QuotaStatusCode status); // Called to check whether all temporary and persistent origin data that // should be deleted has been deleted. If everything's good to go, invokes // OnQuotaManagedDataDeleted on the UI thread. @@ -94,19 +102,17 @@ class BrowsingDataRemoverEfl { // deleted. Updates the waiting flag and invokes NotifyAndDeleteIfDone. void OnQuotaManagedDataDeleted(); - void ClearedCache(); bool AllDone(); void DeleteIfDone(); content::BrowserContext* browser_context_; - content::AppCacheService* app_cache_service_; // The QuotaManager is owned by the profile; we can use a raw pointer here, // and rely on the profile to destroy the object whenever it's reasonable. - storage::QuotaManager* quota_manager_; + storage::QuotaManager* quota_manager_ = nullptr; // The DOMStorageContext is owned by the profile; we'll store a raw pointer. - content::DOMStorageContext* dom_storage_context_; + content::DOMStorageContext* dom_storage_context_ = nullptr; // Start time to delete from. base::Time delete_begin_; @@ -114,37 +120,19 @@ class BrowsingDataRemoverEfl { // End time to delete to. base::Time delete_end_; - enum CacheState { - STATE_NONE, - STATE_CREATE_MAIN, - STATE_CREATE_MEDIA, - STATE_DELETE_MAIN, - STATE_DELETE_MEDIA, - STATE_DONE - }; - CacheState next_cache_state_; - disk_cache::Backend* cache_; - - content::NotificationRegistrar registrar_; - std::set renderers_; - - // Used to delete data from HTTP cache. - scoped_refptr main_context_getter_; - scoped_refptr media_context_getter_; - - bool waiting_for_clear_cache_; - bool waiting_for_clear_local_storage_; - bool waiting_for_clear_quota_managed_data_; + bool waiting_for_clear_local_storage_ = false; + bool waiting_for_clear_session_storage_ = false; + bool waiting_for_clear_quota_managed_data_ = false; // Tracking how many origins need to be deleted, and whether we're finished // gathering origins. - int quota_managed_origins_to_delete_count_; - int quota_managed_storage_types_to_delete_count_; + int quota_managed_origins_to_delete_count_ = 0; + int quota_managed_storage_types_to_delete_count_ = 0; // The removal mask for the current removal operation. - int remove_mask_; + int remove_mask_ = 0; // The origin for the current removal operation. - GURL remove_origin_; + url::Origin remove_origin_; }; #endif diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index 8951e30..e74e8a3 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -519,16 +519,11 @@ Ewk_Cookie_Manager* EWebContext::ewkCookieManager() { } void EWebContext::DeleteAllApplicationCache() { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - base::ThreadPool::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&EWebContext::DeleteAllApplicationCache, - base::Unretained(this))); - return; - } + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get()); remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_APPCACHE, GURL()); + remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_SESSION_STORAGE, GURL()); } void EWebContext::DeleteApplicationCacheForSite(const GURL& site) { -- 2.7.4 From ec2996083e51a9e3874fe71eaae59e2b2a7ab4c3 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Mon, 23 Jan 2023 15:46:57 +0530 Subject: [PATCH 05/16] [M108 Migration] Enable ScreenOrientationDelegate for EFL ScreenOrientationDelegate is needed for fixing tct-screenorientation-w3c-tests failures on M108. Reference: https://review.tizen.org/gerrit/c/274262/ Change-Id: I08d37b9c5c40a551971a79df6b0938300d38d25e Signed-off-by: Ayush Kumar --- content/browser/browser_main_loop.cc | 14 ++++++++++++++ content/browser/browser_main_loop.h | 6 +++--- content/public/common/content_switches.cc | 5 +++++ content/public/common/content_switches.h | 4 ++++ .../screen_orientation/screen_orientation_delegate_efl.cc | 8 +++----- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 28a7e2b..eedf4ba 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -242,6 +242,10 @@ #include "mojo/public/cpp/bindings/lib/test_random_mojo_delays.h" #endif +#if BUILDFLAG(IS_EFL) +#include "content/browser/screen_orientation/screen_orientation_delegate_efl.h" +#endif + // One of the linux specific headers defines this as a macro. #ifdef DestroyAll #undef DestroyAll @@ -713,6 +717,16 @@ void BrowserMainLoop::PostCreateMainMessageLoop() { base::trace_event::CPUFreqMonitor::GetInstance()); #endif +#if BUILDFLAG(IS_EFL) + if (!parsed_command_line_.HasSwitch( + switches::kDisableScreenOrientationLock)) { + TRACE_EVENT0("startup", + "BrowserMainLoop::Subsystem:ScreenOrientationProvider"); + screen_orientation_delegate_ = + std::make_unique(); + } +#endif + if (UsingInProcessGpu()) { // Make sure to limits for skia font cache are applied for in process // gpu setup (crbug.com/1183230). diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index b2660cd..5e2ef10 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h @@ -102,7 +102,7 @@ namespace responsiveness { class Watcher; } // namespace responsiveness -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_EFL) class ScreenOrientationDelegate; #endif @@ -326,8 +326,8 @@ class CONTENT_EXPORT BrowserMainLoop { std::unique_ptr screenlock_monitor_; // Per-process listener for online state changes. std::unique_ptr online_state_observer_; -#if BUILDFLAG(IS_ANDROID) - // Android implementation of ScreenOrientationDelegate +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_EFL) + // Android/EFL implementation of ScreenOrientationDelegate std::unique_ptr screen_orientation_delegate_; #endif diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index f42b7c2..310961b 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -985,6 +985,11 @@ const char kRendererWaitForJavaDebugger[] = "renderer-wait-for-java-debugger"; const char kDisableOoprDebugCrashDump[] = "disable-oopr-debug-crash-dump"; #endif +#if BUILDFLAG(IS_EFL) +// Disable the locking feature of the screen orientation API. +const char kDisableScreenOrientationLock[] = "disable-screen-orientation-lock"; +#endif + // Enable the aggressive flushing of DOM Storage to minimize data loss. const char kEnableAggressiveDOMStorageFlushing[] = "enable-aggressive-domstorage-flushing"; diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 6f44b6a..e3e3ddf 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -267,6 +267,10 @@ CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[]; CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[]; #endif +#if BUILDFLAG(IS_EFL) +CONTENT_EXPORT extern const char kDisableScreenOrientationLock[]; +#endif + // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) diff --git a/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc b/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc index 4fcddbf..a1dabf7 100644 --- a/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc +++ b/tizen_src/chromium_impl/content/browser/screen_orientation/screen_orientation_delegate_efl.cc @@ -5,18 +5,16 @@ #include "content/browser/screen_orientation/screen_orientation_delegate_efl.h" -#include "chromium_impl/content/browser/web_contents/web_contents_impl_efl.h" +#include "content/browser/web_contents/web_contents_impl_efl.h" +#include "content/browser/screen_orientation/screen_orientation_provider.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "ewk/efl_integration/web_contents_efl_delegate_ewk.h" namespace content { -ScreenOrientationDelegate* CreateScreenOrientationDelegateEfl() { - return new ScreenOrientationDelegateEfl(); -} - ScreenOrientationDelegateEfl::ScreenOrientationDelegateEfl() { + ScreenOrientationProvider::SetDelegate(this); } ScreenOrientationDelegateEfl::~ScreenOrientationDelegateEfl() { -- 2.7.4 From 01df9be73211ec524e18da880199503f7411a1eb Mon Sep 17 00:00:00 2001 From: v-saha Date: Mon, 23 Jan 2023 19:37:42 +0530 Subject: [PATCH 06/16] [M108 Migration][Canvas2D][TCT] Do not accelerate small size canvas. Accelerating canvas with smaller size causes TCT issues since M76, it is known in upstream and reported too. Hence disabling acceleration for smaller canvases for EFL port. References: https://review.tizen.org/gerrit/274897 https://bugs.chromium.org/p/chromium/issues/detail?id=1051392 Change-Id: Ie7642016d3d66b8290c9e3a0d170b5f8e16311fa Signed-off-by: v-saha --- content/child/runtime_features.cc | 4 ++++ third_party/blink/public/platform/web_runtime_features.h | 1 + third_party/blink/renderer/platform/exported/web_runtime_features.cc | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 208ace0..3afa697 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc @@ -122,6 +122,10 @@ void SetRuntimeFeatureDefaultsForPlatform( #if BUILDFLAG(IS_EFL) // No plan to support complex UI for date/time INPUT types. WebRuntimeFeatures::EnableInputMultipleFieldsUI(false); + + // Small accelerated 2d canvas has tct issues, which are known in + // upstream version also. + WebRuntimeFeatures::EnableAcceleratedSmallCanvases(false); #endif } diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 5897b64b..62b3f1f 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h @@ -69,6 +69,7 @@ class BLINK_PLATFORM_EXPORT WebRuntimeFeatures : public WebRuntimeFeaturesBase { static void EnableFluentScrollbars(bool); #if BUILDFLAG(IS_EFL) static void EnableInputMultipleFieldsUI(bool); + static void EnableAcceleratedSmallCanvases(bool); #endif WebRuntimeFeatures() = delete; diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 5dd2b16..263302a 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc @@ -69,6 +69,10 @@ void WebRuntimeFeatures::EnableFluentScrollbars(bool enable) { void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) { RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable); } + +void WebRuntimeFeatures::EnableAcceleratedSmallCanvases(bool enable) { + RuntimeEnabledFeatures::SetAcceleratedSmallCanvasesEnabled(enable); +} #endif } // namespace blink -- 2.7.4 From d3644c0193273f708634389d6b47e18c1c8a0c24 Mon Sep 17 00:00:00 2001 From: uzair Date: Thu, 5 Jan 2023 13:31:55 +0530 Subject: [PATCH 07/16] [PDNCF] Backport ImageManager class and its dependencies Zero copy video rendering path is dependent on chromium GL_CHROMIUM_image extension but open source plans to deprecate it in future and hence some part of code is removed before 108 branch was forked for tizen and the new CHROMIUM_shared_image extension path is not completely present in 108 version. For now we partially backport [1] and [2] to bringup TBM path. [1] https://chromium-review.googlesource.com/c/chromium/src/+/3582497 [2] https://chromium-review.googlesource.com/c/chromium/src/+/3743320 Change-Id: If3d8eff200650113bd5b4893bb1636cd9895cb03 Signed-off-by: uzair --- gpu/GLES2/gl2chromium_autogen.h | 4 + gpu/GLES2/gl2extchromium.h | 37 +++++++ gpu/command_buffer/build_gles2_cmd_buffer.py | 15 +++ gpu/command_buffer/client/gles2_c_lib_autogen.h | 26 +++++ .../client/gles2_cmd_helper_autogen.h | 26 +++++ .../client/gles2_implementation_autogen.h | 8 ++ .../client/gles2_implementation_impl_autogen.h | 34 ++++++ .../client/gles2_implementation_unittest_autogen.h | 33 ++++++ .../client/gles2_interface_autogen.h | 5 + .../client/gles2_interface_stub_autogen.h | 5 + .../client/gles2_interface_stub_impl_autogen.h | 8 ++ .../client/gles2_trace_implementation_autogen.h | 5 + .../gles2_trace_implementation_impl_autogen.h | 22 ++++ .../common/gles2_cmd_format_autogen.h | 120 ++++++++++++++++++++ .../common/gles2_cmd_format_test_autogen.h | 41 +++++++ gpu/command_buffer/common/gles2_cmd_ids_autogen.h | 73 ++++++------ gpu/command_buffer/gles2_cmd_buffer_functions.txt | 3 + gpu/command_buffer/service/BUILD.gn | 2 + .../service/command_buffer_task_executor.h | 4 + gpu/command_buffer/service/context_group.cc | 2 + gpu/command_buffer/service/context_group.h | 6 + gpu/command_buffer/service/gles2_cmd_decoder.cc | 122 +++++++++++++++++++++ gpu/command_buffer/service/gles2_cmd_decoder.h | 1 + .../service/gles2_cmd_decoder_autogen.h | 58 ++++++++++ .../service/gles2_cmd_decoder_passthrough.cc | 46 ++++++++ .../service/gles2_cmd_decoder_passthrough.h | 5 + ...gles2_cmd_decoder_passthrough_doer_prototypes.h | 5 + .../service/gles2_cmd_decoder_passthrough_doers.cc | 49 +++++++++ ...es2_cmd_decoder_passthrough_handlers_autogen.cc | 48 ++++++++ gpu/command_buffer/service/image_manager.cc | 38 +++++++ gpu/command_buffer/service/image_manager.h | 42 +++++++ gpu/gles2_conform_support/egl/context.cc | 4 +- gpu/gles2_conform_support/egl/context.h | 2 + gpu/ipc/common/gpu_channel.mojom | 20 ++++ gpu/ipc/in_process_command_buffer.cc | 6 +- gpu/ipc/service/command_buffer_stub.cc | 8 ++ gpu/ipc/service/command_buffer_stub.h | 2 + gpu/ipc/service/gles2_command_buffer_stub.cc | 65 ++++++++++- gpu/ipc/service/gles2_command_buffer_stub.h | 3 + gpu/ipc/service/gpu_channel.cc | 21 ++++ gpu/ipc/service/gpu_channel.h | 11 ++ ui/gl/gl_image.cc | 6 + ui/gl/gl_image.h | 7 ++ 43 files changed, 1007 insertions(+), 41 deletions(-) create mode 100644 gpu/command_buffer/service/image_manager.cc create mode 100644 gpu/command_buffer/service/image_manager.h diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index f0b3a3d..efcb0d37 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -330,6 +330,10 @@ #define glCreateAndConsumeTextureCHROMIUM \ GLES2_GET_FUN(CreateAndConsumeTextureCHROMIUM) #define glBindUniformLocationCHROMIUM GLES2_GET_FUN(BindUniformLocationCHROMIUM) +#define glBindTexImage2DCHROMIUM GLES2_GET_FUN(BindTexImage2DCHROMIUM) +#define glBindTexImage2DWithInternalformatCHROMIUM \ + GLES2_GET_FUN(BindTexImage2DWithInternalformatCHROMIUM) +#define glReleaseTexImage2DCHROMIUM GLES2_GET_FUN(ReleaseTexImage2DCHROMIUM) #define glTraceBeginCHROMIUM GLES2_GET_FUN(TraceBeginCHROMIUM) #define glTraceEndCHROMIUM GLES2_GET_FUN(TraceEndCHROMIUM) #define glDiscardFramebufferEXT GLES2_GET_FUN(DiscardFramebufferEXT) diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index da4583a..44036b8 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h @@ -63,6 +63,43 @@ typedef GLboolean (GL_APIENTRY PFNGLUNMAPBUFFERCHROMIUM) (GLuint target); #endif #endif /* GL_CHROMIUM_pixel_transfer_buffer_object */ +/* GL_CHROMIUM_image */ +#ifndef GL_CHROMIUM_image +#define GL_CHROMIUM_image 1 + +typedef struct _ClientBuffer* ClientBuffer; + +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM(ClientBuffer buffer, + GLsizei width, + GLsizei height, + GLenum internalformat); +GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM(GLuint image_id); +GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM(GLenum target, + GLint imageId); +GL_APICALL void GL_APIENTRY +glBindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId); +GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM(GLenum target, + GLint imageId); +#endif +typedef GLuint(GL_APIENTRYP PFNGLCREATEIMAGECHROMIUMPROC)( + ClientBuffer buffer, + GLsizei width, + GLsizei height, + GLenum internalformat); +typedef void(GL_APIENTRYP PFNGLDESTROYIMAGECHROMIUMPROC)(GLuint image_id); +typedef void(GL_APIENTRYP PFNGLBINDTEXIMAGE2DCHROMIUMPROC)(GLenum target, + GLint imageId); +typedef void(GL_APIENTRYP PFNGLBINDTEXIMAGE2DWITHINTERNALFORMATCHROMIUMPROC)( + GLenum target, + GLenum internalformat, + GLint imageId); +typedef void(GL_APIENTRYP PFNGLRELEASETEXIMAGE2DCHROMIUMPROC)(GLenum target, + GLint imageId); +#endif /* GL_CHROMIUM_image */ + #ifndef GL_RGB_YCRCB_420_CHROMIUM #define GL_RGB_YCRCB_420_CHROMIUM 0x78FA #endif diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 453d713..b8bef5e 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3885,6 +3885,21 @@ _FUNCTION_INFO = { 'unit_test': False, 'pepper_interface': 'VertexArrayObject', }, + 'BindTexImage2DCHROMIUM': { + 'decoder_func': 'DoBindTexImage2DCHROMIUM', + 'unit_test': False, + 'extension': "CHROMIUM_image", + }, + 'BindTexImage2DWithInternalformatCHROMIUM': { + 'decoder_func': 'DoBindTexImage2DWithInternalformatCHROMIUM', + 'unit_test': False, + 'extension': "CHROMIUM_image", + }, + 'ReleaseTexImage2DCHROMIUM': { + 'decoder_func': 'DoReleaseTexImage2DCHROMIUM', + 'unit_test': False, + 'extension': "CHROMIUM_image", + }, 'IsVertexArrayOES': { 'type': 'Is', 'extension': 'OES_vertex_array_object', diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 161c43e..7114150 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1546,6 +1546,19 @@ void GL_APIENTRY GLES2BindUniformLocationCHROMIUM(GLuint program, const char* name) { gles2::GetGLContext()->BindUniformLocationCHROMIUM(program, location, name); } +void GL_APIENTRY GLES2BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::GetGLContext()->BindTexImage2DCHROMIUM(target, imageId); +} +void GL_APIENTRY +GLES2BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) { + gles2::GetGLContext()->BindTexImage2DWithInternalformatCHROMIUM( + target, internalformat, imageId); +} +void GL_APIENTRY GLES2ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::GetGLContext()->ReleaseTexImage2DCHROMIUM(target, imageId); +} void GL_APIENTRY GLES2TraceBeginCHROMIUM(const char* category_name, const char* trace_name) { gles2::GetGLContext()->TraceBeginCHROMIUM(category_name, trace_name); @@ -2908,6 +2921,19 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast(glBindUniformLocationCHROMIUM), }, { + "glBindTexImage2DCHROMIUM", + reinterpret_cast(glBindTexImage2DCHROMIUM), + }, + { + "glBindTexImage2DWithInternalformatCHROMIUM", + reinterpret_cast( + glBindTexImage2DWithInternalformatCHROMIUM), + }, + { + "glReleaseTexImage2DCHROMIUM", + reinterpret_cast(glReleaseTexImage2DCHROMIUM), + }, + { "glTraceBeginCHROMIUM", reinterpret_cast(glTraceBeginCHROMIUM), }, diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 7676f76..1de1be1 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -2923,6 +2923,32 @@ void BindUniformLocationCHROMIUMBucket(GLuint program, } } +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::cmds::BindTexImage2DCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, imageId); + } +} + +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) { + gles2::cmds::BindTexImage2DWithInternalformatCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, internalformat, imageId); + } +} + +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) { + gles2::cmds::ReleaseTexImage2DCHROMIUM* c = + GetCmdSpace(); + if (c) { + c->Init(target, imageId); + } +} + void TraceBeginCHROMIUM(GLuint category_bucket_id, GLuint name_bucket_id) { gles2::cmds::TraceBeginCHROMIUM* c = GetCmdSpace(); diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index b556b23..f1c6a51 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -1090,6 +1090,14 @@ void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; + +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) override; + +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; + void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) override; diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index a8586eb..1b945f0 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -3326,6 +3326,40 @@ void GLES2Implementation::CopySubTextureCHROMIUM( CheckGLError(); } +void GLES2Implementation::BindTexImage2DCHROMIUM(GLenum target, GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindTexImage2DCHROMIUM(" + << GLES2Util::GetStringTextureBindTarget(target) << ", " + << imageId << ")"); + helper_->BindTexImage2DCHROMIUM(target, imageId); + CheckGLError(); +} + +void GLES2Implementation::BindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG( + "[" << GetLogPrefix() << "] glBindTexImage2DWithInternalformatCHROMIUM(" + << GLES2Util::GetStringTextureBindTarget(target) << ", " + << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " + << imageId << ")"); + helper_->BindTexImage2DWithInternalformatCHROMIUM(target, internalformat, + imageId); + CheckGLError(); +} + +void GLES2Implementation::ReleaseTexImage2DCHROMIUM(GLenum target, + GLint imageId) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReleaseTexImage2DCHROMIUM(" + << GLES2Util::GetStringTextureBindTarget(target) << ", " + << imageId << ")"); + helper_->ReleaseTexImage2DCHROMIUM(target, imageId); + CheckGLError(); +} + void GLES2Implementation::DiscardFramebufferEXT(GLenum target, GLsizei count, const GLenum* attachments) { diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 6f17bb34..c2d65f1 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -2874,6 +2874,39 @@ TEST_F(GLES2ImplementationTest, VertexAttribDivisorANGLE) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, BindTexImage2DCHROMIUM) { + struct Cmds { + cmds::BindTexImage2DCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, 2); + + gl_->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, BindTexImage2DWithInternalformatCHROMIUM) { + struct Cmds { + cmds::BindTexImage2DWithInternalformatCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, GL_ALPHA, 3); + + gl_->BindTexImage2DWithInternalformatCHROMIUM(GL_TEXTURE_2D, GL_ALPHA, 3); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, ReleaseTexImage2DCHROMIUM) { + struct Cmds { + cmds::ReleaseTexImage2DCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TEXTURE_2D, 2); + + gl_->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, DiscardFramebufferEXT) { GLenum data[2][1] = {{0}}; struct Cmds { diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 9867b5d..d24bf67 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -814,6 +814,11 @@ virtual GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) = 0; virtual void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) = 0; +virtual void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0; +virtual void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) = 0; +virtual void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) = 0; virtual void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) = 0; virtual void TraceEndCHROMIUM() = 0; diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 0127a24..c799d22 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -790,6 +790,11 @@ GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override; void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) override; +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) override; void TraceEndCHROMIUM() override; diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 7d3af70..0dc071a 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -1056,6 +1056,14 @@ GLuint GLES2InterfaceStub::CreateAndConsumeTextureCHROMIUM( void GLES2InterfaceStub::BindUniformLocationCHROMIUM(GLuint /* program */, GLint /* location */, const char* /* name */) {} +void GLES2InterfaceStub::BindTexImage2DCHROMIUM(GLenum /* target */, + GLint /* imageId */) {} +void GLES2InterfaceStub::BindTexImage2DWithInternalformatCHROMIUM( + GLenum /* target */, + GLenum /* internalformat */, + GLint /* imageId */) {} +void GLES2InterfaceStub::ReleaseTexImage2DCHROMIUM(GLenum /* target */, + GLint /* imageId */) {} void GLES2InterfaceStub::TraceBeginCHROMIUM(const char* /* category_name */, const char* /* trace_name */) {} void GLES2InterfaceStub::TraceEndCHROMIUM() {} diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 9c075c5..2103e9e 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -790,6 +790,11 @@ GLuint CreateAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override; void BindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name) override; +void BindTexImage2DCHROMIUM(GLenum target, GLint imageId) override; +void BindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId) override; +void ReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId) override; void TraceBeginCHROMIUM(const char* category_name, const char* trace_name) override; void TraceEndCHROMIUM() override; diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 071fc7c..e22cb21 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -2217,6 +2217,28 @@ void GLES2TraceImplementation::BindUniformLocationCHROMIUM(GLuint program, gl_->BindUniformLocationCHROMIUM(program, location, name); } +void GLES2TraceImplementation::BindTexImage2DCHROMIUM(GLenum target, + GLint imageId) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindTexImage2DCHROMIUM"); + gl_->BindTexImage2DCHROMIUM(target, imageId); +} + +void GLES2TraceImplementation::BindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint imageId) { + TRACE_EVENT_BINARY_EFFICIENT0( + "gpu", "GLES2Trace::BindTexImage2DWithInternalformatCHROMIUM"); + gl_->BindTexImage2DWithInternalformatCHROMIUM(target, internalformat, + imageId); +} + +void GLES2TraceImplementation::ReleaseTexImage2DCHROMIUM(GLenum target, + GLint imageId) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::ReleaseTexImage2DCHROMIUM"); + gl_->ReleaseTexImage2DCHROMIUM(target, imageId); +} + void GLES2TraceImplementation::TraceBeginCHROMIUM(const char* category_name, const char* trace_name) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::TraceBeginCHROMIUM"); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 0c8b458..c6e3715 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -14537,6 +14537,126 @@ static_assert( offsetof(BindUniformLocationCHROMIUMBucket, name_bucket_id) == 12, "offset of BindUniformLocationCHROMIUMBucket name_bucket_id should be 12"); +struct BindTexImage2DCHROMIUM { + typedef BindTexImage2DCHROMIUM ValueType; + static const CommandId kCmdId = kBindTexImage2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, GLint _imageId) { + SetHeader(); + target = _target; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLint _imageId) { + static_cast(cmd)->Init(_target, _imageId); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + int32_t imageId; +}; + +static_assert(sizeof(BindTexImage2DCHROMIUM) == 12, + "size of BindTexImage2DCHROMIUM should be 12"); +static_assert(offsetof(BindTexImage2DCHROMIUM, header) == 0, + "offset of BindTexImage2DCHROMIUM header should be 0"); +static_assert(offsetof(BindTexImage2DCHROMIUM, target) == 4, + "offset of BindTexImage2DCHROMIUM target should be 4"); +static_assert(offsetof(BindTexImage2DCHROMIUM, imageId) == 8, + "offset of BindTexImage2DCHROMIUM imageId should be 8"); + +struct BindTexImage2DWithInternalformatCHROMIUM { + typedef BindTexImage2DWithInternalformatCHROMIUM ValueType; + static const CommandId kCmdId = kBindTexImage2DWithInternalformatCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, GLenum _internalformat, GLint _imageId) { + SetHeader(); + target = _target; + internalformat = _internalformat; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLenum _internalformat, GLint _imageId) { + static_cast(cmd)->Init(_target, _internalformat, _imageId); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + uint32_t internalformat; + int32_t imageId; +}; + +static_assert(sizeof(BindTexImage2DWithInternalformatCHROMIUM) == 16, + "size of BindTexImage2DWithInternalformatCHROMIUM should be 16"); +static_assert( + offsetof(BindTexImage2DWithInternalformatCHROMIUM, header) == 0, + "offset of BindTexImage2DWithInternalformatCHROMIUM header should be 0"); +static_assert( + offsetof(BindTexImage2DWithInternalformatCHROMIUM, target) == 4, + "offset of BindTexImage2DWithInternalformatCHROMIUM target should be 4"); +static_assert(offsetof(BindTexImage2DWithInternalformatCHROMIUM, + internalformat) == 8, + "offset of BindTexImage2DWithInternalformatCHROMIUM " + "internalformat should be 8"); +static_assert( + offsetof(BindTexImage2DWithInternalformatCHROMIUM, imageId) == 12, + "offset of BindTexImage2DWithInternalformatCHROMIUM imageId should be 12"); + +struct ReleaseTexImage2DCHROMIUM { + typedef ReleaseTexImage2DCHROMIUM ValueType; + static const CommandId kCmdId = kReleaseTexImage2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd(); } + + void Init(GLenum _target, GLint _imageId) { + SetHeader(); + target = _target; + imageId = _imageId; + } + + void* Set(void* cmd, GLenum _target, GLint _imageId) { + static_cast(cmd)->Init(_target, _imageId); + return NextCmdAddress(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + int32_t imageId; +}; + +static_assert(sizeof(ReleaseTexImage2DCHROMIUM) == 12, + "size of ReleaseTexImage2DCHROMIUM should be 12"); +static_assert(offsetof(ReleaseTexImage2DCHROMIUM, header) == 0, + "offset of ReleaseTexImage2DCHROMIUM header should be 0"); +static_assert(offsetof(ReleaseTexImage2DCHROMIUM, target) == 4, + "offset of ReleaseTexImage2DCHROMIUM target should be 4"); +static_assert(offsetof(ReleaseTexImage2DCHROMIUM, imageId) == 8, + "offset of ReleaseTexImage2DCHROMIUM imageId should be 8"); + struct TraceBeginCHROMIUM { typedef TraceBeginCHROMIUM ValueType; static const CommandId kCmdId = kTraceBeginCHROMIUM; diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 5f45c44..d4b335c 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -4795,6 +4795,47 @@ TEST_F(GLES2FormatTest, BindUniformLocationCHROMIUMBucket) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BindTexImage2DCHROMIUM) { + cmds::BindTexImage2DCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = + cmd.Set(&cmd, static_cast(11), static_cast(12)); + EXPECT_EQ(static_cast(cmds::BindTexImage2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, BindTexImage2DWithInternalformatCHROMIUM) { + cmds::BindTexImage2DWithInternalformatCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = cmd.Set(&cmd, static_cast(11), + static_cast(12), static_cast(13)); + EXPECT_EQ(static_cast( + cmds::BindTexImage2DWithInternalformatCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.internalformat); + EXPECT_EQ(static_cast(13), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, ReleaseTexImage2DCHROMIUM) { + cmds::ReleaseTexImage2DCHROMIUM& cmd = + *GetBufferAs(); + void* next_cmd = + cmd.Set(&cmd, static_cast(11), static_cast(12)); + EXPECT_EQ(static_cast(cmds::ReleaseTexImage2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast(11), cmd.target); + EXPECT_EQ(static_cast(12), cmd.imageId); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, TraceBeginCHROMIUM) { cmds::TraceBeginCHROMIUM& cmd = *GetBufferAs(); void* next_cmd = diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 4a47970..430f843 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -301,41 +301,44 @@ OP(ProduceTextureDirectCHROMIUMImmediate) /* 542 */ \ OP(CreateAndConsumeTextureINTERNALImmediate) /* 543 */ \ OP(BindUniformLocationCHROMIUMBucket) /* 544 */ \ - OP(TraceBeginCHROMIUM) /* 545 */ \ - OP(TraceEndCHROMIUM) /* 546 */ \ - OP(DiscardFramebufferEXTImmediate) /* 547 */ \ - OP(LoseContextCHROMIUM) /* 548 */ \ - OP(DrawBuffersEXTImmediate) /* 549 */ \ - OP(DiscardBackbufferCHROMIUM) /* 550 */ \ - OP(FlushDriverCachesCHROMIUM) /* 551 */ \ - OP(SetActiveURLCHROMIUM) /* 552 */ \ - OP(ContextVisibilityHintCHROMIUM) /* 553 */ \ - OP(CoverageModulationCHROMIUM) /* 554 */ \ - OP(BlendBarrierKHR) /* 555 */ \ - OP(BindFragDataLocationIndexedEXTBucket) /* 556 */ \ - OP(BindFragDataLocationEXTBucket) /* 557 */ \ - OP(GetFragDataIndexEXT) /* 558 */ \ - OP(InitializeDiscardableTextureCHROMIUM) /* 559 */ \ - OP(UnlockDiscardableTextureCHROMIUM) /* 560 */ \ - OP(LockDiscardableTextureCHROMIUM) /* 561 */ \ - OP(WindowRectanglesEXTImmediate) /* 562 */ \ - OP(CreateGpuFenceINTERNAL) /* 563 */ \ - OP(WaitGpuFenceCHROMIUM) /* 564 */ \ - OP(DestroyGpuFenceCHROMIUM) /* 565 */ \ - OP(SetReadbackBufferShadowAllocationINTERNAL) /* 566 */ \ - OP(FramebufferTextureMultiviewOVR) /* 567 */ \ - OP(MaxShaderCompilerThreadsKHR) /* 568 */ \ - OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 569 */ \ - OP(BeginSharedImageAccessDirectCHROMIUM) /* 570 */ \ - OP(EndSharedImageAccessDirectCHROMIUM) /* 571 */ \ - OP(EnableiOES) /* 572 */ \ - OP(DisableiOES) /* 573 */ \ - OP(BlendEquationiOES) /* 574 */ \ - OP(BlendEquationSeparateiOES) /* 575 */ \ - OP(BlendFunciOES) /* 576 */ \ - OP(BlendFuncSeparateiOES) /* 577 */ \ - OP(ColorMaskiOES) /* 578 */ \ - OP(IsEnablediOES) /* 579 */ + OP(BindTexImage2DCHROMIUM) /* 545 */ \ + OP(BindTexImage2DWithInternalformatCHROMIUM) /* 546 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 547 */ \ + OP(TraceBeginCHROMIUM) /* 548 */ \ + OP(TraceEndCHROMIUM) /* 549 */ \ + OP(DiscardFramebufferEXTImmediate) /* 550 */ \ + OP(LoseContextCHROMIUM) /* 551 */ \ + OP(DrawBuffersEXTImmediate) /* 552 */ \ + OP(DiscardBackbufferCHROMIUM) /* 553 */ \ + OP(FlushDriverCachesCHROMIUM) /* 554 */ \ + OP(SetActiveURLCHROMIUM) /* 555 */ \ + OP(ContextVisibilityHintCHROMIUM) /* 556 */ \ + OP(CoverageModulationCHROMIUM) /* 557 */ \ + OP(BlendBarrierKHR) /* 558 */ \ + OP(BindFragDataLocationIndexedEXTBucket) /* 559 */ \ + OP(BindFragDataLocationEXTBucket) /* 560 */ \ + OP(GetFragDataIndexEXT) /* 561 */ \ + OP(InitializeDiscardableTextureCHROMIUM) /* 562 */ \ + OP(UnlockDiscardableTextureCHROMIUM) /* 563 */ \ + OP(LockDiscardableTextureCHROMIUM) /* 564 */ \ + OP(WindowRectanglesEXTImmediate) /* 565 */ \ + OP(CreateGpuFenceINTERNAL) /* 566 */ \ + OP(WaitGpuFenceCHROMIUM) /* 567 */ \ + OP(DestroyGpuFenceCHROMIUM) /* 568 */ \ + OP(SetReadbackBufferShadowAllocationINTERNAL) /* 569 */ \ + OP(FramebufferTextureMultiviewOVR) /* 570 */ \ + OP(MaxShaderCompilerThreadsKHR) /* 571 */ \ + OP(CreateAndTexStorage2DSharedImageINTERNALImmediate) /* 572 */ \ + OP(BeginSharedImageAccessDirectCHROMIUM) /* 573 */ \ + OP(EndSharedImageAccessDirectCHROMIUM) /* 574 */ \ + OP(EnableiOES) /* 575 */ \ + OP(DisableiOES) /* 576 */ \ + OP(BlendEquationiOES) /* 577 */ \ + OP(BlendEquationSeparateiOES) /* 578 */ \ + OP(BlendFunciOES) /* 579 */ \ + OP(BlendFuncSeparateiOES) /* 580 */ \ + OP(ColorMaskiOES) /* 581 */ \ + OP(IsEnablediOES) /* 582 */ enum CommandId { kOneBeforeStartPoint = diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt index 590507a..a2801cd 100644 --- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt +++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt @@ -323,6 +323,9 @@ GL_APICALL void GL_APIENTRY glProduceTextureDirectCHROMIUM (GLidBindText GL_APICALL GLuint GL_APIENTRY glCreateAndConsumeTextureCHROMIUM (const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glCreateAndConsumeTextureINTERNAL (GLuint texture, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glBindUniformLocationCHROMIUM (GLidProgram program, GLint location, const char* name); +GL_APICALL void GL_APIENTRY glBindTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); +GL_APICALL void GL_APIENTRY glBindTexImage2DWithInternalformatCHROMIUM (GLenumTextureBindTarget target, GLenumTextureInternalFormat internalformat, GLint imageId); +GL_APICALL void GL_APIENTRY glReleaseTexImage2DCHROMIUM (GLenumTextureBindTarget target, GLint imageId); GL_APICALL void GL_APIENTRY glTraceBeginCHROMIUM (const char* category_name, const char* trace_name); GL_APICALL void GL_APIENTRY glTraceEndCHROMIUM (void); GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenumFramebufferTarget target, GLsizei count, const GLenum* attachments); diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 4632c26..a03eceb 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn @@ -48,6 +48,8 @@ target(link_target_type, "service_sources") { "gpu_switches.h", "image_factory.cc", "image_factory.h", + "image_manager.cc", + "image_manager.h", "mailbox_manager.h", "memory_tracking.cc", "memory_tracking.h", diff --git a/gpu/command_buffer/service/command_buffer_task_executor.h b/gpu/command_buffer/service/command_buffer_task_executor.h index 56f94e7..b01d55f 100644 --- a/gpu/command_buffer/service/command_buffer_task_executor.h +++ b/gpu/command_buffer/service/command_buffer_task_executor.h @@ -13,6 +13,7 @@ #include "gpu/command_buffer/common/activity_flags.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/command_buffer/service/framebuffer_completeness_cache.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/passthrough_discardable_manager.h" #include "gpu/command_buffer/service/sequence_id.h" #include "gpu/command_buffer/service/service_discardable_manager.h" @@ -91,6 +92,8 @@ class GPU_GLES2_EXPORT CommandBufferTaskExecutor { MailboxManager* mailbox_manager() const { return mailbox_manager_; } // Not const because these return inner pointers. + + gles2::ImageManager* image_manager() { return &image_manager_; } ServiceDiscardableManager* discardable_manager() { return &discardable_manager_; } @@ -118,6 +121,7 @@ class GPU_GLES2_EXPORT CommandBufferTaskExecutor { gl::GLSurfaceFormat share_group_surface_format_; std::unique_ptr owned_program_cache_; raw_ptr program_cache_; + gles2::ImageManager image_manager_; ServiceDiscardableManager discardable_manager_; PassthroughDiscardableManager passthrough_discardable_manager_; gles2::ShaderTranslatorCache shader_translator_cache_; diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 0638760..b714271 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -76,6 +76,7 @@ ContextGroup::ContextGroup( FramebufferCompletenessCache* framebuffer_completeness_cache, const scoped_refptr& feature_info, bool bind_generates_resource, + ImageManager* image_manager, gpu::ImageFactory* image_factory, gl::ProgressReporter* progress_reporter, const GpuFeatureInfo& gpu_feature_info, @@ -118,6 +119,7 @@ ContextGroup::ContextGroup( uniform_buffer_offset_alignment_(1u), program_cache_(nullptr), feature_info_(feature_info), + image_manager_(image_manager), image_factory_(image_factory), use_passthrough_cmd_decoder_(false), passthrough_resources_(new PassthroughResources), diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 0aaaf27..6760a38 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -44,6 +44,7 @@ namespace gles2 { class ProgramCache; class BufferManager; +class ImageManager; class RenderbufferManager; class ProgramManager; class SamplerManager; @@ -68,6 +69,7 @@ class GPU_GLES2_EXPORT ContextGroup : public base::RefCounted { FramebufferCompletenessCache* framebuffer_completeness_cache, const scoped_refptr& feature_info, bool bind_generates_resource, + ImageManager* image_manager, gpu::ImageFactory* image_factory, gl::ProgressReporter* progress_reporter, const GpuFeatureInfo& gpu_feature_info, @@ -164,6 +166,8 @@ class GPU_GLES2_EXPORT ContextGroup : public base::RefCounted { return feature_info_.get(); } + ImageManager* image_manager() const { return image_manager_; } + gpu::ImageFactory* image_factory() const { return image_factory_; } const GpuPreferences& gpu_preferences() const { @@ -309,6 +313,8 @@ class GPU_GLES2_EXPORT ContextGroup : public base::RefCounted { scoped_refptr feature_info_; + raw_ptr image_manager_; + raw_ptr image_factory_; std::vector> decoders_; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 0f2c253..43e00a8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -65,6 +65,7 @@ #include "gpu/command_buffer/service/gpu_state_tracer.h" #include "gpu/command_buffer/service/gpu_tracer.h" #include "gpu/command_buffer/service/image_factory.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -963,6 +964,8 @@ class GLES2DecoderImpl : public GLES2Decoder, return vertex_array_manager_.get(); } + ImageManager* image_manager() { return group_->image_manager(); } + MemoryTracker* memory_tracker() { return group_->memory_tracker(); } @@ -1221,6 +1224,16 @@ class GLES2DecoderImpl : public GLES2Decoder, uint32_t texture_target, gl::GLImage* image, bool can_bind_to_sampler) override; + void DoBindTexImage2DCHROMIUM(GLenum target, GLint image_id); + void DoBindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint image_id); + // Common implementation of DoBindTexImage2DCHROMIUM entry points. + void BindTexImage2DCHROMIUMImpl(const char* function_name, + GLenum target, + GLenum internalformat, + GLint image_id); + void DoReleaseTexImage2DCHROMIUM(GLenum target, GLint image_id); void DoTraceEndCHROMIUM(void); @@ -18586,6 +18599,115 @@ void GLES2DecoderImpl::BindImage(uint32_t client_texture_id, : gpu::gles2::Texture::UNBOUND); } +void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(GLenum target, GLint image_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM"); + + BindTexImage2DCHROMIUMImpl("glBindTexImage2DCHROMIUM", target, 0, image_id); +} + +void GLES2DecoderImpl::DoBindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint image_id) { + TRACE_EVENT0("gpu", + "GLES2DecoderImpl::DoBindTexImage2DWithInternalformatCHROMIUM"); + + BindTexImage2DCHROMIUMImpl("glBindTexImage2DWithInternalformatCHROMIUM", + target, internalformat, image_id); +} + +void GLES2DecoderImpl::BindTexImage2DCHROMIUMImpl(const char* function_name, + GLenum target, + GLenum internalformat, + GLint image_id) { + if (target == GL_TEXTURE_CUBE_MAP) { + LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, function_name, "invalid target"); + return; + } + + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "no texture bound"); + return; + } + + gl::GLImage* image = image_manager()->LookupImage(image_id); + if (!image) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "no image found with the given ID"); + return; + } + + Texture::ImageState image_state = Texture::UNBOUND; + + if (image->ShouldBindOrCopy() == gl::GLImage::BIND) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", error_state_.get()); + + // Note: We fallback to using CopyTexImage() before the texture is used + // when BindTexImage() fails. + if (internalformat) { + if (image->BindTexImageWithInternalformat(target, internalformat)) + image_state = Texture::BOUND; + } else { + if (image->BindTexImage(target)) + image_state = Texture::BOUND; + } + } + + gfx::Size size = image->GetSize(); + GLenum texture_internalformat = + internalformat ? internalformat : image->GetInternalFormat(); + texture_manager()->SetLevelInfo(texture_ref, target, 0, + texture_internalformat, size.width(), + size.height(), 1, 0, image->GetDataFormat(), + image->GetDataType(), gfx::Rect(size)); + texture_manager()->SetLevelImage(texture_ref, target, 0, image, image_state); +} + +void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(GLenum target, + GLint image_id) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM"); + + // Default target might be conceptually valid, but disallow it to avoid + // accidents. + TextureRef* texture_ref = + texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target); + if (!texture_ref) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReleaseTexImage2DCHROMIUM", + "no texture bound"); + return; + } + + gl::GLImage* image = image_manager()->LookupImage(image_id); + if (!image) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReleaseTexImage2DCHROMIUM", + "no image found with the given ID"); + return; + } + + Texture::ImageState image_state; + + // Do nothing when image is not currently bound. + if (texture_ref->texture()->GetLevelImage(target, 0, &image_state) != image) + return; + + if (image_state == Texture::BOUND) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", error_state_.get()); + + image->ReleaseTexImage(target); + texture_manager()->SetLevelInfo(texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + } + + texture_manager()->SetLevelImage(texture_ref, target, 0, nullptr, + Texture::UNBOUND); +} + error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index dc7f727..62bf9e9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -46,6 +46,7 @@ class CopyTexImageResourceManager; class CopyTextureCHROMIUMResourceManager; class FramebufferManager; class GLES2Util; +class ImageManager; class Logger; class Outputter; class ShaderTranslatorInterface; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index c07937b..e45bf73 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -5026,6 +5026,64 @@ error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureINTERNALImmediate( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBindTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glBindTexImage2DCHROMIUM", target, + "target"); + return error::kNoError; + } + DoBindTexImage2DCHROMIUM(target, imageId); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleBindTexImage2DWithInternalformatCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DWithInternalformatCHROMIUM& c = + *static_cast(cmd_data); + GLenum target = static_cast(c.target); + GLenum internalformat = static_cast(c.internalformat); + GLint imageId = static_cast(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBindTexImage2DWithInternalformatCHROMIUM", target, "target"); + return error::kNoError; + } + if (!validators_->texture_internal_format.IsValid(internalformat)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM( + "glBindTexImage2DWithInternalformatCHROMIUM", internalformat, + "internalformat"); + return error::kNoError; + } + DoBindTexImage2DWithInternalformatCHROMIUM(target, internalformat, imageId); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleReleaseTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::ReleaseTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + if (!validators_->texture_bind_target.IsValid(target)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glReleaseTexImage2DCHROMIUM", target, + "target"); + return error::kNoError; + } + DoReleaseTexImage2DCHROMIUM(target, imageId); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleTraceEndCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index ab2f90a..c716981 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -3012,6 +3012,52 @@ error::Error GLES2DecoderPassthroughImpl::HandleSetActiveURLCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::BindTexImage2DCHROMIUMImpl( + GLenum target, + GLenum internalformat, + GLint imageId) { + TextureTarget target_enum = GLenumToTextureTarget(target); + if (target_enum == TextureTarget::kCubeMap || + target_enum == TextureTarget::kUnkown) { + InsertError(GL_INVALID_ENUM, "Invalid target"); + return error::kNoError; + } + + gl::GLImage* image = group_->image_manager()->LookupImage(imageId); + if (image == nullptr) { + InsertError(GL_INVALID_OPERATION, "No image found with the given ID"); + return error::kNoError; + } + + const BoundTexture& bound_texture = + bound_textures_[static_cast(target_enum)][active_texture_unit_]; + if (bound_texture.texture == nullptr) { + InsertError(GL_INVALID_OPERATION, "No texture bound"); + return error::kNoError; + } + + if (image->ShouldBindOrCopy() == gl::GLImage::BIND) { + if (internalformat) + image->BindTexImageWithInternalformat(target, internalformat); + else + image->BindTexImage(target); + } else { + image->CopyTexImage(target); + } + + // Target is already validated + UpdateTextureSizeFromTarget(target); + + DCHECK(bound_texture.texture != nullptr); + bound_texture.texture->SetLevelImage(target, 0, image); + + // If there was any GLImage bound to |target| on this texture unit, then + // forget it. + RemovePendingBindingTexture(target, active_texture_unit_); + + return error::kNoError; +} + void GLES2DecoderPassthroughImpl::VerifyServiceTextureObjectsExist() { resources_->texture_object_map.ForEach( [this](GLuint client_id, scoped_refptr texture) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index e46b8ae..2e791c8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h @@ -25,6 +25,7 @@ #include "gpu/command_buffer/service/client_service_map.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/passthrough_abstract_texture_impl.h" @@ -465,6 +466,10 @@ class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl // up-to-date. void LazilyUpdateCurrentlyBoundElementArrayBuffer(); + error::Error BindTexImage2DCHROMIUMImpl(GLenum target, + GLenum internalformat, + GLint image_id); + void VerifyServiceTextureObjectsExist(); bool IsEmulatedFramebufferBound(GLenum target) const; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index 3a96342..cd4a3e0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h @@ -873,6 +873,11 @@ error::Error DoCreateAndConsumeTextureINTERNAL(GLuint texture_client_id, error::Error DoBindUniformLocationCHROMIUM(GLuint program, GLint location, const char* name); +error::Error DoBindTexImage2DCHROMIUM(GLenum target, GLint imageId); +error::Error DoBindTexImage2DWithInternalformatCHROMIUM(GLenum target, + GLenum internalformat, + GLint imageId); +error::Error DoReleaseTexImage2DCHROMIUM(GLenum target, GLint imageId); error::Error DoTraceBeginCHROMIUM(const char* category_name, const char* trace_name); error::Error DoTraceEndCHROMIUM(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index 9b09ddf..9b51b08 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc @@ -4572,6 +4572,55 @@ error::Error GLES2DecoderPassthroughImpl::DoBindUniformLocationCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::DoBindTexImage2DCHROMIUM( + GLenum target, + GLint imageId) { + return BindTexImage2DCHROMIUMImpl(target, 0, imageId); +} + +error::Error +GLES2DecoderPassthroughImpl::DoBindTexImage2DWithInternalformatCHROMIUM( + GLenum target, + GLenum internalformat, + GLint imageId) { + return BindTexImage2DCHROMIUMImpl(target, internalformat, imageId); +} + +error::Error GLES2DecoderPassthroughImpl::DoReleaseTexImage2DCHROMIUM( + GLenum target, + GLint imageId) { + TextureTarget target_enum = GLenumToTextureTarget(target); + if (target_enum == TextureTarget::kCubeMap || + target_enum == TextureTarget::kUnkown) { + InsertError(GL_INVALID_ENUM, "Invalid target"); + return error::kNoError; + } + + const BoundTexture& bound_texture = + bound_textures_[static_cast(target_enum)][active_texture_unit_]; + if (bound_texture.texture == nullptr) { + InsertError(GL_INVALID_OPERATION, "No texture bound"); + return error::kNoError; + } + + gl::GLImage* image = group_->image_manager()->LookupImage(imageId); + if (image == nullptr) { + InsertError(GL_INVALID_OPERATION, "No image found with the given ID"); + return error::kNoError; + } + + // Only release the image if it is currently bound + if (bound_texture.texture->GetLevelImage(target, 0) == image) { + image->ReleaseTexImage(target); + bound_texture.texture->SetLevelImage(target, 0, nullptr); + } + + // Target is already validated + UpdateTextureSizeFromTarget(target); + + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::DoTraceBeginCHROMIUM( const char* category_name, const char* trace_name) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc index 09295b0..e52e094 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc @@ -4302,6 +4302,54 @@ GLES2DecoderPassthroughImpl::HandleCreateAndConsumeTextureINTERNALImmediate( return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::HandleBindTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + error::Error error = DoBindTexImage2DCHROMIUM(target, imageId); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + +error::Error +GLES2DecoderPassthroughImpl::HandleBindTexImage2DWithInternalformatCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::BindTexImage2DWithInternalformatCHROMIUM& c = + *static_cast(cmd_data); + GLenum target = static_cast(c.target); + GLenum internalformat = static_cast(c.internalformat); + GLint imageId = static_cast(c.imageId); + error::Error error = DoBindTexImage2DWithInternalformatCHROMIUM( + target, internalformat, imageId); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::HandleReleaseTexImage2DCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::ReleaseTexImage2DCHROMIUM& c = + *static_cast( + cmd_data); + GLenum target = static_cast(c.target); + GLint imageId = static_cast(c.imageId); + error::Error error = DoReleaseTexImage2DCHROMIUM(target, imageId); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::HandleTraceEndCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { diff --git a/gpu/command_buffer/service/image_manager.cc b/gpu/command_buffer/service/image_manager.cc new file mode 100644 index 0000000..d7ca6d0 --- /dev/null +++ b/gpu/command_buffer/service/image_manager.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/image_manager.h" + +#include + +#include "base/check.h" +#include "ui/gl/gl_image.h" + +namespace gpu { +namespace gles2 { + +ImageManager::ImageManager() = default; + +ImageManager::~ImageManager() = default; + +void ImageManager::AddImage(gl::GLImage* image, int32_t service_id) { + DCHECK(images_.find(service_id) == images_.end()); + images_[service_id] = image; +} + +void ImageManager::RemoveImage(int32_t service_id) { + DCHECK(images_.find(service_id) != images_.end()); + images_.erase(service_id); +} + +gl::GLImage* ImageManager::LookupImage(int32_t service_id) { + GLImageMap::const_iterator iter = images_.find(service_id); + if (iter != images_.end()) + return iter->second.get(); + + return nullptr; +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/service/image_manager.h b/gpu/command_buffer/service/image_manager.h new file mode 100644 index 0000000..8397eee --- /dev/null +++ b/gpu/command_buffer/service/image_manager.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ + +#include + +#include + +#include "base/memory/ref_counted.h" +#include "gpu/gpu_export.h" + +namespace gl { +class GLImage; +} + +namespace gpu { +namespace gles2 { + +// This class keeps track of the images and their state. +class GPU_EXPORT ImageManager { + public: + ImageManager(); + ~ImageManager(); + ImageManager(const ImageManager&) = delete; + ImageManager& operator=(const ImageManager&) = delete; + + void AddImage(gl::GLImage* image, int32_t service_id); + void RemoveImage(int32_t service_id); + gl::GLImage* LookupImage(int32_t service_id); + + private: + typedef std::unordered_map> GLImageMap; + GLImageMap images_; +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_IMAGE_MANAGER_H_ diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc index 35fe874..9dfd81f 100644 --- a/gpu/gles2_conform_support/egl/context.cc +++ b/gpu/gles2_conform_support/egl/context.cc @@ -255,8 +255,8 @@ bool Context::CreateService(gl::GLSurface* gl_surface) { scoped_refptr group(new gpu::gles2::ContextGroup( gpu_preferences, true, &mailbox_manager_, nullptr /* memory_tracker */, &translator_cache_, &completeness_cache_, feature_info, true, - nullptr /* image_factory */, nullptr /* progress_reporter */, - gpu_feature_info, &discardable_manager_, + &image_manager_, nullptr /* image_factory */, + nullptr /* progress_reporter */, gpu_feature_info, &discardable_manager_, &passthrough_discardable_manager_, &shared_image_manager_)); auto command_buffer = std::make_unique(); diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h index f8d0b38..54dbc99 100644 --- a/gpu/gles2_conform_support/egl/context.h +++ b/gpu/gles2_conform_support/egl/context.h @@ -15,6 +15,7 @@ #include "gpu/command_buffer/service/command_buffer_direct.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gpu_tracer.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager_impl.h" #include "gpu/command_buffer/service/passthrough_discardable_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" @@ -116,6 +117,7 @@ class Context : public base::RefCountedThreadSafe, gpu::gles2::MailboxManagerImpl mailbox_manager_; gpu::gles2::TraceOutputter outputter_; + gpu::gles2::ImageManager image_manager_; gpu::ServiceDiscardableManager discardable_manager_; gpu::PassthroughDiscardableManager passthrough_discardable_manager_; gpu::SharedImageManager shared_image_manager_; diff --git a/gpu/ipc/common/gpu_channel.mojom b/gpu/ipc/common/gpu_channel.mojom index 717c9f0..e83f981 100644 --- a/gpu/ipc/common/gpu_channel.mojom +++ b/gpu/ipc/common/gpu_channel.mojom @@ -238,6 +238,15 @@ interface GpuChannel { ReleaseSysmemBufferCollection(mojo_base.mojom.UnguessableToken id); }; +struct CreateImageParams { + int32 id; + gfx.mojom.GpuMemoryBufferHandle gpu_memory_buffer; + gfx.mojom.Size size; + gfx.mojom.BufferFormat format; + gfx.mojom.BufferPlane plane; + uint64 image_release_count; +}; + // Interface used to issue commands to a specific CommandBuffer instance in the // GPU process. interface CommandBuffer { @@ -258,6 +267,17 @@ interface CommandBuffer { // Requests retrieval of a GpuFenceHandle by ID. GetGpuFenceHandle(uint32 id) => (gfx.mojom.GpuFenceHandle? fence_handle); + // Creates an image from an existing gpu memory buffer. The id that can be + // used to identify the image from a command buffer. + // + // TODO(crbug.com/1216120): Remove this once CreateImageCHROMIUM is gone. + CreateImage(CreateImageParams params); + + // Destroys a previously created image identified by `id`. + // + // TODO(crbug.com/1216120): Remove this once CreateImageCHROMIUM is gone. + DestroyImage(int32 id); + // Asynchronously waits until the SyncToken is signaled, then sends a // corresponding SignalAck on the CommandBufferClient interface, using // `signal_id` to identify this request. diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 0d9a6b3..8bf1b65 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc @@ -249,9 +249,9 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread( task_executor_->mailbox_manager(), std::move(memory_tracker), task_executor_->shader_translator_cache(), task_executor_->framebuffer_completeness_cache(), feature_info, - params.attribs.bind_generates_resource, params.image_factory, - nullptr /* progress_reporter */, task_executor_->gpu_feature_info(), - task_executor_->discardable_manager(), + params.attribs.bind_generates_resource, task_executor_->image_manager(), + params.image_factory, nullptr /* progress_reporter */, + task_executor_->gpu_feature_info(), task_executor_->discardable_manager(), task_executor_->passthrough_discardable_manager(), task_executor_->shared_image_manager()); diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc index 88de4e9..8c87d63 100644 --- a/gpu/ipc/service/command_buffer_stub.cc +++ b/gpu/ipc/service/command_buffer_stub.cc @@ -544,6 +544,14 @@ void CommandBufferStub::GetGpuFenceHandle(uint32_t id, std::move(callback).Run(gfx::GpuFenceHandle()); } +void CommandBufferStub::CreateImage(mojom::CreateImageParamsPtr params) { + DLOG(ERROR) << "CreateImage unsupported."; +} + +void CommandBufferStub::DestroyImage(int32_t id) { + DLOG(ERROR) << "DestroyImage unsupported."; +} + void CommandBufferStub::OnDestroyTransferBuffer(int32_t id) { TRACE_EVENT0("gpu", "CommandBufferStub::OnDestroyTransferBuffer"); diff --git a/gpu/ipc/service/command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h index 9089132..2d1b5cd 100644 --- a/gpu/ipc/service/command_buffer_stub.h +++ b/gpu/ipc/service/command_buffer_stub.h @@ -220,6 +220,8 @@ class GPU_IPC_SERVICE_EXPORT CommandBufferStub gfx::GpuFenceHandle handle) override; void GetGpuFenceHandle(uint32_t id, GetGpuFenceHandleCallback callback) override; + void CreateImage(mojom::CreateImageParamsPtr params) override; + void DestroyImage(int32_t id) override; void SignalSyncToken(const SyncToken& sync_token, uint32_t id) override; void SignalQuery(uint32_t query, uint32_t id) override; void BindMediaReceiver(mojo::GenericPendingAssociatedReceiver receiver, diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc index be556d7..cd81adc 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.cc +++ b/gpu/ipc/service/gles2_command_buffer_stub.cc @@ -26,6 +26,7 @@ #include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gl_state_restorer_impl.h" #include "gpu/command_buffer/service/gpu_fence_manager.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/logger.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" @@ -110,7 +111,7 @@ gpu::ContextResult GLES2CommandBufferStub::Initialize( manager->mailbox_manager(), CreateMemoryTracker(), manager->shader_translator_cache(), manager->framebuffer_completeness_cache(), feature_info, - init_params.attribs.bind_generates_resource, + init_params.attribs.bind_generates_resource, channel_->image_manager(), gmb_factory ? gmb_factory->AsImageFactory() : nullptr, manager->watchdog() /* progress_reporter */, manager->gpu_feature_info(), manager->discardable_manager(), @@ -508,6 +509,68 @@ void GLES2CommandBufferStub::GetGpuFenceHandle( std::move(callback).Run(std::move(handle)); } +void GLES2CommandBufferStub::CreateImage(mojom::CreateImageParamsPtr params) { + TRACE_EVENT0("gpu", "GLES2CommandBufferStub::OnCreateImage"); + const int32_t id = params->id; + const gfx::Size& size = params->size; + const gfx::BufferFormat& format = params->format; + const gfx::BufferPlane& plane = params->plane; + const uint64_t image_release_count = params->image_release_count; + ScopedContextOperation operation(*this); + if (!operation.is_context_current()) + return; + + gles2::ImageManager* image_manager = channel_->image_manager(); + DCHECK(image_manager); + if (image_manager->LookupImage(id)) { + LOG(ERROR) << "Image already exists with same ID."; + return; + } + + if (!gpu::IsImageFromGpuMemoryBufferFormatSupported( + format, gles2_decoder_->GetCapabilities())) { + LOG(ERROR) << "Format is not supported."; + return; + } + + if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, format)) { + LOG(ERROR) << "Invalid image size for format."; + return; + } + + if (!gpu::IsPlaneValidForGpuMemoryBufferFormat(plane, format)) { + LOG(ERROR) << "Invalid plane " << gfx::BufferPlaneToString(plane) << " for " + << gfx::BufferFormatToString(format); + return; + } + + scoped_refptr image = channel()->CreateImageForGpuMemoryBuffer( + std::move(params->gpu_memory_buffer), size, format, plane, + surface_handle_); + if (!image.get()) + return; + + image_manager->AddImage(image.get(), id); + if (image_release_count) + sync_point_client_state_->ReleaseFenceSync(image_release_count); +} + +void GLES2CommandBufferStub::DestroyImage(int32_t id) { + TRACE_EVENT0("gpu", "GLES2CommandBufferStub::OnDestroyImage"); + ScopedContextOperation operation(*this); + if (!operation.is_context_current()) + return; + + gles2::ImageManager* image_manager = channel_->image_manager(); + DCHECK(image_manager); + if (!image_manager->LookupImage(id)) { + LOG(ERROR) << "Image with ID doesn't exist."; + return; + } + + image_manager->RemoveImage(id); +} + void GLES2CommandBufferStub::OnSwapBuffers(uint64_t swap_id, uint32_t flags) {} } // namespace gpu diff --git a/gpu/ipc/service/gles2_command_buffer_stub.h b/gpu/ipc/service/gles2_command_buffer_stub.h index 4568fe5..973134f 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.h +++ b/gpu/ipc/service/gles2_command_buffer_stub.h @@ -66,6 +66,9 @@ class GPU_IPC_SERVICE_EXPORT GLES2CommandBufferStub void GetGpuFenceHandle(uint32_t gpu_fence_id, GetGpuFenceHandleCallback callback) override; + void CreateImage(mojom::CreateImageParamsPtr params) override; + void DestroyImage(int32_t id) override; + void OnSwapBuffers(uint64_t swap_id, uint32_t flags) override; // The group of contexts that share namespaces with this context. diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index 11b35bf..b00928a 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc @@ -41,6 +41,7 @@ #include "base/unguessable_token.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/service/image_factory.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/scheduler.h" @@ -50,6 +51,7 @@ #include "gpu/ipc/service/gles2_command_buffer_stub.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "gpu/ipc/service/image_decode_accelerator_stub.h" #include "gpu/ipc/service/raster_command_buffer_stub.h" #include "gpu/ipc/service/webgpu_command_buffer_stub.h" @@ -541,6 +543,7 @@ GpuChannel::GpuChannel( task_runner_(task_runner), io_task_runner_(io_task_runner), share_group_(share_group), + image_manager_(new gles2::ImageManager()), is_gpu_host_(is_gpu_host), filter_(base::MakeRefCounted( this, @@ -1078,4 +1081,22 @@ uint64_t GpuChannel::GetMemoryUsage() const { return size; } +scoped_refptr GpuChannel::CreateImageForGpuMemoryBuffer( + gfx::GpuMemoryBufferHandle handle, + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane, + SurfaceHandle surface_handle) { + GpuChannelManager* manager = gpu_channel_manager(); + if (!manager->gpu_memory_buffer_factory()) + return nullptr; + + // TODO(b/220336463): plumb the right color space. + return manager->gpu_memory_buffer_factory() + ->AsImageFactory() + ->CreateImageForGpuMemoryBuffer(std::move(handle), size, format, + gfx::ColorSpace(), plane, client_id_, + surface_handle); +} + } // namespace gpu diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h index 49f643b..c877b7b 100644 --- a/gpu/ipc/service/gpu_channel.h +++ b/gpu/ipc/service/gpu_channel.h @@ -36,6 +36,7 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_image.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gpu_preference.h" @@ -104,6 +105,8 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener, SyncPointManager* sync_point_manager() const { return sync_point_manager_; } + gles2::ImageManager* image_manager() const { return image_manager_.get(); } + const scoped_refptr& task_runner() const { return task_runner_; } @@ -155,6 +158,13 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener, uint64_t GetMemoryUsage() const; + scoped_refptr CreateImageForGpuMemoryBuffer( + gfx::GpuMemoryBufferHandle handle, + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferPlane plane, + SurfaceHandle surface_handle); + // Executes a DeferredRequest that was previously received and has now been // scheduled by the scheduler. void ExecuteDeferredRequest(mojom::DeferredRequestParamsPtr params); @@ -285,6 +295,7 @@ class GPU_IPC_SERVICE_EXPORT GpuChannel : public IPC::Listener, // process use. scoped_refptr share_group_; + std::unique_ptr image_manager_; std::unique_ptr shared_image_stub_; const bool is_gpu_host_; diff --git a/ui/gl/gl_image.cc b/ui/gl/gl_image.cc index 18834f4..fca4990 100644 --- a/ui/gl/gl_image.cc +++ b/ui/gl/gl_image.cc @@ -67,6 +67,12 @@ bool GLImage::BindTexImage(unsigned target) { return false; } +bool GLImage::BindTexImageWithInternalformat(unsigned target, + unsigned internalformat) { + NOTREACHED(); + return false; +} + void GLImage::ReleaseTexImage(unsigned target) { NOTREACHED(); } diff --git a/ui/gl/gl_image.h b/ui/gl/gl_image.h index c7b3d98..1c65bcb 100644 --- a/ui/gl/gl_image.h +++ b/ui/gl/gl_image.h @@ -73,6 +73,13 @@ class GL_EXPORT GLImage : public base::RefCounted { // It is valid for an implementation to always return false. virtual bool BindTexImage(unsigned target); + // Bind image to texture currently bound to |target|, forcing the texture's + // internal format to the specified one. This is a feature not available on + // all platforms. Returns true on success. It is valid for an implementation + // to always return false. + virtual bool BindTexImageWithInternalformat(unsigned target, + unsigned internalformat); + // Release image from texture currently bound to |target|. virtual void ReleaseTexImage(unsigned target); -- 2.7.4 From f5520c6619ee217bbdfe45c0f6ef3b0ae68a0b67 Mon Sep 17 00:00:00 2001 From: Suhaspoornachandra Date: Wed, 11 Jan 2023 10:23:28 +0530 Subject: [PATCH 08/16] [M108 Migration][STT] Speech bring up. Refrence: https://review.tizen.org/gerrit/c/274769/ https://review.tizen.org/gerrit/c/275686/ Change-Id: Ic439f156dc8804d7d2ad7eed59f3bd550153623a Signed-off-by: Suhaspoornachandra --- content/browser/browser_interface_binders.cc | 2 + content/browser/browser_main_loop.cc | 13 +- content/browser/browser_main_loop.h | 8 +- .../speech/speech_recognition_dispatcher_host.cc | 9 + .../speech/speech_recognition_manager_impl.cc | 15 +- .../speech/speech_recognition_manager_impl.h | 12 + content/browser/speech/speech_recognizer.h | 8 + packaging/chromium-efl.spec | 2 + tizen_src/build/BUILD.gn | 32 ++ tizen_src/build/config/BUILD.gn | 3 + tizen_src/build/config/tizen_features.gni | 1 + tizen_src/build/gn_chromiumefl.sh | 1 + .../chromium_impl/content/browser/browser_efl.gni | 22 + .../browser/speech/speech_recognizer_impl_tizen.cc | 533 +++++++++++++++++++++ .../browser/speech/speech_recognizer_impl_tizen.h | 93 ++++ .../tizen_speech_recognition_manager_delegate.cc | 37 ++ .../tizen_speech_recognition_manager_delegate.h | 41 ++ .../efl_integration/content_browser_client_efl.cc | 11 + .../efl_integration/content_browser_client_efl.h | 10 + 19 files changed, 846 insertions(+), 7 deletions(-) create mode 100644 tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc create mode 100644 tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h create mode 100644 tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc create mode 100644 tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index adac0a4..541cf90 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc @@ -737,10 +737,12 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) { map->Add( base::BindRepeating(&BindSharedWorkerConnector, base::Unretained(host))); +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) map->Add( base::BindRepeating(&SpeechRecognitionDispatcherHost::Create, host->GetProcess()->GetID(), host->GetRoutingID()), GetIOThreadTaskRunner({})); +#endif map->Add(base::BindRepeating( &RenderFrameHostImpl::GetSpeechSynthesis, base::Unretained(host))); diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index eedf4ba..420eca0 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -87,7 +87,6 @@ #include "content/browser/screenlock_monitor/screenlock_monitor.h" #include "content/browser/screenlock_monitor/screenlock_monitor_device_source.h" #include "content/browser/sms/sms_provider.h" -#include "content/browser/speech/speech_recognition_manager_impl.h" #include "content/browser/speech/tts_controller_impl.h" #include "content/browser/startup_data_impl.h" #include "content/browser/startup_task_runner.h" @@ -149,6 +148,10 @@ #include "ui/gfx/font_render_params.h" #include "ui/gfx/switches.h" +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +#include "content/browser/speech/speech_recognition_manager_impl.h" +#endif + #if defined(USE_AURA) || BUILDFLAG(IS_MAC) #include "content/browser/compositor/image_transport_factory.h" #endif @@ -1111,14 +1114,14 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:MidiService"); midi_service_->Shutdown(); } - +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:SpeechRecognitionManager"); io_thread_->task_runner()->DeleteSoon( FROM_HERE, speech_recognition_manager_.release()); } - +#endif TtsControllerImpl::GetInstance()->Shutdown(); memory_pressure_monitor_.reset(); @@ -1358,14 +1361,14 @@ void BrowserMainLoop::PostCreateThreadsImpl() { media_stream_manager_ = std::make_unique(audio_system_.get()); } - +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) { TRACE_EVENT0("startup", "BrowserMainLoop::PostCreateThreads:InitSpeechRecognition"); speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl( audio_system_.get(), media_stream_manager_.get())); } - +#endif { TRACE_EVENT0("startup", "BrowserMainLoop::PostCreateThreads::InitUserInputMonitor"); diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index 5e2ef10..acc602d 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h @@ -93,11 +93,15 @@ class MediaStreamManager; class SaveFileManager; class ScreenlockMonitor; class SmsProvider; -class SpeechRecognitionManagerImpl; + class StartupTaskRunner; class TracingControllerImpl; struct MainFunctionParams; +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +class SpeechRecognitionManagerImpl; +#endif + namespace responsiveness { class Watcher; } // namespace responsiveness @@ -367,8 +371,10 @@ class CONTENT_EXPORT BrowserMainLoop { std::unique_ptr midi_service_; +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) // Must be deleted on the IO thread. std::unique_ptr speech_recognition_manager_; +#endif #if BUILDFLAG(IS_WIN) std::unique_ptr system_message_window_; diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc index bf5d858..f322ba6 100644 --- a/content/browser/speech/speech_recognition_dispatcher_host.cc +++ b/content/browser/speech/speech_recognition_dispatcher_host.cc @@ -121,6 +121,15 @@ void SpeechRecognitionDispatcherHost::StartRequestOnUI( DCHECK_NE(embedder_render_frame_id, MSG_ROUTING_NONE); } +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + if (SpeechRecognitionManagerImpl::GetInstance()) { + Evas_Object* parent_view = + static_cast(web_contents->GetEflNativeView()); + Evas* evas = evas_object_evas_get(parent_view); + SpeechRecognitionManagerImpl::GetInstance()->SetEvas(evas); + } +#endif + bool filter_profanities = SpeechRecognitionManagerImpl::GetInstance() && SpeechRecognitionManagerImpl::GetInstance()->delegate() && diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index 0fdb61f..007f645 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc @@ -45,6 +45,10 @@ #include "content/browser/speech/speech_recognizer_impl_android.h" #endif +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) && BUILDFLAG(IS_EFL) +#include "content/browser/speech/speech_recognizer_impl_tizen.h" +#endif + namespace content { SpeechRecognitionManager* SpeechRecognitionManager::manager_for_tests_; @@ -180,7 +184,7 @@ int SpeechRecognitionManagerImpl::CreateSession( session->config = config; session->context = config.initial_context; -#if !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_EFL) // A SpeechRecognitionEngine (and corresponding Config) is required only // when using SpeechRecognizerImpl, which performs the audio capture and // endpointing in the browser. This is not the case of Android where, not @@ -211,6 +215,15 @@ int SpeechRecognitionManagerImpl::CreateSession( session->recognizer = new SpeechRecognizerImpl( this, audio_system_, session_id, config.continuous, config.interim_results, google_remote_engine); +#elif BUILDFLAG(IS_EFL) +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) + session->recognizer = new SpeechRecognizerImplTizen(this, session_id); +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + session->recognizer->SetEvas(evas_); +#endif +#else + NOTREACHED(); +#endif #else session->recognizer = new SpeechRecognizerImplAndroid(this, session_id); #endif diff --git a/content/browser/speech/speech_recognition_manager_impl.h b/content/browser/speech/speech_recognition_manager_impl.h index 9f26103..6f1b15e 100644 --- a/content/browser/speech/speech_recognition_manager_impl.h +++ b/content/browser/speech/speech_recognition_manager_impl.h @@ -19,6 +19,10 @@ #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-forward.h" #include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h" +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) +#include +#endif + namespace media { class AudioSystem; } @@ -89,6 +93,10 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl SpeechRecognitionManagerDelegate* delegate() const { return delegate_.get(); } +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + void SetEvas(Evas* evas) { evas_ = evas; } +#endif + protected: // BrowserMainLoop is the only one allowed to instantiate this class. friend class BrowserMainLoop; @@ -185,6 +193,10 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl std::unique_ptr delegate_; const int requester_id_; +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + Evas* evas_ = nullptr; +#endif + // Used for posting asynchronous tasks (on the IO thread) without worrying // about this class being destroyed in the meanwhile (due to browser shutdown) // since tasks pending on a destroyed WeakPtr are automatically discarded. diff --git a/content/browser/speech/speech_recognizer.h b/content/browser/speech/speech_recognizer.h index 681691d..86822c8 100644 --- a/content/browser/speech/speech_recognizer.h +++ b/content/browser/speech/speech_recognizer.h @@ -10,6 +10,10 @@ #include "base/memory/ref_counted.h" #include "content/common/content_export.h" +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) +#include +#endif + namespace content { class SpeechRecognitionEventListener; @@ -32,6 +36,10 @@ class CONTENT_EXPORT SpeechRecognizer virtual bool IsActive() const = 0; virtual bool IsCapturingAudio() const = 0; +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + virtual void SetEvas(Evas* evas) {} +#endif + protected: friend class base::RefCountedThreadSafe; diff --git a/packaging/chromium-efl.spec b/packaging/chromium-efl.spec index 01e43e7..baa95b3 100644 --- a/packaging/chromium-efl.spec +++ b/packaging/chromium-efl.spec @@ -106,6 +106,7 @@ BuildRequires: pkgconfig(nss) BuildRequires: pkgconfig(scim) BuildRequires: pkgconfig(security-manager) BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(stt) BuildRequires: pkgconfig(tts) BuildRequires: pkgconfig(ui-gadget-1) BuildRequires: pkgconfig(vconf) @@ -141,6 +142,7 @@ BuildRequires: pkgconfig(xtst) %endif %if "%{?tizen_profile_name}" == "tv" +BuildRequires: pkgconfig(capi-stt-wrapper-tv) BuildRequires: pkgconfig(vd-win-util) %endif diff --git a/tizen_src/build/BUILD.gn b/tizen_src/build/BUILD.gn index 3fbf271..ce7e0ba 100644 --- a/tizen_src/build/BUILD.gn +++ b/tizen_src/build/BUILD.gn @@ -579,6 +579,38 @@ config("tts-public") { } } +config("capi-stt-wrapper-tv") { + if (tizen_product_tv) { + ldflags = [ "-lcapi-stt-wrapper-tv" ] + } +} + +tizen_pkg_config("libcapi-stt-wrapper-tv") { + packages = [] + if (tizen_product_tv) { + packages = [ "capi-stt-wrapper-tv" ] + } +} + +config("stt") { + if (is_tizen) { + ldflags = [ "-lstt" ] + } +} + +tizen_pkg_config("libstt") { + packages = [] + if (is_tizen) { + packages = [ "stt" ] + } +} + +config("stt-public") { + if (is_tizen) { + cflags = [ "-stt" ] + } +} + config("vconf") { if (is_tizen) { ldflags = [ "-lvconf" ] diff --git a/tizen_src/build/config/BUILD.gn b/tizen_src/build/config/BUILD.gn index ed0f2b7..3b4e9c1 100644 --- a/tizen_src/build/config/BUILD.gn +++ b/tizen_src/build/config/BUILD.gn @@ -39,6 +39,9 @@ config("tizen_feature_flags") { "TIZEN_MULTIMEDIA_USE_CAPI_AUDIO_IO", ] } + if (tizen_web_speech_recognition) { + defines += [ "TIZEN_WEB_SPEECH_RECOGNITION" ] + } # TODO: There are X11 dependencies in following condition. # The files need to be implemented based on Wayland. diff --git a/tizen_src/build/config/tizen_features.gni b/tizen_src/build/config/tizen_features.gni index 94b85b2..5e1ec9a 100644 --- a/tizen_src/build/config/tizen_features.gni +++ b/tizen_src/build/config/tizen_features.gni @@ -46,6 +46,7 @@ declare_args() { tizen_multimedia_support = false tizen_multimedia = false tizen_tbm_support = false + tizen_web_speech_recognition = false } if (is_tizen && tizen_multimedia_support) { diff --git a/tizen_src/build/gn_chromiumefl.sh b/tizen_src/build/gn_chromiumefl.sh index d2e392a..fd9662f 100755 --- a/tizen_src/build/gn_chromiumefl.sh +++ b/tizen_src/build/gn_chromiumefl.sh @@ -221,6 +221,7 @@ add_tizen_flags() { # FIXME: http://165.213.149.170/jira/browse/TWF-610 ADDITIONAL_GN_PARAMETERS+="tizen_multimedia=true proprietary_codecs=true + tizen_web_speech_recognition=true tizen_tbm_support=false " } diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index b6a1022..2586fa5 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -52,6 +52,19 @@ if (tizen_multimedia_support) { ] } +if (tizen_web_speech_recognition) { + external_content_browser_efl_configs += [ + "//tizen_src/build:stt", + "//tizen_src/build:libstt", + ] + if (tizen_product_tv) { + external_content_browser_efl_configs += [ + "//tizen_src/build:capi-stt-wrapper-tv", + "//tizen_src/build:libcapi-stt-wrapper-tv", + ] + } +} + ############################################################################## # Dependency ############################################################################## @@ -148,3 +161,12 @@ if (tizen_tbm_support) { "//tizen_src/chromium_impl/content/browser/media/browser_mediapacket_manager.h", ] } + +if (tizen_web_speech_recognition) { + external_content_browser_efl_sources += [ + "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc", + "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h", + "//tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc", + "//tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h", + ] +} diff --git a/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc new file mode 100644 index 0000000..72e2ac0 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc @@ -0,0 +1,533 @@ +// Copyright 2016 Samsung Electronics Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/speech/speech_recognizer_impl_tizen.h" + +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/speech_recognition_event_listener.h" +#include "content/public/browser/speech_recognition_manager.h" +#include "content/public/browser/speech_recognition_session_config.h" +#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h" + +#define RUN_ON_BROWSER_IO_THREAD(METHOD, ...) \ + do { \ + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { \ + GetIOThreadTaskRunner({})->PostTask( \ + FROM_HERE, base::BindOnce(&SpeechRecognizerImplTizen::METHOD, this, \ + ##__VA_ARGS__)); \ + return; \ + } \ + } while (0) + +#define RUN_ON_BROWSER_UI_THREAD(METHOD, ...) \ + do { \ + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { \ + GetUIThreadTaskRunner({})->PostTask( \ + FROM_HERE, base::BindOnce(&SpeechRecognizerImplTizen::METHOD, this, \ + ##__VA_ARGS__)); \ + return; \ + } \ + } while (0) + +#define ENUM_CASE(x) \ + case x: \ + return #x; \ + break + +#if !BUILDFLAG(IS_TIZEN_TV) +#define stt_wrapper_get_error_message stt_get_error_message +#define stt_wrapper_get_state stt_get_state +#define stt_wrapper_destroy stt_destroy +#define stt_wrapper_unset_error_cb stt_unset_error_cb +#define stt_wrapper_unset_state_changed_cb stt_unset_state_changed_cb +#define stt_wrapper_unset_recognition_result_cb stt_unset_recognition_result_cb +#define stt_wrapper_unprepare stt_unprepare +#define stt_wrapper_cancel stt_cancel +#define stt_wrapper_start stt_start +#define stt_wrapper_set_error_cb stt_set_error_cb +#define stt_wrapper_set_state_changed_cb stt_set_state_changed_cb +#define stt_wrapper_set_recognition_result_cb stt_set_recognition_result_cb +#define stt_wrapper_create stt_create +#define stt_wrapper_stop stt_stop +#define stt_wrapper_prepare stt_prepare +#define stt_wrapper_foreach_supported_languages stt_foreach_supported_languages +#endif + +namespace { + +// Replace hyphen "-" in language with underscore "_". CAPI does not +// support language string with hyphen. Example: en-US -> en_US. +// change character case. Example: en_us -> en_US. +std::string GetLanguageString(const std::string& language) { + std::string ret(language); + std::replace(ret.begin(), ret.end(), '-', '_'); + std::transform(ret.begin(), ret.begin() + 2, ret.begin(), ::tolower); + std::transform(ret.end() - 2, ret.end(), ret.end() - 2, ::toupper); + return ret; +} + +const char* GetErrorString(stt_error_e error) { + switch (error) { + ENUM_CASE(STT_ERROR_NONE); + ENUM_CASE(STT_ERROR_OUT_OF_MEMORY); + ENUM_CASE(STT_ERROR_IO_ERROR); + ENUM_CASE(STT_ERROR_INVALID_PARAMETER); + ENUM_CASE(STT_ERROR_TIMED_OUT); + ENUM_CASE(STT_ERROR_RECORDER_BUSY); + ENUM_CASE(STT_ERROR_OUT_OF_NETWORK); + ENUM_CASE(STT_ERROR_PERMISSION_DENIED); + ENUM_CASE(STT_ERROR_NOT_SUPPORTED); + ENUM_CASE(STT_ERROR_INVALID_STATE); + ENUM_CASE(STT_ERROR_INVALID_LANGUAGE); + ENUM_CASE(STT_ERROR_ENGINE_NOT_FOUND); + ENUM_CASE(STT_ERROR_OPERATION_FAILED); + ENUM_CASE(STT_ERROR_NOT_SUPPORTED_FEATURE); + ENUM_CASE(STT_ERROR_RECORDING_TIMED_OUT); + ENUM_CASE(STT_ERROR_NO_SPEECH); + ENUM_CASE(STT_ERROR_IN_PROGRESS_TO_READY); + ENUM_CASE(STT_ERROR_IN_PROGRESS_TO_RECORDING); + ENUM_CASE(STT_ERROR_IN_PROGRESS_TO_PROCESSING); + ENUM_CASE(STT_ERROR_SERVICE_RESET); + }; + + NOTREACHED() << "Invalid stt_error_e! (" << error << ")"; + return ""; +} + +} // namespace + +namespace content { + +blink::mojom::SpeechRecognitionErrorCode GetErrorCode(stt_error_e reason) { + switch (reason) { + case STT_ERROR_NONE: + return blink::mojom::SpeechRecognitionErrorCode::kNone; + case STT_ERROR_NO_SPEECH: + return blink::mojom::SpeechRecognitionErrorCode::kNoSpeech; + case STT_ERROR_RECORDING_TIMED_OUT: + case STT_ERROR_IO_ERROR: + case STT_ERROR_RECORDER_BUSY: + return blink::mojom::SpeechRecognitionErrorCode::kAudioCapture; + case STT_ERROR_OUT_OF_NETWORK: + return blink::mojom::SpeechRecognitionErrorCode::kNetwork; + case STT_ERROR_PERMISSION_DENIED: + return blink::mojom::SpeechRecognitionErrorCode::kNotAllowed; + case STT_ERROR_INVALID_LANGUAGE: + return blink::mojom::SpeechRecognitionErrorCode::kLanguageNotSupported; + case STT_ERROR_NOT_SUPPORTED: + return blink::mojom::SpeechRecognitionErrorCode::kServiceNotAllowed; + default: + return blink::mojom::SpeechRecognitionErrorCode::kAborted; + } +} + +SpeechRecognizerImplTizen::SpeechRecognizerImplTizen( + SpeechRecognitionEventListener* listener, + int session_id) + : SpeechRecognizer(listener, session_id) {} + +SpeechRecognizerImplTizen::~SpeechRecognizerImplTizen() { + base::AutoLock auto_lock(abort_lock_); + if (!handle_ || is_aborted_) + return; + + Destroy(); +} + +void SpeechRecognizerImplTizen::StartRecognition(const std::string& device_id) { + SpeechRecognitionSessionConfig config = + SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id()); + + recognition_type_ = config.interim_results ? STT_RECOGNITION_TYPE_FREE_PARTIAL + : STT_RECOGNITION_TYPE_FREE; + continuous_ = config.continuous; + + if (config.language.empty()) { + LOG(ERROR) << "stt session #" << session_id() + << " language config is empty! Use 'en_US'"; + is_lang_supported_ = true; + language_ = "en_US"; + } else { + language_ = GetLanguageString(config.language); + } + + // Initialize and prepare stt in UI thread + Prepare(); +} + +void SpeechRecognizerImplTizen::Prepare() { + RUN_ON_BROWSER_UI_THREAD(Prepare); + + if (!Initialize()) + return; + + stt_wrapper_foreach_supported_languages(handle_, &OnSupportedLanguages, this); + +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + int err = stt_wrapper_prepare_with_evas(handle_, evas_); +#else + int err = stt_wrapper_prepare(handle_); +#endif + if (STT_ERROR_NONE != err) + HandleSttError(static_cast(err), FROM_HERE); +} + +void SpeechRecognizerImplTizen::AbortRecognition() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + EndRecognition(FROM_HERE); +} + +void SpeechRecognizerImplTizen::StopAudioCapture() { + RUN_ON_BROWSER_UI_THREAD(StopAudioCapture); + continuous_ = false; + + if (GetCurrentState() != STT_STATE_RECORDING) + return; + + int err = stt_wrapper_stop(handle_); + if (STT_ERROR_NONE != err) + HandleSttError(static_cast(err), FROM_HERE); +} + +bool SpeechRecognizerImplTizen::IsActive() const { + return GetCurrentState() > STT_STATE_CREATED ? true : false; +} + +bool SpeechRecognizerImplTizen::IsCapturingAudio() const { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + return GetCurrentState() >= STT_STATE_RECORDING ? true : false; +} + +bool SpeechRecognizerImplTizen::Initialize() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + is_aborted_ = false; + + int err = stt_wrapper_create(&handle_); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + + err = stt_wrapper_set_recognition_result_cb(handle_, &OnRecognitionResult, + this); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + + err = stt_wrapper_set_state_changed_cb(handle_, &OnStateChange, this); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + + err = stt_wrapper_set_error_cb(handle_, &OnError, this); + if (err != STT_ERROR_NONE) { + HandleSttError(static_cast(err), FROM_HERE); + return false; + } + return true; +} + +void SpeechRecognizerImplTizen::StartInternal() { + RUN_ON_BROWSER_UI_THREAD(StartInternal); + + LOG(INFO) << "stt session #" << session_id() + << " language used : " << language_.c_str() + << " type : " << recognition_type_; + if (!is_lang_supported_) { + HandleSttError(STT_ERROR_INVALID_LANGUAGE, FROM_HERE); + return; + } + + int err = stt_wrapper_start(handle_, language_.c_str(), recognition_type_); + if (STT_ERROR_NONE != err) + HandleSttError(static_cast(err), FROM_HERE); +} + +void SpeechRecognizerImplTizen::Destroy() { + RUN_ON_BROWSER_UI_THREAD(Destroy); + if (!handle_) + return; + + is_lang_supported_ = false; + continuous_ = false; + if (GetCurrentState() >= STT_STATE_RECORDING) + stt_wrapper_cancel(handle_); + if (GetCurrentState() == STT_STATE_READY) { +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + stt_wrapper_unprepare_with_evas(handle_, evas_); +#else + stt_wrapper_unprepare(handle_); +#endif + } + if (GetCurrentState() == STT_STATE_CREATED) { + stt_wrapper_unset_recognition_result_cb(handle_); + stt_wrapper_unset_state_changed_cb(handle_); + stt_wrapper_unset_error_cb(handle_); + } + + // Valid states to be called: created, Ready, Recording, Processing +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + int err = stt_wrapper_destroy_with_evas(handle_, evas_); +#else + int err = stt_wrapper_destroy(handle_); +#endif + if (err != STT_ERROR_NONE) + LOG(ERROR) << "stt session #" << session_id() << " stt_destroy failed with " + << GetErrorString(static_cast(err)); + else + handle_ = nullptr; +} + +bool SpeechRecognizerImplTizen::ShouldStartRecognition() const { + return GetCurrentState() >= STT_STATE_READY; +} + +// There is no default stt state. So use |STT_STATE_CREATED| +// This will work as we will use it to determine audio capturing. +stt_state_e SpeechRecognizerImplTizen::GetCurrentState() const { + if (!handle_ || is_aborted_) + return STT_STATE_CREATED; + + stt_state_e state = STT_STATE_CREATED; + int err = stt_wrapper_get_state(handle_, &state); + if (err != STT_ERROR_NONE) + LOG(ERROR) << "stt session #" << session_id() << " stt_get_state FAILED!"; + return state; +} + +void SpeechRecognizerImplTizen::RecognitionResults( + bool no_speech, + std::vector& results) { + { + base::AutoLock auto_lock(abort_lock_); + if (is_aborted_) { + LOG(INFO) << "stt engine is in error state"; + return; + } + } + + if (no_speech && !continuous_) { + HandleSttError(STT_ERROR_NO_SPEECH, FROM_HERE); + return; + } + + listener()->OnRecognitionResults(session_id(), results); +} + +void SpeechRecognizerImplTizen::HandleSttError(stt_error_e error, + const base::Location& location) { + RUN_ON_BROWSER_IO_THREAD(HandleSttError, error, location); + LOG(ERROR) << "stt session #" << session_id() << " error " + << GetErrorString(error) << " from " << location.function_name() + << "(" << location.line_number() << ")"; + { + base::AutoLock auto_lock(abort_lock_); + if (!handle_ || is_aborted_) + return; + } + + blink::mojom::SpeechRecognitionError recognition_error; + recognition_error.code = GetErrorCode(static_cast(error)); + recognition_error.details = blink::mojom::SpeechAudioErrorDetails::kNone; + + listener()->OnRecognitionError(session_id(), recognition_error); + EndRecognition(FROM_HERE); +} + +void SpeechRecognizerImplTizen::HandleSttResultError(const std::string error) { + RUN_ON_BROWSER_IO_THREAD(HandleSttResultError, error); + LOG(ERROR) << "stt session #" << session_id() << " no result as " << error; + + { + base::AutoLock auto_lock(abort_lock_); + if (!handle_ || is_aborted_) + return; + } + + if (error == STT_RESULT_MESSAGE_ERROR_TOO_SOON || + error == STT_RESULT_MESSAGE_ERROR_TOO_SHORT || + error == STT_RESULT_MESSAGE_ERROR_TOO_LONG || + error == STT_RESULT_MESSAGE_ERROR_TOO_QUIET || + error == STT_RESULT_MESSAGE_ERROR_TOO_LOUD || + error == STT_RESULT_MESSAGE_ERROR_TOO_FAST) { + blink::mojom::SpeechRecognitionError recognition_error; + recognition_error.code = blink::mojom::SpeechRecognitionErrorCode::kNoMatch; + recognition_error.details = blink::mojom::SpeechAudioErrorDetails::kNone; + listener()->OnRecognitionError(session_id(), recognition_error); + } +} + +void SpeechRecognizerImplTizen::RecognitionStarted() { + RUN_ON_BROWSER_IO_THREAD(RecognitionStarted); + + listener()->OnAudioStart(session_id()); + listener()->OnSoundStart(session_id()); + listener()->OnRecognitionStart(session_id()); +} + +void SpeechRecognizerImplTizen::AudioCaptureEnd() { + RUN_ON_BROWSER_IO_THREAD(AudioCaptureEnd); + + listener()->OnSoundEnd(session_id()); + listener()->OnAudioEnd(session_id()); +} + +void SpeechRecognizerImplTizen::EndRecognition(const base::Location& location) { + RUN_ON_BROWSER_IO_THREAD(EndRecognition, location); + + { + base::AutoLock auto_lock(abort_lock_); + if (is_aborted_) + return; + + is_aborted_ = true; + } + + LOG(INFO) << "stt session #" << session_id() + << " ending recognition called from " << location.function_name() + << "(" << location.line_number() << ")"; + + if (GetCurrentState() == STT_STATE_RECORDING) + AudioCaptureEnd(); + + listener()->OnRecognitionEnd(session_id()); + Destroy(); +} + +bool SpeechRecognizerImplTizen::OnSupportedLanguages(stt_h stt, + const char* language, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return false; + + if (!speech->language_.compare(language)) { + speech->is_lang_supported_ = true; + return false; + } + + return true; +} + +void SpeechRecognizerImplTizen::OnRecognitionResult(stt_h stt, + stt_result_event_e event, + const char** data, + int data_count, + const char* msg, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return; + + if (event == STT_RESULT_EVENT_ERROR) { + speech->HandleSttResultError(msg); + return; + } + + bool no_speech = true; + blink::mojom::SpeechRecognitionResultPtr result = + blink::mojom::SpeechRecognitionResult::New(); + for (int i = 0; i < data_count; i++) { + if (data[i] && data[i][0] != ' ') { + no_speech = false; + std::u16string utterance; + base::UTF8ToUTF16(data[i], strlen(data[i]), &utterance); + result->hypotheses.push_back( + blink::mojom::SpeechRecognitionHypothesis::New(utterance, 1.0)); + } + } + + result->is_provisional = + (event == STT_RESULT_EVENT_FINAL_RESULT) ? false : true; + + std::vector results; + results.push_back(std::move(result)); + + speech->RecognitionResults(no_speech, results); +} + +void SpeechRecognizerImplTizen::OnStateChange(stt_h stt, + stt_state_e previous, + stt_state_e current, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return; + + LOG(INFO) << "stt session #" << speech->session_id() + << " state change called. Previous : " << previous + << " Current : " << current; + + switch (current) { + case STT_STATE_READY: + switch (previous) { + case STT_STATE_CREATED: + speech->StartInternal(); + break; + case STT_STATE_RECORDING: + if (!speech->is_aborted_) + speech->HandleSttError(STT_ERROR_NO_SPEECH, FROM_HERE); + break; + case STT_STATE_PROCESSING: + // If continuous attribute is true recognition shouldn't stop after + // receiving one final result. So start the recognition again. + if (speech->continuous_) + speech->StartInternal(); + // |stt_recognition_result_cb| is called even when a partial result is + // obtained. So, need to end recognition only when the state change + // is confirmed. + else + speech->EndRecognition(FROM_HERE); + break; + default: + break; + } + break; + case STT_STATE_RECORDING: + speech->RecognitionStarted(); + break; + case STT_STATE_PROCESSING: + speech->AudioCaptureEnd(); + break; + default: + break; + } +} + +void SpeechRecognizerImplTizen::OnError(stt_h stt, + stt_error_e reason, + void* user_data) { + SpeechRecognizerImplTizen* speech = + static_cast(user_data); + if (!speech) + return; +#if BUILDFLAG(IS_TIZEN_TV) + char* error_msg = nullptr; + const std::string no_speech_msg = "voice_engine.error.no_speech"; + int ret = stt_wrapper_get_error_message(stt, &error_msg); + if (ret == STT_ERROR_NONE) { + LOG(INFO) << "stt session #" << speech->session_id() + << "err msg : " << error_msg; + if (!no_speech_msg.compare(error_msg)) + reason = STT_ERROR_NO_SPEECH; + if (error_msg) + free(error_msg); + } else { + LOG(ERROR) << "stt session #" << speech->session_id() + << " stt_wrapper_get_error_message:" + << GetErrorString(static_cast(ret)); + } +#endif + speech->HandleSttError(reason, FROM_HERE); +} + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h new file mode 100644 index 0000000..1cb47ce --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.h @@ -0,0 +1,93 @@ +// Copyright 2016 Samsung Electronics Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SPEECH_SPEECH_RECOGNIZER_IMPL_TIZEN_ +#define CONTENT_BROWSER_SPEECH_SPEECH_RECOGNIZER_IMPL_TIZEN_ + +#include + +#include "base/location.h" +#include "content/browser/speech/speech_recognizer.h" +#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h" + +#if BUILDFLAG(IS_TIZEN_TV) +#include +#if defined(USE_WAYLAND) +#include +#endif +#else +#include +#endif + +namespace content { + +class CONTENT_EXPORT SpeechRecognizerImplTizen : public SpeechRecognizer { + public: + SpeechRecognizerImplTizen(SpeechRecognitionEventListener* listener, + int session_id); + + // SpeechRecognizer methods. + void StartRecognition(const std::string& device_id) override; + void AbortRecognition() override; + void StopAudioCapture() override; + bool IsActive() const override; + bool IsCapturingAudio() const override; +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + void SetEvas(Evas* evas) override { evas_ = evas; } +#endif + + private: + SpeechRecognizerImplTizen(const SpeechRecognizerImplTizen&) = delete; + SpeechRecognizerImplTizen& operator=(const SpeechRecognizerImplTizen&) = + delete; + + ~SpeechRecognizerImplTizen() override; + + void Prepare(); + bool Initialize(); + void StartInternal(); + void Destroy(); + stt_state_e GetCurrentState() const; + bool ShouldStartRecognition() const; + void RecognitionResults( + bool no_speech, + std::vector& results); + void HandleSttError(stt_error_e error, const base::Location& location); + void HandleSttResultError(const std::string error); + void RecognitionStarted(); + void AudioCaptureEnd(); + void EndRecognition(const base::Location& location); + + // Callbacks + static bool OnSupportedLanguages(stt_h stt, + const char* language, + void* user_data); + static void OnRecognitionResult(stt_h stt, + stt_result_event_e event, + const char** data, + int data_count, + const char* msg, + void* user_data); + static void OnStateChange(stt_h stt, + stt_state_e previous, + stt_state_e current, + void* user_data); + static void OnError(stt_h stt, stt_error_e reason, void* user_data); + +#if BUILDFLAG(IS_TIZEN_TV) && defined(USE_WAYLAND) + Evas* evas_ = nullptr; +#endif + + stt_h handle_ = nullptr; + std::string language_; + bool is_lang_supported_ = false; + bool continuous_ = false; + const char* recognition_type_ = ""; + bool is_aborted_ = false; + base::Lock abort_lock_; +}; + +} // namespace content + +#endif // BROWSER_SPEECH_SPEECH_RECOGNIZER_IMPL_TIZEN_ diff --git a/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc new file mode 100644 index 0000000..8435e66 --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.cc @@ -0,0 +1,37 @@ +// Copyright 2016 Samsung Electronics Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/speech/tizen_speech_recognition_manager_delegate.h" + +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" + +#if BUILDFLAG(IS_TIZEN_TV) +#include "tizen_src/ewk/efl_integration/common/application_type.h" +#endif + +namespace content { + +void TizenSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( + int session_id, + base::OnceCallback callback) { + // For tizen, we expect speech recognition to happen when requested. + + // Therefore we simply authorize it by calling back with is_allowed=true. The + // first parameter, ask_user, is set to false because we don't want to prompt + // the user for permission with an infobar. + + // In browser, a pop-up for permission to use microphone will show up. + // In web app, however, the user agrees on the access to microphone + // when the app is installed on device. So the pop-up will not show up. +#if BUILDFLAG(IS_TIZEN_TV) && defined(WRT_BRINGUP) + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), IsTIZENWRT(), false)); +#else + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false, true)); +#endif +} + +} // namespace content diff --git a/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h new file mode 100644 index 0000000..6ac79bb --- /dev/null +++ b/tizen_src/chromium_impl/content/browser/speech/tizen_speech_recognition_manager_delegate.h @@ -0,0 +1,41 @@ +// Copyright 2016 Samsung Electronics Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SPEECH_TIZEN_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ +#define CONTENT_BROWSER_SPEECH_TIZEN_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ + +#include "base/bind.h" +#include "content/public/browser/speech_recognition_manager_delegate.h" + +namespace content { + +class SpeechRecognitionEventListener; +// This delegate is used by the speech recognition manager to +// check for permission to record audio. For tizen, we always authorize +// speech recognition. +class TizenSpeechRecognitionManagerDelegate + : public SpeechRecognitionManagerDelegate { + public: + TizenSpeechRecognitionManagerDelegate() {} + ~TizenSpeechRecognitionManagerDelegate() override {} + + private: + TizenSpeechRecognitionManagerDelegate( + const TizenSpeechRecognitionManagerDelegate&) = delete; + TizenSpeechRecognitionManagerDelegate& operator=( + const TizenSpeechRecognitionManagerDelegate&) = delete; + + void CheckRecognitionIsAllowed( + int session_id, + base::OnceCallback callback) + override; + SpeechRecognitionEventListener* GetEventListener() override { + return nullptr; + } + bool FilterProfanities(int render_process_id) override { return false; } +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SPEECH_TIZEN_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc index 7b36d0f..23882ee 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -41,6 +41,10 @@ #include "private/ewk_notification_private.h" +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +#include "content/browser/speech/tizen_speech_recognition_manager_delegate.h" +#endif + using web_contents_utils::WebContentsFromFrameID; using web_contents_utils::WebContentsFromViewID; using web_contents_utils::WebViewFromWebContents; @@ -250,6 +254,13 @@ bool ContentBrowserClientEfl::HasErrorPage(int http_status_code) { error_page::Error::kHttpErrorDomain, http_status_code); } +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +SpeechRecognitionManagerDelegate* +ContentBrowserClientEfl::CreateSpeechRecognitionManagerDelegate() { + return new TizenSpeechRecognitionManagerDelegate(); +} +#endif + void ContentBrowserClientEfl::AllowCertificateError( WebContents* web_contents, int cert_error, diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.h b/tizen_src/ewk/efl_integration/content_browser_client_efl.h index cef8cb6..7b3f8f1 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.h +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.h @@ -21,6 +21,11 @@ namespace content { class BrowserMainPartsEfl; class NotificationControllerEfl; class SharedURLLoaderFactoryEfl; + +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) +class SpeechRecognitionManagerDelegate; +#endif + class WebContents; class WebContentsView; @@ -59,6 +64,11 @@ class ContentBrowserClientEfl : public ContentBrowserClient { bool opener_suppressed, bool* no_javascript_access) override; +#if defined(TIZEN_WEB_SPEECH_RECOGNITION) + SpeechRecognitionManagerDelegate* CreateSpeechRecognitionManagerDelegate() + override; +#endif + scoped_refptr CreateQuotaPermissionContext() override; bool HasErrorPage(int http_status_code) override; -- 2.7.4 From eb1cfd8dd1dec8e0c312d1245ac19d51935c81ad Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Tue, 24 Jan 2023 12:15:06 +0530 Subject: [PATCH 09/16] [M108 Migration][API] Introduce AddJavascriptInterface for Tizen Introduces AddJavascriptInterface for tizen, adds logs for debugging and support for posting blob type data type when using custom JS msg handler. Additionally, on M108, due to lot of upstream changes in base/values.{h,cc} prototypes, this patch fixes many build errors with respect to conversion of JS types (list, blob, dict etc) to Native types. Reference: https://review.tizen.org/gerrit/273935 Change-Id: Id18d8756919c3730ad991ab2a2ea02f91d64131f Signed-off-by: Gajendra N --- .../renderer_host/render_frame_host_impl.cc | 1 + ipc/ipc_message_start.h | 1 + .../core/frame/local_frame_mojo_handler.cc | 1 + tizen_src/ewk/efl_integration/BUILD.gn | 21 ++ .../gin_native_bound_object.cc | 43 +++ .../javascript_interface/gin_native_bound_object.h | 63 ++++ .../gin_native_bridge_dispatcher_host.cc | 381 +++++++++++++++++++++ .../gin_native_bridge_dispatcher_host.h | 98 ++++++ .../gin_native_bridge_message_filter.cc | 137 ++++++++ .../gin_native_bridge_message_filter.h | 98 ++++++ .../common/gin_native_bridge_errors.cc | 39 +++ .../common/gin_native_bridge_errors.h | 31 ++ .../common/gin_native_bridge_messages.h | 60 ++++ .../common/gin_native_bridge_value.cc | 105 ++++++ .../common/gin_native_bridge_value.h | 56 +++ .../efl_integration/common/message_generator_ewk.h | 3 +- tizen_src/ewk/efl_integration/eweb_view.cc | 31 +- tizen_src/ewk/efl_integration/eweb_view.h | 13 + tizen_src/ewk/efl_integration/public/ewk_view.cc | 39 +++ .../renderer/content_renderer_client_efl.cc | 3 + .../renderer/gin_native_bridge_dispatcher.cc | 120 +++++++ .../renderer/gin_native_bridge_dispatcher.h | 77 +++++ .../renderer/gin_native_bridge_object.cc | 124 +++++++ .../renderer/gin_native_bridge_object.h | 74 ++++ .../renderer/gin_native_bridge_value_converter.cc | 37 ++ .../renderer/gin_native_bridge_value_converter.h | 36 ++ .../gin_native_function_invocation_helper.cc | 108 ++++++ .../gin_native_function_invocation_helper.h | 42 +++ 28 files changed, 1833 insertions(+), 9 deletions(-) create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc create mode 100644 tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc create mode 100644 tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc create mode 100644 tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index c735f4a..a614089 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -2326,6 +2326,7 @@ void RenderFrameHostImpl::ForEachRenderFrameHostImpl( base::FunctionRef on_frame, bool include_speculative) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + LOG(INFO) << __FUNCTION__; if (!include_speculative && (lifecycle_state() == LifecycleStateImpl::kSpeculative || diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h index 8c91037..7758a5f 100644 --- a/ipc/ipc_message_start.h +++ b/ipc/ipc_message_start.h @@ -27,6 +27,7 @@ enum IPCMessageStart { TtsMsgStart, #endif ExtensionWorkerMsgStart, + GinNativeBridgeMsgStart, LastIPCMsgStart // Must come last. }; diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index 4716b95..4dd8501 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc @@ -943,6 +943,7 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestForTests( bool resolve_promises, int32_t world_id, JavaScriptExecuteRequestForTestsCallback callback) { + LOG(INFO) << __FUNCTION__; TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests", TRACE_EVENT_SCOPE_THREAD); diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index c04d0c6..bfbb46a 100755 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -313,6 +313,12 @@ shared_library("chromium-ewk") { "browser/input_picker/color_chooser_efl.h", "browser/input_picker/input_picker.cc", "browser/input_picker/input_picker.h", + "browser/javascript_interface/gin_native_bound_object.cc", + "browser/javascript_interface/gin_native_bound_object.h", + "browser/javascript_interface/gin_native_bridge_dispatcher_host.cc", + "browser/javascript_interface/gin_native_bridge_dispatcher_host.h", + "browser/javascript_interface/gin_native_bridge_message_filter.cc", + "browser/javascript_interface/gin_native_bridge_message_filter.h", "browser/network_service/browser_url_loader_throttle_efl.cc", "browser/network_service/browser_url_loader_throttle_efl.h", "browser/notification/notification_controller_efl.cc", @@ -345,6 +351,11 @@ shared_library("chromium-ewk") { "common/content_switches_efl.cc", "common/content_switches_efl.h", "common/editing_messages.h", + "common/gin_native_bridge_errors.cc", + "common/gin_native_bridge_errors.h", + "common/gin_native_bridge_messages.h", + "common/gin_native_bridge_value.cc", + "common/gin_native_bridge_value.h", "common/hit_test_params.h", "common/message_generator_ewk.cc", "common/message_generator_ewk.h", @@ -549,6 +560,16 @@ shared_library("chromium-ewk") { "renderer/content_renderer_client_efl.h", "renderer/content_settings_client_efl.cc", "renderer/content_settings_client_efl.h", + "renderer/gin_native_bridge_dispatcher.cc", + "renderer/gin_native_bridge_dispatcher.h", + "renderer/gin_native_bridge_object.cc", + "renderer/gin_native_bridge_object.h", + "renderer/gin_native_bridge_value_converter.cc", + "renderer/gin_native_bridge_value_converter.h", + "renderer/gin_native_function_invocation_helper.cc", + "renderer/gin_native_function_invocation_helper.h", + "renderer/plugins/plugin_placeholder_efl.cc", + "renderer/plugins/plugin_placeholder_efl.h", "renderer/print_web_view_helper_efl.cc", "renderer/print_web_view_helper_efl.h", "renderer/render_frame_observer_efl.cc", diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc new file mode 100644 index 0000000..a16ee7a2 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.cc @@ -0,0 +1,43 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/javascript_interface/gin_native_bound_object.h" + +namespace content { + +GinNativeBoundObject::GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name) + : obj_(obj), callback_(callback), name_(name), names_count_(0) {} + +GinNativeBoundObject::GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + const std::set& holders) + : obj_(obj), + callback_(callback), + name_(name), + names_count_(0), + holders_(holders) {} + +// static +GinNativeBoundObject* GinNativeBoundObject::CreateNamed( + Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name) { + return new GinNativeBoundObject(obj, callback, name); +} + +// static +GinNativeBoundObject* GinNativeBoundObject::CreateTransient( + Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + int32_t holder) { + std::set holders; + holders.insert(holder); + return new GinNativeBoundObject(obj, callback, name, holders); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h new file mode 100644 index 0000000..d95658f --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bound_object.h @@ -0,0 +1,63 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BOUND_OBJECT_H_ +#define EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BOUND_OBJECT_H_ + +#include +#include + +#include +#include + +#include "base/memory/ref_counted.h" +#include "public/ewk_view.h" + +namespace content { + +class GinNativeBoundObject + : public base::RefCountedThreadSafe { + public: + typedef int32_t ObjectID; + static GinNativeBoundObject* CreateNamed(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name); + static GinNativeBoundObject* CreateTransient( + Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + int32_t holder); + void AddName() { ++names_count_; } + void RemoveName() { --names_count_; } + Evas_Object* GetView() const { return obj_; } + Ewk_View_Script_Message_Cb CallBack() const { return callback_; } + const char* Name() const { return name_.c_str(); } + + private: + friend class base::RefCountedThreadSafe; + GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name); + GinNativeBoundObject(Evas_Object* obj, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + const std::set& holders); + ~GinNativeBoundObject(){}; + + GinNativeBoundObject(const GinNativeBoundObject&) = delete; + GinNativeBoundObject& operator=(const GinNativeBoundObject&) = delete; + + Evas_Object* obj_; + Ewk_View_Script_Message_Cb callback_; + std::string name_; + + // An object must be kept in retained_object_set_ either if it has + // names or if it has a non-empty holders set. + int names_count_; + std::set holders_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BOUND_OBJECT_H_ diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc new file mode 100644 index 0000000..145925c --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.cc @@ -0,0 +1,381 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h" + +#include "base/logging.h" +#include "base/task/task_runner_util.h" +#include "browser/javascript_interface/gin_native_bridge_message_filter.h" +#include "common/gin_native_bridge_messages.h" +#include "common/gin_native_bridge_value.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "ipc/ipc_message_utils.h" + +namespace content { + +GinNativeBridgeDispatcherHost::GinNativeBridgeDispatcherHost( + WebContents* web_contents) + : WebContentsObserver(web_contents), next_object_id_(1) {} + +GinNativeBridgeDispatcherHost::~GinNativeBridgeDispatcherHost() {} + +void GinNativeBridgeDispatcherHost::InstallFilterAndRegisterAllRoutingIds() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!web_contents()->GetPrimaryMainFrame()->GetProcess()->GetChannel()) { + return; + } + + web_contents()->GetPrimaryMainFrame()->ForEachRenderFrameHost( + [this](RenderFrameHostImpl* frame) { + auto filter = GinNativeBridgeMessageFilter::FromHost(this, true); + filter->AddRoutingIdForHost(this, frame); + }); +} + +void GinNativeBridgeDispatcherHost::RenderFrameCreated( + RenderFrameHost* render_frame_host) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (auto filter = GinNativeBridgeMessageFilter::FromHost(this, false)) { + filter->AddRoutingIdForHost( + this, static_cast(render_frame_host)); + } else { + InstallFilterAndRegisterAllRoutingIds(); + } + for (NamedObjectMap::const_iterator iter = named_objects_.begin(); + iter != named_objects_.end(); ++iter) { + render_frame_host->Send(new GinNativeBridgeMsg_AddNamedObject( + render_frame_host->GetRoutingID(), iter->first, iter->second)); + } +} + +void GinNativeBridgeDispatcherHost::WebContentsDestroyed() { + scoped_refptr filter = + GinNativeBridgeMessageFilter::FromHost(this, false); + if (filter) + filter->RemoveHost(this); +} + +WebContentsImpl* GinNativeBridgeDispatcherHost::web_contents() const { + return static_cast(WebContentsObserver::web_contents()); +} + +bool GinNativeBridgeDispatcherHost::AddNamedObject( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name) { + LOG(INFO) << __FUNCTION__; + DCHECK_CURRENTLY_ON(BrowserThread::UI); + GinNativeBoundObject::ObjectID object_id; + NamedObjectMap::iterator iter = named_objects_.find(name); + if (iter != named_objects_.end()) + return false; + + object_id = AddObject(view, callback, name, true, 0); + named_objects_[name] = object_id; + + InstallFilterAndRegisterAllRoutingIds(); + + web_contents() + ->GetPrimaryMainFrame() + ->ForEachRenderFrameHostIncludingSpeculative( + [&name, object_id](RenderFrameHostImpl* render_frame_host) { + render_frame_host->Send(new GinNativeBridgeMsg_AddNamedObject( + render_frame_host->GetRoutingID(), name, object_id)); + }); + + return true; +} + +void GinNativeBridgeDispatcherHost::RemoveNamedObject(const std::string& name) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + NamedObjectMap::iterator iter = named_objects_.find(name); + if (iter == named_objects_.end()) + return; + + // |name| may come from |named_objects_|. Make a copy of name so that if + // |name| is from |named_objects_| it'll be valid after the remove below. + const std::string copied_name(name); + { + base::AutoLock locker(objects_lock_); + objects_[iter->second]->RemoveName(); + } + named_objects_.erase(iter); + + // As the object isn't going to be removed from the JavaScript side until the + // next page reload, calls to it must still work, thus we should continue to + // hold it. All the transient objects and removed named objects will be purged + // during the cleansing caused by DocumentAvailableInMainFrame event. + web_contents() + ->GetPrimaryMainFrame() + ->ForEachRenderFrameHostIncludingSpeculative( + [&copied_name](RenderFrameHostImpl* render_frame_host) { + render_frame_host->Send(new GinNativeBridgeMsg_RemoveNamedObject( + render_frame_host->GetRoutingID(), copied_name)); + }); +} + +GinNativeBoundObject::ObjectID GinNativeBridgeDispatcherHost::AddObject( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + bool is_named, + int32_t holder) { + scoped_refptr new_object = + is_named + ? GinNativeBoundObject::CreateNamed(view, callback, name) + : GinNativeBoundObject::CreateTransient(view, callback, name, holder); + // Note that we are abusing the fact that StaticAtomicSequenceNumber + // uses Atomic32 as a counter, so it is guaranteed that it will not + // overflow our int32_t IDs. IDs start from 1. + GinNativeBoundObject::ObjectID object_id = next_object_id_++; + { + base::AutoLock locker(objects_lock_); + objects_[object_id] = new_object; + } + return object_id; +} + +void GinNativeBridgeDispatcherHost::PrimaryMainDocumentElementAvailable() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // Called when the window object has been cleared in the main frame. + // That means, all sub-frames have also been cleared, so only named + // objects survived. + + NOTIMPLEMENTED(); +} + +scoped_refptr GinNativeBridgeDispatcherHost::FindObject( + GinNativeBoundObject::ObjectID object_id) { + // Can be called on any thread. + base::AutoLock locker(objects_lock_); + auto iter = objects_.find(object_id); + if (iter != objects_.end()) + return iter->second; + LOG(ERROR) << "WebView: Unknown object: " << object_id; + return nullptr; +} + +void GinNativeBridgeDispatcherHost::OnHasMethod( + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result) { + scoped_refptr object = FindObject(object_id); + + *result = (object.get()) ? true : false; +} + +void GinNativeBridgeDispatcherHost::OnInvokeMethod( + int routing_id, + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* wrapped_result, + content::GinNativeBridgeError* error_code) { + LOG(INFO) << __FUNCTION__; + DCHECK(routing_id != MSG_ROUTING_NONE); + if (method_name != "postMessage") { + LOG(ERROR) << __FUNCTION__ << " : kGinNativeBridgeMethodNotFound"; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeMethodNotFound; + return; + } + + scoped_refptr object = FindObject(object_id); + if (!object.get()) { + LOG(ERROR) << "WebView: Unknown object: " << object_id; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeUnknownObjectId; + return; + } + + Ewk_Script_Message msg; + msg.name = object->Name(); + + if (named_objects_.find(msg.name) == named_objects_.end()) { + LOG(ERROR) << __FUNCTION__ << " : kGinNativeBridgeMessageNameIsWrong"; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeMessageNameIsWrong; + return; + } + + JavaScript_Values values; + values.bool_buf = EINA_FALSE; + values.int_buf = -1; + values.double_buf = -1; + values.str_buf = ""; + + bool bool_buf = false; + bool should_free = false; + + base::Value::List::const_iterator iter = arguments.begin(); + + switch (iter->type()) { + case base::Value::Type::BOOLEAN: + bool_buf = iter->GetBool(); + (bool_buf) ? values.bool_buf = EINA_TRUE : values.bool_buf = EINA_FALSE; + msg.body = &values.bool_buf; + break; + case base::Value::Type::INTEGER: + values.int_buf = iter->GetInt(); + msg.body = &values.int_buf; + break; + case base::Value::Type::DOUBLE: + values.double_buf = iter->GetDouble(); + msg.body = &values.double_buf; + break; + case base::Value::Type::STRING: + values.str_buf = iter->GetString(); + msg.body = strdup(values.str_buf.c_str()); + should_free = true; + break; + case base::Value::Type::DICTIONARY: + values.str_buf = ConvertDictionaryValueToString(iter->GetDict()); + msg.body = strdup(values.str_buf.c_str()); + should_free = true; + break; + case base::Value::Type::LIST: + values.str_buf = ConvertListValueToString(iter->GetList()); + msg.body = strdup(values.str_buf.c_str()); + should_free = true; + break; + case base::Value::Type::BINARY: + values.str_buf.assign(iter->GetBlob().begin(), iter->GetBlob().end()); + msg.body = (void*)values.str_buf.data(); + break; + default: + LOG(ERROR) << __FUNCTION__ << " : kGinNativeBridgeNotSupportedTypes"; + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeNotSupportedTypes; + return; + } + + object->CallBack()(object->GetView(), msg); + wrapped_result->Append(base::Value::FromUniquePtrValue( + GinNativeBridgeValue::CreateObjectIDValue(object_id))); + + if (should_free) + free(msg.body); + + return; +} + +std::string GinNativeBridgeDispatcherHost::ConvertListValueToString( + const base::Value::List& list) { + bool init = false; + bool bool_buf = false; + int int_buf = -1; + double double_buf = -1; + std::string str_buf = ""; + std::string token = ""; + + str_buf = "["; + for (base::Value::List::const_iterator iter_list = list.begin(); + iter_list != list.end(); ++iter_list) { + if (init) + str_buf += ","; + + switch (iter_list->type()) { + case base::Value::Type::BOOLEAN: + bool_buf = false; + bool_buf = iter_list->GetBool(); + (bool_buf) ? str_buf += "true" : str_buf += "false"; + break; + case base::Value::Type::INTEGER: + int_buf = -1; + int_buf = iter_list->GetInt(); + str_buf += std::to_string(int_buf); + break; + case base::Value::Type::DOUBLE: + double_buf = -1; + double_buf = iter_list->GetDouble(); + str_buf += std::to_string(double_buf); + break; + case base::Value::Type::STRING: + token = ""; + token = iter_list->GetString(); + str_buf += "\""; + str_buf += token; + str_buf += "\""; + break; + case base::Value::Type::DICTIONARY: + str_buf = ConvertDictionaryValueToString(iter_list->GetDict()); + break; + case base::Value::Type::LIST: + str_buf += ConvertListValueToString(iter_list->GetList()); + break; + default: + str_buf += "\"\""; + break; + } + init = true; + } + str_buf += "]"; + + return str_buf; +} + +std::string GinNativeBridgeDispatcherHost::ConvertDictionaryValueToString( + const base::Value::Dict& dict) { + bool init = false; + bool bool_buf = false; + int int_buf = -1; + double double_buf = -1; + std::string str_buf = ""; + std::string token = ""; + + str_buf = "{"; + for (const auto item : dict) { + if (init) + str_buf += ","; + str_buf += " \""; + str_buf += item.first; + str_buf += "\": "; + + switch (item.second.type()) { + case base::Value::Type::BOOLEAN: + bool_buf = false; + bool_buf = item.second.GetBool(); + (bool_buf) ? str_buf += "true" : str_buf += "false"; + break; + case base::Value::Type::INTEGER: + int_buf = -1; + int_buf = item.second.GetInt(); + str_buf += std::to_string(int_buf); + break; + case base::Value::Type::DOUBLE: + double_buf = -1; + double_buf = item.second.GetDouble(); + str_buf += std::to_string(double_buf); + break; + case base::Value::Type::STRING: + token = ""; + token = item.second.GetString(); + str_buf += "\""; + str_buf += token; + str_buf += "\""; + break; + case base::Value::Type::DICTIONARY: + str_buf += ConvertDictionaryValueToString(item.second.GetDict()); + break; + case base::Value::Type::LIST: + str_buf += ConvertListValueToString(item.second.GetList()); + break; + default: + str_buf += "\"\""; + break; + } + init = true; + } + str_buf += "}"; + + return str_buf; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h new file mode 100644 index 0000000..43df6ef --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_dispatcher_host.h @@ -0,0 +1,98 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_DISPATCHER_HOST_H_ +#define EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_DISPATCHER_HOST_H_ + +#include +#include +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "browser/javascript_interface/gin_native_bound_object.h" +#include "common/gin_native_bridge_errors.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/web_contents_observer.h" +#include "public/ewk_view.h" + +namespace content { + +class GinNativeBridgeDispatcherHost + : public base::RefCountedThreadSafe, + public WebContentsObserver { + public: + explicit GinNativeBridgeDispatcherHost(WebContents* web_contents); + ~GinNativeBridgeDispatcherHost() override; + + GinNativeBridgeDispatcherHost(const GinNativeBridgeDispatcherHost&) = delete; + GinNativeBridgeDispatcherHost& operator=( + const GinNativeBridgeDispatcherHost&) = delete; + + // WebContentsObserver + void RenderFrameCreated(RenderFrameHost* render_frame_host) override; + void WebContentsDestroyed() override; + void PrimaryMainDocumentElementAvailable() override; + + bool AddNamedObject(Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name); + void RemoveNamedObject(const std::string& name); + void OnHasMethod(GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result); + + void OnInvokeMethod(int routing_id, + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* result, + content::GinNativeBridgeError* error_code); + WebContentsImpl* web_contents() const; + + private: + friend class base::RefCountedThreadSafe; + typedef std::map> + ObjectMap; + + // Run on the UI thread. + void InstallFilterAndRegisterAllRoutingIds(); + + bool FindObjectId(); + GinNativeBoundObject::ObjectID AddObject(Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const std::string& name, + bool is_named, + int32_t holder); + scoped_refptr FindObject( + GinNativeBoundObject::ObjectID object_id); + + std::string ConvertListValueToString(const base::Value::List& list); + + std::string ConvertDictionaryValueToString(const base::Value::Dict& dict); + + typedef std::map NamedObjectMap; + NamedObjectMap named_objects_; + + GinNativeBoundObject::ObjectID next_object_id_; + + // Note that retained_object_set_ does not need to be consistent + // with objects_. + ObjectMap objects_; + base::Lock objects_lock_; + + struct _JavaScript_Values { + Eina_Bool bool_buf; /**< Buffer for boolean */ + int int_buf; /**< Buffer for integer */ + double double_buf; /**< Buffer for double */ + std::string str_buf; /**< Buffer for string */ + }; + typedef struct _JavaScript_Values JavaScript_Values; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_DISPATCHER_HOST_H_ diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc new file mode 100644 index 0000000..2eacac2 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.cc @@ -0,0 +1,137 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/javascript_interface/gin_native_bridge_message_filter.h" + +#include "base/auto_reset.h" +#include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h" +#include "common/gin_native_bridge_messages.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" + +namespace { +const char kGinNativeBridgeMessageFilterKey[] = "GinNativeBridgeMessageFilter"; +} // namespace + +namespace content { + +GinNativeBridgeMessageFilter::GinNativeBridgeMessageFilter() + : BrowserMessageFilter(GinNativeBridgeMsgStart), + current_routing_id_(MSG_ROUTING_NONE) {} + +GinNativeBridgeMessageFilter::~GinNativeBridgeMessageFilter() {} + +void GinNativeBridgeMessageFilter::OnDestruct() const { + if (BrowserThread::CurrentlyOn(BrowserThread::UI)) + delete this; + else + BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); +} + +bool GinNativeBridgeMessageFilter::OnMessageReceived( + const IPC::Message& message) { + base::AutoReset routing_id(¤t_routing_id_, + message.routing_id()); + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GinNativeBridgeMessageFilter, message) + IPC_MESSAGE_HANDLER(GinNativeBridgeHostMsg_HasMethod, OnHasMethod) + IPC_MESSAGE_HANDLER(GinNativeBridgeHostMsg_InvokeMethod, OnInvokeMethod) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +scoped_refptr +GinNativeBridgeMessageFilter::OverrideTaskRunnerForMessage( + const IPC::Message& message) { + // As the filter is only invoked for the messages of the particular class, + // we can return the task runner unconfitionally. + return nullptr; +} + +void GinNativeBridgeMessageFilter::AddRoutingIdForHost( + GinNativeBridgeDispatcherHost* host, + RenderFrameHostImpl* render_frame_host) { + base::AutoLock locker(hosts_lock_); + hosts_[render_frame_host->GetRoutingID()] = host; +} + +void GinNativeBridgeMessageFilter::RemoveHost( + GinNativeBridgeDispatcherHost* host) { + base::AutoLock locker(hosts_lock_); + auto iter = hosts_.begin(); + while (iter != hosts_.end()) { + if (iter->second == host) + hosts_.erase(iter++); + else + ++iter; + } +} + +// static +scoped_refptr +GinNativeBridgeMessageFilter::FromHost(GinNativeBridgeDispatcherHost* host, + bool create_if_not_exists) { + RenderProcessHost* rph = + host->web_contents()->GetPrimaryMainFrame()->GetProcess(); + scoped_refptr filter = + base::UserDataAdapter::Get( + rph, kGinNativeBridgeMessageFilterKey); + if (!filter && create_if_not_exists) { + filter = new GinNativeBridgeMessageFilter(); + rph->AddFilter(filter.get()); + rph->SetUserData( + kGinNativeBridgeMessageFilterKey, + base::WrapUnique( + new base::UserDataAdapter( + filter.get()))); + } + return filter; +} + +GinNativeBridgeDispatcherHost* GinNativeBridgeMessageFilter::FindHost() { + base::AutoLock locker(hosts_lock_); + auto iter = hosts_.find(current_routing_id_); + if (iter != hosts_.end()) + return iter->second; + // This is usually OK -- we can receive messages form RenderFrames for + // which the corresponding host part has already been destroyed. That means, + // any references to Native objects that the host was holding were already + // released (with the death of ContentViewCore), so we can just drop such + // messages. + LOG(WARNING) << "WebView: Unknown frame routing id: " << current_routing_id_; + return nullptr; +} + +void GinNativeBridgeMessageFilter::OnHasMethod( + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result) { + GinNativeBridgeDispatcherHost* host = FindHost(); + if (host) + host->OnHasMethod(object_id, method_name, result); + else + *result = false; +} + +void GinNativeBridgeMessageFilter::OnInvokeMethod( + GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* wrapped_result, + content::GinNativeBridgeError* error_code) { + LOG(INFO) << __FUNCTION__; + GinNativeBridgeDispatcherHost* host = FindHost(); + if (host) { + host->OnInvokeMethod(current_routing_id_, object_id, method_name, arguments, + wrapped_result, error_code); + } else { + wrapped_result->Append(base::Value()); + *error_code = kGinNativeBridgeRenderFrameDeleted; + } +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h new file mode 100644 index 0000000..dbb24c6 --- /dev/null +++ b/tizen_src/ewk/efl_integration/browser/javascript_interface/gin_native_bridge_message_filter.h @@ -0,0 +1,98 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_MESSAGE_FILTER_H_ +#define EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_MESSAGE_FILTER_H_ + +#include + +#include +#include +#include + +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "base/values.h" +#include "browser/javascript_interface/gin_native_bound_object.h" +#include "common/gin_native_bridge_errors.h" +#include "content/public/browser/browser_message_filter.h" + +namespace base { +class ListValue; +} + +namespace IPC { +class Message; +} + +namespace content { + +class GinNativeBridgeDispatcherHost; +class RenderFrameHostImpl; + +class GinNativeBridgeMessageFilter : public BrowserMessageFilter { + public: + // BrowserMessageFilter + void OnDestruct() const override; + bool OnMessageReceived(const IPC::Message& message) override; + scoped_refptr OverrideTaskRunnerForMessage( + const IPC::Message& message) override; + + // Called on the UI thread. + void AddRoutingIdForHost(GinNativeBridgeDispatcherHost* host, + RenderFrameHostImpl* render_frame_host); + void RemoveHost(GinNativeBridgeDispatcherHost* host); + + static scoped_refptr FromHost( + GinNativeBridgeDispatcherHost* host, + bool create_if_not_exists); + + private: + friend class BrowserThread; + friend class base::DeleteHelper; + + // WebView (who owns GinNativeBridgeDispatcherHost) outlives + // WebContents, and GinNativeBridgeDispatcherHost removes itself form the map + // on WebContents destruction, so there is no risk that the pointer would + // become stale. + // + // The filter keeps its own routing map of RenderFrames for two reasons: + // 1. Message dispatching must be done on the background thread, + // without resorting to the UI thread, which can be in fact currently + // blocked, waiting for an event from an injected Native object. + // 2. As RenderFrames pass away earlier than JavaScript wrappers, + // messages form the latter can arrive after the RenderFrame has been + // removed from the WebContent's routing table. + typedef std::map HostMap; + + GinNativeBridgeMessageFilter(); + ~GinNativeBridgeMessageFilter() override; + + GinNativeBridgeMessageFilter(const GinNativeBridgeMessageFilter&) = delete; + GinNativeBridgeMessageFilter& operator=(const GinNativeBridgeMessageFilter&) = + delete; + + // Called on the background thread. + GinNativeBridgeDispatcherHost* FindHost(); + void OnHasMethod(GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + bool* result); + void OnInvokeMethod(GinNativeBoundObject::ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + base::Value::List* result, + content::GinNativeBridgeError* error_code); + + // Accessed both from UI and background threads. + HostMap hosts_; + base::Lock hosts_lock_; + + // The routing id of the RenderFrameHost whose request we are processing. + // Used on the backgrount thread. + int32_t current_routing_id_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_BROWSER_JAVASCRIPT_INTERFACE_GIN_NATIVE_BRIDGE_MESSAGE_FILTER_H_ diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc new file mode 100644 index 0000000..dd8184a --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.cc @@ -0,0 +1,39 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "common/gin_native_bridge_errors.h" + +#include "base/notreached.h" + +namespace content { + +const char* GinNativeBridgeErrorToString(GinNativeBridgeError error) { + switch (error) { + case kGinNativeBridgeNoError: + return "No error"; + case kGinNativeBridgeUnknownObjectId: + return "Unknown Native object ID"; + case kGinNativeBridgeObjectIsGone: + return "Native object is gone"; + case kGinNativeBridgeMethodNotFound: + return "Method not found"; + case kGinNativeBridgeAccessToObjectGetClassIsBlocked: + return "Access to Object.getClass is blocked"; + case kGinNativeBridgeNativeExceptionRaised: + return "Native exception was raised during method invocation"; + case kGinNativeBridgeNonAssignableTypes: + return "The type of the object passed to the method is incompatible " + "with the type of method's argument"; + case kGinNativeBridgeRenderFrameDeleted: + return "RenderFrame has been deleted"; + case kGinNativeBridgeNotSupportedTypes: + return "This type is not supported"; + case kGinNativeBridgeMessageNameIsWrong: + return "Message name is wrong"; + } + NOTREACHED(); + return "Unknown error"; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h new file mode 100644 index 0000000..cee74ff --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_errors.h @@ -0,0 +1,31 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_ERRORS_H_ +#define EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_ERRORS_H_ + +#include "content/common/content_export.h" + +namespace content { + +enum GinNativeBridgeError { + kGinNativeBridgeNoError = 0, + kGinNativeBridgeUnknownObjectId, + kGinNativeBridgeObjectIsGone, + kGinNativeBridgeMethodNotFound, + kGinNativeBridgeAccessToObjectGetClassIsBlocked, + kGinNativeBridgeNativeExceptionRaised, + kGinNativeBridgeNonAssignableTypes, + kGinNativeBridgeRenderFrameDeleted, + kGinNativeBridgeNotSupportedTypes, + kGinNativeBridgeMessageNameIsWrong, + kGinNativeBridgeErrorLast = kGinNativeBridgeRenderFrameDeleted +}; + +CONTENT_EXPORT const char* GinNativeBridgeErrorToString( + GinNativeBridgeError error); + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_ERRORS_H_ diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h b/tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h new file mode 100644 index 0000000..6f976df --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_messages.h @@ -0,0 +1,60 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +#include "common/gin_native_bridge_errors.h" +#include "content/common/content_export.h" +#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_message_start.h" + +#undef IPC_MESSAGE_EXPORT +#define IPC_MESSAGE_EXPORT CONTENT_EXPORT +#define IPC_MESSAGE_START GinNativeBridgeMsgStart + +// Messages for handling Java objects injected into JavaScript ----------------- + +IPC_ENUM_TRAITS_MAX_VALUE(content::GinNativeBridgeError, + content::kGinNativeBridgeErrorLast) + +// Sent from browser to renderer to add a Native object with the given name. +// Object IDs are generated on the browser side. +IPC_MESSAGE_ROUTED2(GinNativeBridgeMsg_AddNamedObject, + std::string /* name */, + int32_t /* object_id */) + +// Sent from browser to renderer to remove a Java object with the given name. +IPC_MESSAGE_ROUTED1(GinNativeBridgeMsg_RemoveNamedObject, + std::string /* name */) + +// Sent from renderer to browser to get information about methods of +// the given object. The query will only succeed if inspection of injected +// objects is enabled on the browser side. +IPC_SYNC_MESSAGE_ROUTED1_1(GinNativeBridgeHostMsg_GetMethods, + int32_t /* object_id */, + std::set /* returned_method_names */) + +// Sent from renderer to browser to find out, if an object has a method with +// the given name. +IPC_SYNC_MESSAGE_ROUTED2_1(GinNativeBridgeHostMsg_HasMethod, + int32_t /* object_id */, + std::string /* method_name */, + bool /* result */) + +// Sent from renderer to browser to invoke a method. Method arguments +// are chained into |arguments| list. base::Value::List is used for |result| as +// a container to work around immutability of base::Value. +// Empty result list indicates that an error has happened on the Native side +// (either bridge-induced error or an unhandled Native exception) and an +// exception must be thrown into JavaScript. |error_code| indicates the cause of +// the error. +// Some special value types that are not supported by base::Value are encoded +// as BinaryValues via GinNativeBridgeValue. +IPC_SYNC_MESSAGE_ROUTED3_2(GinNativeBridgeHostMsg_InvokeMethod, + int32_t /* object_id */, + std::string /* method_name */, + base::Value::List /* arguments */, + base::Value::List /* result */, + content::GinNativeBridgeError /* error_code */) diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc new file mode 100644 index 0000000..ab8e34a --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.cc @@ -0,0 +1,105 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ewk/efl_integration/common/gin_native_bridge_value.h" + +namespace content { + +namespace { +// The magic value is only used to prevent accidental attempts of reading +// GinJavaBridgeValue from a random BinaryValue. GinJavaBridgeValue is not +// intended for scenarios where with BinaryValues are being used for anything +// else than holding GinJavaBridgeValues. If a need for such scenario ever +// emerges, the best solution would be to extend GinJavaBridgeValue to be able +// to wrap raw BinaryValues. +const uint32_t kHeaderMagic = 0xBEEFCAFE; + +#pragma pack(push, 4) +struct Header : public base::Pickle::Header { + uint32_t magic; + int32_t type; +}; +#pragma pack(pop) +} // namespace + +// static +std::unique_ptr GinNativeBridgeValue::CreateObjectIDValue( + int32_t in_value) { + GinNativeBridgeValue gin_value(TYPE_OBJECT_ID); + gin_value.pickle_.WriteInt(in_value); + return gin_value.SerializeToValue(); +} + +// static +bool GinNativeBridgeValue::ContainsGinJavaBridgeValue( + const base::Value* value) { + if (!value->is_blob()) + return false; + const base::Value* binary_value = reinterpret_cast(value); + if (binary_value->GetBlob().size() < sizeof(Header)) + return false; + base::Pickle pickle((const char*)binary_value->GetBlob().data(), + binary_value->GetBlob().size()); + // Broken binary value: payload or header size is wrong + if (!pickle.data() || pickle.size() - pickle.payload_size() != sizeof(Header)) + return false; + Header* header = pickle.headerT
(); + return (header->magic == kHeaderMagic && header->type >= TYPE_FIRST_VALUE && + header->type < TYPE_LAST_VALUE); +} + +// static +std::unique_ptr GinNativeBridgeValue::FromValue( + const base::Value* value) { + return std::unique_ptr( + value->is_blob() ? new GinNativeBridgeValue( + reinterpret_cast(value)) + : NULL); +} + +GinNativeBridgeValue::Type GinNativeBridgeValue::GetType() const { + const Header* header = pickle_.headerT
(); + DCHECK(header->type >= TYPE_FIRST_VALUE && header->type < TYPE_LAST_VALUE); + return static_cast(header->type); +} + +bool GinNativeBridgeValue::IsType(Type type) const { + return GetType() == type; +} + +bool GinNativeBridgeValue::GetAsNonFinite(float* out_value) const { + if (GetType() != TYPE_NONFINITE) + return false; + + base::PickleIterator iter(pickle_); + return iter.ReadFloat(out_value); +} + +bool GinNativeBridgeValue::GetAsObjectID(int32_t* out_object_id) const { + if (GetType() != TYPE_OBJECT_ID) + return false; + + base::PickleIterator iter(pickle_); + return iter.ReadInt(out_object_id); +} + +GinNativeBridgeValue::GinNativeBridgeValue(Type type) + : pickle_(sizeof(Header)) { + Header* header = pickle_.headerT
(); + header->magic = kHeaderMagic; + header->type = type; +} + +GinNativeBridgeValue::GinNativeBridgeValue(const base::Value* value) + : pickle_((const char*)value->GetBlob().data(), value->GetBlob().size()) { + DCHECK(ContainsGinJavaBridgeValue(value)); +} + +std::unique_ptr GinNativeBridgeValue::SerializeToValue() { + return std::make_unique(base::Value::BlobStorage( + reinterpret_cast(pickle_.data()), + reinterpret_cast(pickle_.data()) + pickle_.size())); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h new file mode 100644 index 0000000..946293f9 --- /dev/null +++ b/tizen_src/ewk/efl_integration/common/gin_native_bridge_value.h @@ -0,0 +1,56 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_VALUE_H_ +#define EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_VALUE_H_ + +#include + +#include "base/pickle.h" +#include "base/values.h" +#include "content/common/content_export.h" + +namespace content { + +class GinNativeBridgeValue { + public: + enum Type { + TYPE_FIRST_VALUE = 0, + // JavaScript 'undefined' + TYPE_UNDEFINED = 0, + // JavaScript NaN and Infinity + TYPE_NONFINITE, + // Bridge Object ID + TYPE_OBJECT_ID, + TYPE_LAST_VALUE + }; + + CONTENT_EXPORT static std::unique_ptr CreateObjectIDValue( + int32_t in_value); + + // De-serialization + CONTENT_EXPORT static bool ContainsGinJavaBridgeValue( + const base::Value* value); + CONTENT_EXPORT static std::unique_ptr FromValue( + const base::Value* value); + CONTENT_EXPORT Type GetType() const; + CONTENT_EXPORT bool IsType(Type type) const; + CONTENT_EXPORT bool GetAsNonFinite(float* out_value) const; + CONTENT_EXPORT bool GetAsObjectID(int32_t* out_object_id) const; + + private: + explicit GinNativeBridgeValue(Type type); + explicit GinNativeBridgeValue(const base::Value* value); + + GinNativeBridgeValue(const GinNativeBridgeValue&) = delete; + GinNativeBridgeValue& operator=(const GinNativeBridgeValue&) = delete; + + std::unique_ptr SerializeToValue(); + + base::Pickle pickle_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_COMMON_GIN_NATIVE_BRIDGE_VALUE_H_ diff --git a/tizen_src/ewk/efl_integration/common/message_generator_ewk.h b/tizen_src/ewk/efl_integration/common/message_generator_ewk.h index db42330..f9760ba 100644 --- a/tizen_src/ewk/efl_integration/common/message_generator_ewk.h +++ b/tizen_src/ewk/efl_integration/common/message_generator_ewk.h @@ -5,5 +5,6 @@ // Multiply-included file, hence no include guard. // efl message generator -#include "common/render_messages_ewk.h" #include "common/editing_messages.h" +#include "common/gin_native_bridge_messages.h" +#include "common/render_messages_ewk.h" diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index a9f9686..449ac1b 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/pickle.h" #include "base/strings/utf_string_conversions.h" +#include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h" #include "browser/navigation_policy_handler_efl.h" #include "browser/quota_permission_context_efl.h" #include "browser/selectpicker/popup_menu_item.h" @@ -64,6 +65,7 @@ #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/display/screen.h" +#include "ui/events/event_switches.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/vector2d_f.h" #include "ui/platform_window/platform_window_init_properties.h" @@ -290,6 +292,7 @@ EWebView::~EWebView() { if (context_->GetImpl()->browser_context()->IsOffTheRecord()) Ewk_Context::Delete(context_.get()); + gin_native_bridge_dispatcher_host_.reset(); } void EWebView::ReleasePopupMenuList() { @@ -332,6 +335,17 @@ Eina_Bool EWebView::HasFocus() const { return rwhva()->offscreen_helper()->HasFocus() ? EINA_TRUE : EINA_FALSE; } +Eina_Bool EWebView::AddJavaScriptMessageHandler( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + std::string name) { + if (!gin_native_bridge_dispatcher_host_) + return EINA_FALSE; + + return gin_native_bridge_dispatcher_host_->AddNamedObject(view, callback, + name); +} + bool EWebView::CreateNewWindow( content::WebContentsEflDelegate::WebContentsCreateCallback cb) { create_new_window_web_contents_cb_ = cb; @@ -734,18 +748,17 @@ void JavaScriptComplete(JavaScriptCallbackDetails* script_callback_data, bool EWebView::ExecuteJavaScript(const char* script, Ewk_View_Script_Execute_Callback callback, void* userdata) { - if (!script) - return false; - - if (!web_contents_delegate_) // question, can I remove this check? - return false; - - if (!web_contents_) + LOG(INFO) << __FUNCTION__; + if (!web_contents_) { + LOG(ERROR) << __FUNCTION__ << "web_contents_ is null"; return false; + } RenderFrameHost* render_frame_host = web_contents_->GetPrimaryMainFrame(); - if (!render_frame_host) + if (!render_frame_host) { + LOG(ERROR) << __FUNCTION__ << " render_frame_host is null"; return false; + } // Note: M37. Execute JavaScript, |script| with // |RenderFrameHost::ExecuteJavaScript|. @@ -2264,6 +2277,8 @@ void EWebView::InitializeContent() { new _Ewk_Back_Forward_List(web_contents_->GetController())); permission_popup_manager_.reset(new PermissionPopupManager(evas_object_)); + gin_native_bridge_dispatcher_host_.reset( + new content::GinNativeBridgeDispatcherHost(web_contents_.get())); native_view_ = static_cast(web_contents_.get())->GetEflNativeView(); diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 93a0b53..bb7357b 100755 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -71,6 +71,7 @@ class WebContentsViewAura; class ContextMenuControllerEfl; class PopupControllerEfl; class InputPicker; +class GinNativeBridgeDispatcherHost; } class ErrorParams; @@ -475,6 +476,14 @@ class EWebView { return context_menu_.get(); } void ResetContextMenuController(); + Eina_Bool AddJavaScriptMessageHandler(Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + std::string name); + + content::GinNativeBridgeDispatcherHost* GetGinNativeBridgeDispatcherHost() + const { + return gin_native_bridge_dispatcher_host_.get(); + } /// ---- Event handling bool HandleShow(); @@ -623,6 +632,10 @@ class EWebView { std::unique_ptr permission_popup_manager_; std::unique_ptr scroll_detector_; + // Manages injecting native objects. + std::unique_ptr + gin_native_bridge_dispatcher_host_; + #if BUILDFLAG(IS_TIZEN) blink::mojom::FileChooserParams::Mode filechooser_mode_; #endif diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 40d8e79..9392ea8 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -21,6 +21,7 @@ #include "ewk_view_product.h" #include +#include #include "authentication_challenge_popup.h" #include "content/public/browser/navigation_controller.h" @@ -1318,6 +1319,44 @@ Eina_Bool ewk_view_tts_mode_set(Evas_Object* view, ewk_tts_mode tts_mode) { return false; } +Eina_Bool ewk_view_javascript_message_handler_add( + Evas_Object* view, + Ewk_View_Script_Message_Cb callback, + const char* name) { + EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); + return impl->AddJavaScriptMessageHandler(view, callback, std::string(name)); +} + +Eina_Bool ewk_view_evaluate_javascript(Evas_Object* view, + const char* name, + const char* result) { + EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(result, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); + + std::string function(name); + std::string data(result); + std::string pattern("\n"); + std::string replace("
"); + std::string::size_type pos = 0; + std::string::size_type offset = 0; + while ((pos = data.find(pattern, offset)) != std::string::npos) { + data.replace(data.begin() + pos, data.begin() + pos + pattern.size(), + replace); + offset = pos + replace.size(); + } + + // For JSON Object or Array. + if (result[0] == '{' || result[0] == '[') { + data = "javascript:" + function + "(JSON.parse('" + data + "'))"; + } else { + data = "javascript:" + function + "('" + data + "')"; + } + + return impl->ExecuteJavaScript(data.c_str(), NULL, 0); +} + void ewk_view_authentication_callback_set( Evas_Object* ewk_view, Ewk_View_Authentication_Callback callback, diff --git a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc index eb24496..aaf4c52 100644 --- a/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc +++ b/tizen_src/ewk/efl_integration/renderer/content_renderer_client_efl.cc @@ -26,6 +26,7 @@ #if !defined(EWK_BRINGUP) // FIXME: m94 bringup #include "renderer/editorclient_agent.h" #endif +#include "renderer/gin_native_bridge_dispatcher.h" #include "renderer/plugins/plugin_placeholder_efl.h" #include "renderer/render_frame_observer_efl.h" #include "third_party/blink/public/platform/url_conversion.h" @@ -147,6 +148,8 @@ void ContentRendererClientEfl::RenderThreadStarted() { void ContentRendererClientEfl::RenderFrameCreated(content::RenderFrame* render_frame) { new content::RenderFrameObserverEfl(render_frame); new content::ContentSettingsClientEfl(render_frame); + // Deletes itself when render_frame is destroyed. + new content::GinNativeBridgeDispatcher(render_frame); #if defined(TIZEN_AUTOFILL_SUPPORT) PasswordAutofillAgent* password_autofill_agent = diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc new file mode 100644 index 0000000..1b95734 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.cc @@ -0,0 +1,120 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "renderer/gin_native_bridge_dispatcher.h" + +#include "base/auto_reset.h" +#include "common/gin_native_bridge_messages.h" +#include "content/public/renderer/render_frame.h" +#include "renderer/gin_native_bridge_object.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_view.h" + +namespace content { + +GinNativeBridgeDispatcher::GinNativeBridgeDispatcher(RenderFrame* render_frame) + : RenderFrameObserver(render_frame), + inside_did_clear_window_object_(false) {} + +GinNativeBridgeDispatcher::~GinNativeBridgeDispatcher() {} + +bool GinNativeBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(GinNativeBridgeDispatcher, msg) + IPC_MESSAGE_HANDLER(GinNativeBridgeMsg_AddNamedObject, OnAddNamedObject) + IPC_MESSAGE_HANDLER(GinNativeBridgeMsg_RemoveNamedObject, + OnRemoveNamedObject) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void GinNativeBridgeDispatcher::DidClearWindowObject() { + // Accessing window object when adding properties to it may trigger + // a nested call to DidClearWindowObject. + if (inside_did_clear_window_object_) + return; + base::AutoReset flag_entry(&inside_did_clear_window_object_, true); + for (NamedObjectMap::const_iterator iter = named_objects_.begin(); + iter != named_objects_.end(); ++iter) { + // Always create a new GinNativeBridgeObject, so we don't pull any of the V8 + // wrapper's custom properties into the context of the page we have + // navigated to. The old GinNativeBridgeObject will be automatically + // deleted after its wrapper will be collected. + // On the browser side, we ignore wrapper deletion events for named objects, + // as they are only removed upon embedder's request (RemoveNamedObject). + if (objects_.Lookup(iter->second)) + objects_.Remove(iter->second); + GinNativeBridgeObject* object = GinNativeBridgeObject::InjectNamed( + render_frame()->GetWebFrame(), AsWeakPtr(), iter->first, iter->second); + if (object) { + objects_.AddWithID(object, iter->second); + } else { + // FIXME: Inform the host about wrapper creation failure. + } + } +} + +void GinNativeBridgeDispatcher::OnAddNamedObject(const std::string& name, + ObjectID object_id) { + LOG(INFO) << __FUNCTION__; + // Added objects only become available after page reload, so here they + // are only added into the internal map. + named_objects_.insert(std::make_pair(name, object_id)); +} + +void GinNativeBridgeDispatcher::OnRemoveNamedObject(const std::string& name) { + // Removal becomes in effect on next reload. We simply removing the entry + // from the map here. + NamedObjectMap::iterator iter = named_objects_.find(name); + DCHECK(iter != named_objects_.end()); + named_objects_.erase(iter); +} + +void GinNativeBridgeDispatcher::GetNativeMethods( + ObjectID object_id, + std::set* methods) { + render_frame()->Send( + new GinNativeBridgeHostMsg_GetMethods(routing_id(), object_id, methods)); +} + +bool GinNativeBridgeDispatcher::HasNativeMethod( + ObjectID object_id, + const std::string& method_name) { + bool result; + render_frame()->Send(new GinNativeBridgeHostMsg_HasMethod( + routing_id(), object_id, method_name, &result)); + return result; +} + +std::unique_ptr GinNativeBridgeDispatcher::InvokeNativeMethod( + ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + GinNativeBridgeError* error) { + LOG(INFO) << __FUNCTION__; + base::Value::List result_wrapper; + render_frame()->Send(new GinNativeBridgeHostMsg_InvokeMethod( + routing_id(), object_id, method_name, arguments, &result_wrapper, error)); + if (result_wrapper.empty()) + return nullptr; + return base::Value::ToUniquePtrValue(result_wrapper[0].Clone()); +} + +GinNativeBridgeObject* GinNativeBridgeDispatcher::GetObject( + ObjectID object_id) { + GinNativeBridgeObject* result = objects_.Lookup(object_id); + if (!result) { + result = GinNativeBridgeObject::InjectAnonymous(AsWeakPtr(), object_id); + if (result) + objects_.AddWithID(result, object_id); + } + return result; +} + +void GinNativeBridgeDispatcher::OnDestruct() { + delete this; +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h new file mode 100644 index 0000000..0905eb6 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_dispatcher.h @@ -0,0 +1,77 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_DISPATCHER_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_DISPATCHER_H_ + +#include +#include +#include + +#include "base/containers/id_map.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "content/public/renderer/render_frame_observer.h" +#include "ewk/efl_integration/common/gin_native_bridge_errors.h" + +namespace blink { +class WebFrame; +} + +namespace content { + +class GinNativeBridgeObject; + +// This class handles injecting Native objects into the main frame of a +// RenderView. The 'add' and 'remove' messages received from the browser +// process modify the entries in a map of 'pending' objects. These objects are +// bound to the window object of the main frame when that window object is next +// cleared. These objects remain bound until the window object is cleared +// again. + +class GinNativeBridgeDispatcher + : public base::SupportsWeakPtr, + public RenderFrameObserver { + public: + // GinNativeBridgeObjects are managed by gin. An object gets destroyed + // when it is no more referenced from JS. As GinNativeBridgeObjects reports + // deletion of self to GinNativeBridgeDispatcher, we would not have stale + // pointers here. + typedef base::IDMap ObjectMap; + typedef ObjectMap::KeyType ObjectID; + + explicit GinNativeBridgeDispatcher(RenderFrame* render_frame); + ~GinNativeBridgeDispatcher() override; + + GinNativeBridgeDispatcher(const GinNativeBridgeDispatcher&) = delete; + GinNativeBridgeDispatcher& operator=(const GinNativeBridgeDispatcher&) = + delete; + + // RenderFrameObserver override: + void OnDestruct() override; + bool OnMessageReceived(const IPC::Message& message) override; + void DidClearWindowObject() override; + + void GetNativeMethods(ObjectID object_id, std::set* methods); + bool HasNativeMethod(ObjectID object_id, const std::string& method_name); + std::unique_ptr InvokeNativeMethod( + ObjectID object_id, + const std::string& method_name, + const base::Value::List& arguments, + GinNativeBridgeError* error); + GinNativeBridgeObject* GetObject(ObjectID object_id); + + private: + void OnAddNamedObject(const std::string& name, ObjectID object_id); + void OnRemoveNamedObject(const std::string& name); + + typedef std::map NamedObjectMap; + NamedObjectMap named_objects_; + ObjectMap objects_; + bool inside_did_clear_window_object_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_DISPATCHER_H_ diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc new file mode 100644 index 0000000..caf9e41 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.cc @@ -0,0 +1,124 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "renderer/gin_native_bridge_object.h" + +#include "common/gin_native_bridge_messages.h" +#include "content/public/renderer/render_thread.h" +#include "gin/function_template.h" +#include "renderer/gin_native_function_invocation_helper.h" +#include "third_party/blink/public/web/blink.h" +#include "third_party/blink/public/web/web_frame.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "v8/include/v8-function.h" + +namespace content { +// static +GinNativeBridgeObject* GinNativeBridgeObject::InjectNamed( + blink::WebFrame* frame, + const base::WeakPtr& dispatcher, + const std::string& object_name, + GinNativeBridgeDispatcher::ObjectID object_id) { + v8::Isolate* isolate = blink::MainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + + if (!frame->IsWebLocalFrame()) + return NULL; + + v8::Local context = + frame->ToWebLocalFrame()->MainWorldScriptContext(); + if (context.IsEmpty()) + return NULL; + + GinNativeBridgeObject* object = + new GinNativeBridgeObject(isolate, dispatcher, object_id); + + v8::Context::Scope context_scope(context); + v8::Handle global = context->Global(); + gin::Handle controller = + gin::CreateHandle(isolate, object); + // WrappableBase instance deletes itself in case of a wrapper + // creation failure, thus there is no need to delete |object|. + if (controller.IsEmpty()) + return NULL; + + global->Set(context, gin::StringToV8(isolate, object_name), controller.ToV8()) + .Check(); + return object; +} + +// static +GinNativeBridgeObject* GinNativeBridgeObject::InjectAnonymous( + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id) { + return new GinNativeBridgeObject(blink::MainThreadIsolate(), dispatcher, + object_id); +} + +GinNativeBridgeObject::GinNativeBridgeObject( + v8::Isolate* isolate, + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id) + : gin::NamedPropertyInterceptor(isolate, this), + dispatcher_(dispatcher), + object_id_(object_id), + frame_routing_id_(dispatcher_->routing_id()), + template_cache_(isolate) {} + +GinNativeBridgeObject::~GinNativeBridgeObject() {} + +gin::ObjectTemplateBuilder GinNativeBridgeObject::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return gin::Wrappable::GetObjectTemplateBuilder( + isolate) + .AddNamedPropertyInterceptor(); +} + +v8::Local GinNativeBridgeObject::GetNamedProperty( + v8::Isolate* isolate, + const std::string& property) { + std::map::iterator method_pos = + known_methods_.find(property); + if (method_pos == known_methods_.end()) { + if (!dispatcher_) + return v8::Local(); + + known_methods_[property] = + dispatcher_->HasNativeMethod(object_id_, property); + } + if (known_methods_[property]) + return GetFunctionTemplate(isolate, property) + ->GetFunction(isolate->GetCurrentContext()) + .FromMaybe(v8::Local()); + else + return v8::Local(); +} + +std::vector GinNativeBridgeObject::EnumerateNamedProperties( + v8::Isolate* isolate) { + std::set method_names; + if (dispatcher_) + dispatcher_->GetNativeMethods(object_id_, &method_names); + return std::vector(method_names.begin(), method_names.end()); +} + +v8::Local GinNativeBridgeObject::GetFunctionTemplate( + v8::Isolate* isolate, + const std::string& name) { + v8::Local function_template = template_cache_.Get(name); + if (!function_template.IsEmpty()) + return function_template; + function_template = gin::CreateFunctionTemplate( + isolate, + base::BindRepeating(&GinNativeFunctionInvocationHelper::Invoke, + base::Owned(new GinNativeFunctionInvocationHelper( + name, dispatcher_)))); + template_cache_.Set(name, function_template); + return function_template; +} + +gin::WrapperInfo GinNativeBridgeObject::kWrapperInfo = { + gin::kEmbedderNativeGin}; + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h new file mode 100644 index 0000000..4c5af69 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_object.h @@ -0,0 +1,74 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_OBJECT_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_OBJECT_H_ + +#include +#include +#include +#include + +#include "base/memory/weak_ptr.h" +#include "gin/handle.h" +#include "gin/interceptor.h" +#include "gin/object_template_builder.h" +#include "gin/wrappable.h" +#include "renderer/gin_native_bridge_dispatcher.h" +#include "v8/include/v8-util.h" + +namespace blink { +class WebFrame; +} + +namespace content { + +class GinNativeBridgeObject : public gin::Wrappable, + public gin::NamedPropertyInterceptor { + public: + static gin::WrapperInfo kWrapperInfo; + GinNativeBridgeDispatcher::ObjectID object_id() const { return object_id_; } + + // gin::Wrappable. + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + + // gin::NamedPropertyInterceptor + v8::Local GetNamedProperty(v8::Isolate* isolate, + const std::string& property) override; + std::vector EnumerateNamedProperties( + v8::Isolate* isolate) override; + + static GinNativeBridgeObject* InjectNamed( + blink::WebFrame* frame, + const base::WeakPtr& dispatcher, + const std::string& object_name, + GinNativeBridgeDispatcher::ObjectID object_id); + static GinNativeBridgeObject* InjectAnonymous( + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id); + + private: + GinNativeBridgeObject( + v8::Isolate* isolate, + const base::WeakPtr& dispatcher, + GinNativeBridgeDispatcher::ObjectID object_id); + ~GinNativeBridgeObject() override; + + GinNativeBridgeObject(const GinNativeBridgeObject&) = delete; + GinNativeBridgeObject& operator=(const GinNativeBridgeObject&) = delete; + + v8::Local GetFunctionTemplate(v8::Isolate* isolate, + const std::string& name); + + base::WeakPtr dispatcher_; + GinNativeBridgeDispatcher::ObjectID object_id_; + int frame_routing_id_; + std::map known_methods_; + v8::StdGlobalValueMap template_cache_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_OBJECT_H_ diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc new file mode 100644 index 0000000..209eb6a --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.cc @@ -0,0 +1,37 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "renderer/gin_native_bridge_value_converter.h" + +#include + +#include "base/values.h" +#include "gin/array_buffer.h" +#include "renderer/gin_native_bridge_object.h" + +namespace content { + +GinNativeBridgeValueConverter::GinNativeBridgeValueConverter() + : converter_(V8ValueConverter::Create()) { + converter_->SetDateAllowed(false); + converter_->SetRegExpAllowed(false); + converter_->SetFunctionAllowed(true); + converter_->SetStrategy(this); +} + +GinNativeBridgeValueConverter::~GinNativeBridgeValueConverter() {} + +v8::Local GinNativeBridgeValueConverter::ToV8Value( + const base::Value* value, + v8::Local context) const { + return converter_->ToV8Value(*value, context); +} + +std::unique_ptr GinNativeBridgeValueConverter::FromV8Value( + v8::Local value, + v8::Local context) const { + return converter_->FromV8Value(value, context); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h new file mode 100644 index 0000000..fb4185b --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_bridge_value_converter.h @@ -0,0 +1,36 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_VALUE_CONVERTER_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_VALUE_CONVERTER_H_ + +#include "content/common/content_export.h" +#include "content/public/renderer/v8_value_converter.h" + +namespace content { + +class GinNativeBridgeValueConverter + : public content::V8ValueConverter::Strategy { + public: + CONTENT_EXPORT GinNativeBridgeValueConverter(); + CONTENT_EXPORT ~GinNativeBridgeValueConverter() override; + + GinNativeBridgeValueConverter(const GinNativeBridgeValueConverter&) = delete; + GinNativeBridgeValueConverter& operator=( + const GinNativeBridgeValueConverter&) = delete; + + CONTENT_EXPORT v8::Local ToV8Value( + const base::Value* value, + v8::Local context) const; + CONTENT_EXPORT std::unique_ptr FromV8Value( + v8::Local value, + v8::Local context) const; + + private: + std::unique_ptr converter_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_BRIDGE_VALUE_CONVERTER_H_ diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc new file mode 100644 index 0000000..8906fdd --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.cc @@ -0,0 +1,108 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "renderer/gin_native_function_invocation_helper.h" + +#include "common/gin_native_bridge_value.h" +#include "content/public/renderer/v8_value_converter.h" +#include "renderer/gin_native_bridge_object.h" +#include "renderer/gin_native_bridge_value_converter.h" +#include "v8/include/v8-exception.h" + +namespace content { + +namespace { + +const char kMethodInvocationAsConstructorDisallowed[] = + "Native bridge method can't be invoked as a constructor"; +const char kMethodInvocationOnNonInjectedObjectDisallowed[] = + "Native bridge method can't be invoked on a non-injected object"; +const char kMethodInvocationErrorMessage[] = + "Native bridge method invocation error"; + +} // namespace + +GinNativeFunctionInvocationHelper::GinNativeFunctionInvocationHelper( + const std::string& method_name, + const base::WeakPtr& dispatcher) + : method_name_(method_name), + dispatcher_(dispatcher), + converter_(new GinNativeBridgeValueConverter()) {} + +GinNativeFunctionInvocationHelper::~GinNativeFunctionInvocationHelper() {} + +v8::Local GinNativeFunctionInvocationHelper::Invoke( + gin::Arguments* args) { + if (!dispatcher_) { + args->isolate()->ThrowException(v8::Exception::Error( + gin::StringToV8(args->isolate(), kMethodInvocationErrorMessage))); + return v8::Undefined(args->isolate()); + } + + if (args->IsConstructCall()) { + args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( + args->isolate(), kMethodInvocationAsConstructorDisallowed))); + return v8::Undefined(args->isolate()); + } + + content::GinNativeBridgeObject* object = NULL; + if (!args->GetHolder(&object) || !object) { + args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8( + args->isolate(), kMethodInvocationOnNonInjectedObjectDisallowed))); + return v8::Undefined(args->isolate()); + } + + base::Value::List arguments; + { + v8::HandleScope handle_scope(args->isolate()); + v8::Local context = args->isolate()->GetCurrentContext(); + v8::Local val; + while (args->GetNext(&val)) { + std::unique_ptr arg(converter_->FromV8Value(val, context)); + if (arg.get()) { + arguments.Append(base::Value::FromUniquePtrValue(std::move(arg))); + } else { + arguments.Append(base::Value()); + } + } + } + + GinNativeBridgeError error; + std::unique_ptr result = dispatcher_->InvokeNativeMethod( + object->object_id(), method_name_, arguments, &error); + if (!result.get()) { + args->isolate()->ThrowException(v8::Exception::Error( + gin::StringToV8(args->isolate(), GinNativeBridgeErrorToString(error)))); + return v8::Undefined(args->isolate()); + } + if (!result->is_blob()) { + return converter_->ToV8Value(result.get(), + args->isolate()->GetCurrentContext()); + } + + std::unique_ptr gin_value = + GinNativeBridgeValue::FromValue(result.get()); + + if (gin_value->IsType(GinNativeBridgeValue::TYPE_OBJECT_ID)) { + GinNativeBridgeObject* result = NULL; + GinNativeBridgeDispatcher::ObjectID object_id; + if (gin_value->GetAsObjectID(&object_id)) { + result = dispatcher_->GetObject(object_id); + } + if (result) { + gin::Handle controller = + gin::CreateHandle(args->isolate(), result); + if (controller.IsEmpty()) + return v8::Undefined(args->isolate()); + return controller.ToV8(); + } + } else if (gin_value->IsType(GinNativeBridgeValue::TYPE_NONFINITE)) { + float float_value; + gin_value->GetAsNonFinite(&float_value); + return v8::Number::New(args->isolate(), float_value); + } + return v8::Undefined(args->isolate()); +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h new file mode 100644 index 0000000..adca806 --- /dev/null +++ b/tizen_src/ewk/efl_integration/renderer/gin_native_function_invocation_helper.h @@ -0,0 +1,42 @@ +// Copyright 2017 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_FUNCTION_INVOCATION_HELPER_H_ +#define EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_FUNCTION_INVOCATION_HELPER_H_ + +#include +#include + +#include "base/memory/weak_ptr.h" +#include "gin/arguments.h" +#include "gin/handle.h" +#include "renderer/gin_native_bridge_dispatcher.h" + +namespace content { + +class GinNativeBridgeValueConverter; + +class GinNativeFunctionInvocationHelper { + public: + GinNativeFunctionInvocationHelper( + const std::string& method_name, + const base::WeakPtr& dispatcher); + ~GinNativeFunctionInvocationHelper(); + + GinNativeFunctionInvocationHelper(const GinNativeFunctionInvocationHelper&) = + delete; + GinNativeFunctionInvocationHelper& operator=( + const GinNativeFunctionInvocationHelper&) = delete; + + v8::Local Invoke(gin::Arguments* args); + + private: + std::string method_name_; + base::WeakPtr dispatcher_; + std::unique_ptr converter_; +}; + +} // namespace content + +#endif // EWK_EFL_INTEGRATION_RENDERER_GIN_NATIVE_FUNCTION_INVOCATION_HELPER_H_ -- 2.7.4 From 466cbd900fd1345e16151291208758c451d818aa Mon Sep 17 00:00:00 2001 From: "b.kiran" Date: Wed, 25 Jan 2023 10:26:48 +0530 Subject: [PATCH 10/16] [M108 Migration] Implement view port setting and zoom factor API This patch implement below preference setting and API for content scale. 1. As default meta view port enabling for mobile 2. Implement ewk api for view port set/get Reference: https://review.tizen.org/gerrit/c/278887 Change-Id: Id030ba049d55d46e55aaa2b8c75e27f3c7ed5fe9 Signed-off-by: Bakka Uday Kiran --- content/browser/web_contents/web_contents_impl.cc | 8 ++++++++ tizen_src/ewk/efl_integration/eweb_context.cc | 22 ++++++++++++++++++++++ tizen_src/ewk/efl_integration/eweb_context.h | 3 +++ .../efl_integration/private/ewk_context_private.cc | 8 ++++++++ .../efl_integration/private/ewk_context_private.h | 4 ++++ .../ewk/efl_integration/public/ewk_context.cc | 16 +++++++++++----- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 0f16da0..c2cd303 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -189,6 +189,7 @@ #if BUILDFLAG(IS_EFL) #include "content/browser/date_time_chooser_efl.h" +#include "tizen/system_info.h" #endif #if BUILDFLAG(IS_ANDROID) @@ -2829,6 +2830,13 @@ const blink::web_pref::WebPreferences WebContentsImpl::ComputeWebPreferences() { prefs.viewport_meta_enabled = false; } +#if BUILDFLAG(IS_EFL) + if (IsMobileProfile()) + prefs.viewport_meta_enabled = true; + + prefs.viewport_enabled |= prefs.viewport_meta_enabled; +#endif + prefs.spatial_navigation_enabled = command_line.HasSwitch(switches::kEnableSpatialNavigation); diff --git a/tizen_src/ewk/efl_integration/eweb_context.cc b/tizen_src/ewk/efl_integration/eweb_context.cc index e74e8a3..6e0ef15 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.cc +++ b/tizen_src/ewk/efl_integration/eweb_context.cc @@ -21,6 +21,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/dom_storage_context.h" +#include "content/public/browser/host_zoom_map.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_usage_info.h" @@ -31,6 +32,7 @@ #include "storage/browser/database/database_quota_client.h" #include "storage/browser/file_system/file_system_quota_client.h" #include "storage/browser/quota/quota_manager.h" +#include "third_party/blink/public/common/page/page_zoom.h" #include "ui/gl/gl_shared_context_efl.h" #if defined(ENABLE_PLUGINS) @@ -799,6 +801,26 @@ bool EWebContext::GetExtensibleAPI(const std::string& api_name) { return TizenExtensibleHost::GetInstance()->GetExtensibleAPI(api_name); } +void EWebContext::SetDefaultZoomFactor(double zoom_factor) { + content::HostZoomMap* host_zoom_map = + content::HostZoomMap::GetDefaultForBrowserContext(browser_context_.get()); + if (host_zoom_map) { + host_zoom_map->SetDefaultZoomLevel( + blink::PageZoomFactorToZoomLevel(zoom_factor)); + } +} + +double EWebContext::GetDefaultZoomFactor() const { + content::HostZoomMap* host_zoom_map = + content::HostZoomMap::GetDefaultForBrowserContext(browser_context_.get()); + if (host_zoom_map) { + return blink::PageZoomLevelToZoomFactor( + host_zoom_map->GetDefaultZoomLevel()); + } + + return -1.0; +} + void EWebContext::SetInterceptRequestCallback( Ewk_Context* ewk_context, Ewk_Context_Intercept_Request_Callback callback, diff --git a/tizen_src/ewk/efl_integration/eweb_context.h b/tizen_src/ewk/efl_integration/eweb_context.h index 04812da..560b3aa 100644 --- a/tizen_src/ewk/efl_integration/eweb_context.h +++ b/tizen_src/ewk/efl_integration/eweb_context.h @@ -174,6 +174,9 @@ class EWebContext { bool SetExtensibleAPI(const std::string& api_name, bool enable); bool GetExtensibleAPI(const std::string& api_name); + void SetDefaultZoomFactor(double zoom_factor); + double GetDefaultZoomFactor() const; + void SetInterceptRequestCallback( Ewk_Context* ewk_context, Ewk_Context_Intercept_Request_Callback callback, diff --git a/tizen_src/ewk/efl_integration/private/ewk_context_private.cc b/tizen_src/ewk/efl_integration/private/ewk_context_private.cc index cd4e31d..f10f434 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_context_private.cc @@ -269,6 +269,14 @@ void Ewk_Context::SetContextInterceptRequestCallback( impl->SetInterceptRequestCallback(this, callback, user_data); } +void Ewk_Context::SetDefaultZoomFactor(double zoom_factor) { + impl->SetDefaultZoomFactor(zoom_factor); +} + +double Ewk_Context::GetDefaultZoomFactor() const { + return impl->GetDefaultZoomFactor(); +} + #if BUILDFLAG(IS_TIZEN_TV) void Ewk_Context::SetApplicationType( const Ewk_Application_Type application_type) { diff --git a/tizen_src/ewk/efl_integration/private/ewk_context_private.h b/tizen_src/ewk/efl_integration/private/ewk_context_private.h index dce8618..d6daffc 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_context_private.h @@ -134,6 +134,10 @@ struct Ewk_Context : public base::RefCounted { Ewk_Context_Notification_Cancel_Callback cancel_callback, void* user_data); + // default zoom factor + void SetDefaultZoomFactor(double zoom_factor); + double GetDefaultZoomFactor() const; + void SetContextInterceptRequestCallback( Ewk_Context_Intercept_Request_Callback callback, void* user_data); diff --git a/tizen_src/ewk/efl_integration/public/ewk_context.cc b/tizen_src/ewk/efl_integration/public/ewk_context.cc index 3e3d06f..358a9679 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_context.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_context.cc @@ -974,11 +974,6 @@ void ewk_context_form_autofill_credit_card_changed_callback_set( LOG_EWK_API_MOCKUP(); } -void ewk_context_default_zoom_factor_set(Ewk_Context* context, - double zoom_factor) { - LOG_EWK_API_MOCKUP(); -} - void ewk_context_application_type_set( Ewk_Context* ewkContext, const Ewk_Application_Type applicationType) { @@ -1002,3 +997,14 @@ Ewk_Application_Type ewk_context_application_type_get(Ewk_Context* ewkContext) { return EWK_APPLICATION_TYPE_OTHER; #endif } + +void ewk_context_default_zoom_factor_set(Ewk_Context* context, + double zoom_factor) { + EINA_SAFETY_ON_NULL_RETURN(context); + context->SetDefaultZoomFactor(zoom_factor); +} + +double ewk_context_default_zoom_factor_get(Ewk_Context* context) { + EINA_SAFETY_ON_NULL_RETURN_VAL(context, -1.0); + return context->GetDefaultZoomFactor(); +} -- 2.7.4 From 13abb71fc3add7717ff7284a5b14bd19c45aa3ed Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Wed, 25 Jan 2023 17:38:03 +0530 Subject: [PATCH 11/16] [M108 Migration][Product TV] Support TV specific keys 1. Support keys on TV remote controller, like the media control keys: play, pause, stop. Mapping these keys from EFL key names to VKEYs. 2. Enable DomCode and DomKey conversion on standard profiles. Reference: https://review.tizen.org/gerrit/c/277836 https://review.tizen.org/gerrit/c/279232 https://review.tizen.org/gerrit/c/279340 Change-Id: Iefb7f9c30a5bdc623e77adf2034c3c1c8160cb6a Signed-off-by: Bakka Uday Kiran --- .../blink/renderer/platform/keyboard_codes.h | 357 +++++++++++++++++++++ .../renderer/platform/windows_keyboard_codes.h | 154 +++++++++ .../ui/ozone/platform/efl/efl_keycode_map.h | 99 ++++++ ui/events/event.cc | 3 + ui/events/event_utils.h | 5 + ui/events/events_default.cc | 8 + ui/events/keycodes/dom/dom_key_data.inc | 127 ++++++++ ui/events/keycodes/keyboard_codes_posix.h | 159 +++++++++ 8 files changed, 912 insertions(+) diff --git a/third_party/blink/renderer/platform/keyboard_codes.h b/third_party/blink/renderer/platform/keyboard_codes.h index b183f16..b5c7d2f 100644 --- a/third_party/blink/renderer/platform/keyboard_codes.h +++ b/third_party/blink/renderer/platform/keyboard_codes.h @@ -564,6 +564,363 @@ enum { // VKEY_OEM_CLEAR (FE) Clear key VKEY_OEM_CLEAR = VK_OEM_CLEAR, +#if BUILDFLAG(IS_TIZEN_TV) + // VKEY_RED (193) Red key on tv remote. + VKEY_RED = VK_RED, + + // VKEY_GREEN (194) Green key on tv remote. + VKEY_GREEN = VK_GREEN, + + // VKEY_YELLOW (195) Yellow key on tv remote. + VKEY_YELLOW = VK_YELLOW, + + // VKEY_BLUE (196) Blue key on tv remote. + VKEY_BLUE = VK_BLUE, + + // VKEY_GREY (197) Grey key on tv remote. + VKEY_GREY = VK_GREY, + + // VKEY_BROWN (198) Brown key on tv remote. + VKEY_BROWN = VK_BROWN, + + // VKEY_DTV_RETURN (2719) Return key on tv remote. + VKEY_DTV_RETURN = VK_DTV_RETURN, + + // VKEY_DTV_HOME (2757) + VKEY_DTV_HOME = VK_DTV_HOME, + + // VKEY_SOURCE (2758) + VKEY_SOURCE = VK_SOURCE, + + // VKEY_CH_LIST (2759) + VKEY_CH_LIST = VK_CH_LIST, + + // VKEY_POWER (199) + VKEY_POWER = VK_POWER, + + // VKEY_DTV_MENU (2795) + VKEY_DTV_MENU = VK_DTV_MENU, + + // VKEY_GUIDE (1CA) + VKEY_GUIDE = VK_GUIDE, + + // VKEY_ADDDEL (1AD) + VKEY_ADDDEL = VK_ADDDEL, + + // VKEY_AUTO_PROGRAM (1B9) + VKEY_AUTO_PROGRAM = VK_AUTO_PROGRAM, + + // VKEY_FAVCH (1B1) + VKEY_FAVCH = VK_FAVCH, + + // VKEY_BT_DUALVIEW (1BB) + VKEY_BT_DUALVIEW = VK_BT_DUALVIEW, + + // VKEY_SUB_TITLE (1CC) + VKEY_SUB_TITLE = VK_SUB_TITLE, + + // VKEY_REWIND (19c) Rewind key on tv remote. + VKEY_REWIND = VK_REWIND, + + // VKEY_STOP (19D) + VKEY_STOP = VK_STOP, + + // VKEY_RECORD (1A0) + VKEY_RECORD = VK_RECORD, + + // VKEY_FAST_FWD (1a1) Fast forward key on tv remote. + VKEY_FAST_FWD = VK_FAST_FWD, + + // VKEY_CHANNEL_UP (1ab) P+ key on tv remote. + VKEY_CHANNEL_UP = VK_CHANNEL_UP, + + // VKEY_CHANNEL_DOWN (1ac) P- key on tv remote. + VKEY_CHANNEL_DOWN = VK_CHANNEL_DOWN, + + // VKEY_INFO (1C9) + VKEY_INFO = VK_INFO, + + // VKEY_REPEAT (2799) + VKEY_REPEAT = VK_REPEAT, + + // VKEY_ASPECT (279C) + VKEY_ASPECT = VK_ASPECT, + + // VKEY_PMODE (279D) + VKEY_PMODE = VK_PMODE, + + // VKEY_HDMI (279F) + VKEY_HDMI = VK_HDMI, + + // VKEY_USBHUB_SWITCH (27A0) + VKEY_USBHUB_SWITCH = VK_USBHUB_SWITCH, + + // VKEY_EMANUAL (27A2) + VKEY_EMANUAL = VK_EMANUAL, + + // VKEY_TOOLS (2797) + VKEY_TOOLS = VK_TOOLS, + + // VKEY_MORE (27A4) + VKEY_MORE = VK_MORE, + + // VKEY_FACTORY (27A5) + VKEY_FACTORY = VK_FACTORY, + + // VKEY_TV (27A9) + VKEY_TV = VK_TV, + + // VKEY_DTV (27AA) + VKEY_DTV = VK_DTV, + + // VKEY_STB_POWER (27AB) + VKEY_STB_POWER = VK_STB_POWER, + + // VKEY_PANEL_DOWN (27AD) + VKEY_PANEL_DOWN = VK_PANEL_DOWN, + + // VKEY_CONVERGENCE (27AE) + VKEY_CONVERGENCE = VK_CONVERGENCE, + + // VKEY_BT_COLOR_MECHA (27AF) + VKEY_BT_COLOR_MECHA = VK_BT_COLOR_MECHA, + + // VKEY_STILL_PICTURE (27B0) + VKEY_STILL_PICTURE = VK_STILL_PICTURE, + + // VKEY_BT_TRIGGER (27B1) + VKEY_BT_TRIGGER = VK_BT_TRIGGER, + + // VKEY_BT_HOTVK (27B2) + VKEY_BT_HOTVK = VK_BT_HOTVK, + + // VKEY_BT_DEVICE (27B3) + VKEY_BT_DEVICE = VK_BT_DEVICE, + + // VKEY_BT_CONTENTSBAR (27B4) + VKEY_BT_CONTENTSBAR = VK_BT_CONTENTSBAR, + + // VKEY_GAME (27B5) + VKEY_GAME = VK_GAME, + + // VKEY_PIP_CHUP (27B7) + VKEY_PIP_CHUP = VK_PIP_CHUP, + + // VKEY_PIP_CHDOWN (27B8) + VKEY_PIP_CHDOWN = VK_PIP_CHDOWN, + + // VKEY_ANTENA (27B9) + VKEY_ANTENA = VK_ANTENA, + + // VKEY_PANEL_ENTER (27BB) + VKEY_PANEL_ENTER = VK_PANEL_ENTER, + + // VKEY_LINK (27BC) + VKEY_LINK = VK_LINK, + + // VKEY_PANEL_UP (27BD) + VKEY_PANEL_UP = VK_PANEL_UP, + + // VKEY_ANGLE (27C1) + VKEY_ANGLE = VK_ANGLE, + + // VKEY_WHEEL_LEFT (27C2) + VKEY_WHEEL_LEFT = VK_WHEEL_LEFT, + + // VKEY_WHEEL_RIGHT (27C3) + VKEY_WHEEL_RIGHT = VK_WHEEL_RIGHT, + + // VKEY_CONTENTS (2757) + VKEY_CONTENTS = VK_CONTENTS, + + // VKEY_PANEL_EXIT (27C5) + VKEY_PANEL_EXIT = VK_PANEL_EXIT, + + // VKEY_EXIT (27C6) + VKEY_EXIT = VK_EXIT, + + // VKEY_MBR_TV (27C7) + VKEY_MBR_TV = VK_MBR_TV, + + // VKEY_MBR_STB_GUIDE (27C8) + VKEY_MBR_STB_GUIDE = VK_MBR_STB_GUIDE, + + // VKEY_MBR_BD_POPUP (27C9) + VKEY_MBR_BD_POPUP = VK_MBR_BD_POPUP, + + // VKEY_MBR_BDDVD_POWER (27CA) + VKEY_MBR_BDDVD_POWER = VK_MBR_BDDVD_POWER, + + // VKEY_MBR_SETUP_FAILURE (27CB) + VKEY_MBR_SETUP_FAILURE = VK_MBR_SETUP_FAILURE, + + // VKEY_MBR_SETUP (27CC) + VKEY_MBR_SETUP = VK_MBR_SETUP, + + // VKEY_MBR_WATCH_TV (27CD) + VKEY_MBR_WATCH_TV = VK_MBR_WATCH_TV, + + // VKEY_PRECH (27CE) + VKEY_PRECH = VK_PRECH, + + // VKEY_RECOMMEND_SEARCH_TOGGLE (27D0) + VKEY_RECOMMEND_SEARCH_TOGGLE = VK_RECOMMEND_SEARCH_TOGGLE, + + // VKEY_BT_NUMBER (27D1) + VKEY_BT_NUMBER = VK_BT_NUMBER, + + // VKEY_16_9 (27D2) + VKEY_16_9 = VK_16_9, + + // VKEY_MTS (27D3) + VKEY_MTS = VK_MTS, + + // VKEY_SMODE (27D5) + VKEY_SMODE = VK_SMODE, + + // VKEY_3SPEED (27D6) + VKEY_3SPEED = VK_3SPEED, + + // VKEY_3D (27D7) + VKEY_3D = VK_3D, + + // VKEY_TTX_MIX (27D8) + VKEY_TTX_MIX = VK_TTX_MIX, + + // VKEY_SRSTSXT (27D9) + VKEY_SRSTSXT = VK_SRSTSXT, + + // VKEY_WIFI_PAIRING (27DA) + VKEY_WIFI_PAIRING = VK_WIFI_PAIRING, + + // VKEY_BT_SAMSUNG_APPS (27E3) + VKEY_BT_SAMSUNG_APPS = VK_BT_SAMSUNG_APPS, + + // VKEY_W_LINK (2757) + VKEY_W_LINK = VK_W_LINK, + + // VKEY_ESAVING (27E5) + VKEY_ESAVING = VK_ESAVING, + + // VKEY_TV_SNS (27E9) + VKEY_TV_SNS = VK_TV_SNS, + + // VKEY_DVR (27EA) + VKEY_DVR = VK_DVR, + + // VKEY_APP_LIST (27EB) + VKEY_APP_LIST = VK_APP_LIST, + + // VKEY_CAMERA (27EC) + VKEY_CAMERA = VK_CAMERA, + + // VKEY_CAPTION (27ED) + VKEY_CAPTION = VK_CAPTION, + + // VKEY_ZOOM1 (27EE) + VKEY_ZOOM1 = VK_ZOOM1, + + // VKEY_PANEL_PLUS (27EF) + VKEY_PANEL_PLUS = VK_PANEL_PLUS, + + // VKEY_BT_VOICE (27F0) + VKEY_BT_VOICE = VK_BT_VOICE, + + // VKEY_SEARCH (27F1) + VKEY_SEARCH = VK_SEARCH, + + // VKEY_PANEL_MINUS (27F3) + VKEY_PANEL_MINUS = VK_PANEL_MINUS, + + // VKEY_SOCCER_MODE (27F4) + VKEY_SOCCER_MODE = VK_SOCCER_MODE, + + // VKEY_FUNCTIONS_AMAZON (27F5) + VKEY_FUNCTIONS_AMAZON = VK_FUNCTIONS_AMAZON, + + // VKEY_AD (27F6) + VKEY_AD = VK_AD, + + // VKEY_REWIND_ (27F8) + VKEY_REWIND_ = VK_REWIND_, + + // VKEY_FF_ (27F9) + VKEY_FF_ = VK_FF_, + + // VKEY_FUNCTIONS_NETFLIX (27FA) + VKEY_FUNCTIONS_NETFLIX = VK_FUNCTIONS_NETFLIX, + + // VKEY_PIP_ONOFF (27FB) + VKEY_PIP_ONOFF = VK_PIP_ONOFF, + + // VKEY_MBR_WATCH_MOVIE (27FC) + VKEY_MBR_WATCH_MOVIE = VK_MBR_WATCH_MOVIE, + + // VKEY_MBR_STBBD_MENU (27FD) + VKEY_MBR_STBBD_MENU = VK_MBR_STBBD_MENU, + + // VKEY_MBR_SETUP_CONFIRM (27FE) + VKEY_MBR_SETUP_CONFIRM = VK_MBR_SETUP_CONFIRM, + + // VKEY_FAMILYHUB (27FF) + VKEY_FAMILYHUB = VK_FAMILYHUB, + + // VKEY_ANYVIEW (2800) + VKEY_ANYVIEW = VK_ANYVIEW, + + // VKEY_PAGE_LEFT (2809) + VKEY_PAGE_LEFT = VK_PAGE_LEFT, + + // VKEY_PAGE_RIGHT (280A) + VKEY_PAGE_RIGHT = VK_PAGE_RIGHT, + + // VKEY_SOFT_WAKE_UP (2804) + VKEY_SOFT_WAKE_UP = VK_SOFT_WAKE_UP, + + // VKEY_PANEL_ON (280B) + VKEY_PANEL_ON = VK_PANEL_ON, + + // VKEY_PLAY_BACK (280C) + VKEY_PLAY_BACK = VK_PLAY_BACK, + + // VKEY_EXTRA (280D) + VKEY_EXTRA = VK_EXTRA, + + // VKEY_COLOR (2891) + VKEY_COLOR = VK_COLOR, + + // VKEY_ALARM (28B2) + VKEY_ALARM = VK_ALARM, + + // VKEY_HOTEL_MOVIES (28FE) + VKEY_HOTEL_MOVIES = VK_HOTEL_MOVIES, + + // VKEY_HOTEL_LANGUAGE (28FF) + VKEY_HOTEL_LANGUAGE = VK_HOTEL_LANGUAGE, + + // VKEY_HOTEL_TV_GUIDE (2900) + VKEY_HOTEL_TV_GUIDE = VK_HOTEL_TV_GUIDE, + + // VKEY_HOTEL_APPS_GUEST (2901) + VKEY_HOTEL_APPS_GUEST = VK_HOTEL_APPS_GUEST, + + // VKEY_NOISE_REDUCTION (2917) + VKEY_NOISE_REDUCTION = VK_NOISE_REDUCTION, + + // VKEY_NR (2919) + VKEY_NR = VK_NR, + + // VKEY_HOTEL_ROOM_CONTROL (291A) + VKEY_HOTEL_ROOM_CONTROL = VK_HOTEL_ROOM_CONTROL, + + // VKEY_IME_DONE (FF60) Done key on TV IME panel + VKEY_IME_DONE = VK_IME_DONE, + + // VKEY_IME_CANCEL (FF69) Cancel key on TV IME panel + VKEY_IME_CANCEL = VK_IME_CANCEL, + +#endif + VKEY_UNKNOWN = 0 }; diff --git a/third_party/blink/renderer/platform/windows_keyboard_codes.h b/third_party/blink/renderer/platform/windows_keyboard_codes.h index fea3fa6..dcfd4d3 100644 --- a/third_party/blink/renderer/platform/windows_keyboard_codes.h +++ b/third_party/blink/renderer/platform/windows_keyboard_codes.h @@ -142,9 +142,11 @@ #ifndef VK_DELETE #define VK_DELETE 0x2E // DEL key #endif +#if !BUILDFLAG(IS_TIZEN_TV) #ifndef VK_HELP #define VK_HELP 0x2F // HELP key #endif +#endif #define VK_0 0x30 #define VK_1 0x31 @@ -334,6 +336,158 @@ #define VK_OEM_CLEAR 0xFE // Clear key +#if BUILDFLAG(IS_TIZEN_TV) +// TV keys on remote controller. +// Virtual keys defined in http://www.atsc.org/cms/standards/a100/a_100_2.pdf +// Same volume virtual keys are already defined in Windows virtual keys but we +// overlap with the keys defined in DTV. +#undef VK_PLAY +#undef VK_VOLUME_UP +#undef VK_VOLUME_DOWN +#undef VK_VOLUME_MUTE +#undef VK_SLEEP +#undef VK_CLEAR + +#define VK_RED 0x193 +#define VK_GREEN 0x194 +#define VK_YELLOW 0x195 +#define VK_BLUE 0x196 +#define VK_GREY 0x197 +#define VK_BROWN 0x198 +#define VK_DTV_RETURN 0x2719 +#define VK_DTV_HOME 0x2757 +#define VK_SOURCE 0x2758 +#define VK_CH_LIST 0x2759 +#define VK_POWER 0x199 +#define VK_DTV_MENU 0x2795 +#define VK_GUIDE 0x1CA +#define VK_ADDDEL 0x1AD +#define VK_AUTO_PROGRAM 0x1B9 +#define VK_FAVCH 0x1B1 +#define VK_BT_DUALVIEW 0x1BB +#define VK_SUB_TITLE 0x1CC +#define VK_REWIND 0x19C +#define VK_STOP 0x19D +#define VK_PLAY 0x19F +#define VK_RECORD 0x1A0 +#define VK_FAST_FWD 0x1A1 +#define VK_CHANNEL_UP 0x1AB +#define VK_CHANNEL_DOWN 0x1AC +#define VK_VOLUME_UP 0x1BF +#define VK_VOLUME_DOWN 0x1C0 +#define VK_VOLUME_MUTE 0x1C1 +#define VK_INFO 0x1C9 +#define VK_REPEAT 0x2799 +#define VK_ASPECT 0x279C +#define VK_PMODE 0x279D +#define VK_HDMI 0x279F +#define VK_USBHUB_SWITCH 0x27A0 +#define VK_EMANUAL 0x27A2 +#define VK_TOOLS 0x2797 +#define VK_MORE 0x27A4 +#define VK_FACTORY 0x27A5 +#define VK_SLEEP 0x27A6 +#define VK_TV 0x27A9 +#define VK_DTV 0x27AA +#define VK_STB_POWER 0x27AB +#define VK_PANEL_DOWN 0x27AD +#define VK_CONVERGENCE 0x27AE +#define VK_BT_COLOR_MECHA 0x27AF +#define VK_STILL_PICTURE 0x27B0 +#define VK_BT_TRIGGER 0x27B1 +#define VK_BT_HOTVK 0x27B2 +#define VK_BT_DEVICE 0x27B3 +#define VK_BT_CONTENTSBAR 0x27B4 +#define VK_GAME 0x27B5 +#define VK_PIP_CHUP 0x27B7 +#define VK_PIP_CHDOWN 0x27B8 +#define VK_ANTENA 0x27B9 +#define VK_PANEL_ENTER 0x27BB +#define VK_LINK 0x27BC +#define VK_PANEL_UP 0x27BD + +#define VK_ANGLE 0x27C1 +#define VK_WHEEL_LEFT 0x27C2 +#define VK_WHEEL_RIGHT 0x27C3 +#define VK_CONTENTS 0x2757 +#define VK_PANEL_EXIT 0x27C5 +#define VK_EXIT 0x27C6 + +#define VK_MBR_TV 0x27C7 +#define VK_MBR_STB_GUIDE 0x27C8 +#define VK_MBR_BD_POPUP 0x27C9 +#define VK_MBR_BDDVD_POWER 0x27CA +#define VK_MBR_SETUP_FAILURE 0x27CB +#define VK_MBR_SETUP 0x27CC +#define VK_MBR_WATCH_TV 0x27CD + +#define VK_PRECH 0x27CE +#define VK_RECOMMEND_SEARCH_TOGGLE 0x27D0 +#define VK_BT_NUMBER 0x27D1 +#define VK_16_9 0x27D2 +#define VK_MTS 0x27D3 +#define VK_SMODE 0x27D5 +#define VK_3SPEED 0x27D6 +#define VK_3D 0x27D7 +#define VK_TTX_MIX 0x27D8 +#define VK_SRSTSXT 0x27D9 +#define VK_WIFI_PAIRING 0x27DA +#define VK_BT_SAMSUNG_APPS 0x27E3 +#define VK_W_LINK 0x2757 +#define VK_ESAVING 0x27E5 +#define VK_CLEAR 0x27E6 +#define VK_TV_SNS 0x27E9 +#define VK_DVR 0x27EA +#define VK_APP_LIST 0x27EB +#define VK_CAMERA 0x27EC +#define VK_CAPTION 0x27ED +#define VK_ZOOM1 0x27EE +#define VK_PANEL_PLUS 0x27EF +#define VK_BT_VOICE 0x27F0 +#define VK_SEARCH 0x27F1 +#define VK_PANEL_MINUS 0x27F3 +#define VK_SOCCER_MODE 0x27F4 +#define VK_FUNCTIONS_AMAZON 0x27F5 +#define VK_AD 0x27F6 +#define VK_REWIND_ 0x27F8 +#define VK_FF_ 0x27F9 +#define VK_FUNCTIONS_NETFLIX 0x27FA +#define VK_PIP_ONOFF 0x27FB +#define VK_MBR_WATCH_MOVIE 0x27FC +#define VK_MBR_STBBD_MENU 0x27FD +#define VK_MBR_SETUP_CONFIRM 0x27FE +#define VK_FAMILYHUB 0x27FF +#define VK_ANYVIEW 0x2800 +#define VK_PAGE_LEFT 0x2809 +#define VK_PAGE_RIGHT 0x280A + +#define VK_SOFT_WAKE_UP 0x2804 +#define VK_PANEL_ON 0x280B +#define VK_PLAY_BACK 0x280C +#define VK_EXTRA 0x280D +#define VK_COLOR 0x2891 + +#define VK_ALARM 0x28B2 +#define VK_HOTEL_MOVIES 0x28FE +#define VK_HOTEL_LANGUAGE 0x28FF +#define VK_HOTEL_TV_GUIDE 0x2900 +#define VK_HOTEL_APPS_GUEST 0x2901 +#define VK_NOISE_REDUCTION 0x2917 +#define VK_HELP 0x2918 +#define VK_NR 0x2919 +#define VK_HOTEL_ROOM_CONTROL 0x291A + +#define VK_IME_DONE \ + 0xFF60 // keyname of IME Done button is Select. but Select(0xFF60) is only + // Tizen TV IME keyname defined by ISF, there is no X Server keycode. + // 0xFF60 is ISF keycode. +#define VK_IME_CANCEL \ + 0xFF69 // keyname of IME Cancel button is Cancel. but Select(0xFF69) is only + // Tizen TV IME keyname defined by ISF, there is no X Server keycode. + // 0xFF69 is ISF keycode. + +#endif // #if BUILDFLAG(IS_TIZEN_TV) + #endif // VK_UNKNOWN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WINDOWS_KEYBOARD_CODES_H_ diff --git a/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_keycode_map.h b/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_keycode_map.h index a83ceac..4c3e9ef 100644 --- a/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_keycode_map.h +++ b/tizen_src/chromium_impl/ui/ozone/platform/efl/efl_keycode_map.h @@ -111,6 +111,105 @@ static ui::KeyboardCode UIKeyCodeFromEflKey(const char* key) { {"XF86KbdBrightnessDown", ui::VKEY_KBD_BRIGHTNESS_DOWN}, {"XF86KbdBrightnessUp", ui::VKEY_KBD_BRIGHTNESS_UP}, +#if BUILDFLAG(IS_TIZEN_TV) + {"XF86Back", ui::VKEY_DTV_RETURN}, + {"XF86RaiseChannel", ui::VKEY_CHANNEL_UP}, + {"XF86LowerChannel", ui::VKEY_CHANNEL_DOWN}, + {"XF86AudioRewind", ui::VKEY_REWIND}, + {"XF86AudioPause", ui::VKEY_PAUSE}, + {"XF86AudioNext", ui::VKEY_FAST_FWD}, + {"XF86AudioRecord", ui::VKEY_RECORD}, {"XF86AudioPlay", ui::VKEY_PLAY}, + {"XF86AudioStop", ui::VKEY_STOP}, {"XF86Red", ui::VKEY_RED}, + {"XF86Green", ui::VKEY_GREEN}, {"XF86Yellow", ui::VKEY_YELLOW}, + {"XF86Blue", ui::VKEY_BLUE}, {"XF86Grey", ui::VKEY_GREY}, + {"XF86Brown", ui::VKEY_BROWN}, {"XF86Info", ui::VKEY_INFO}, + {"XF86Home", ui::VKEY_DTV_HOME}, {"XF86Display", ui::VKEY_SOURCE}, + {"XF86ChannelList", ui::VKEY_CH_LIST}, + {"XF86MBRRepeat", ui::VKEY_REPEAT}, + {"XF86PictureSize", ui::VKEY_ASPECT}, + {"XF86PictureMode", ui::VKEY_PMODE}, {"XF86Hdmi", ui::VKEY_HDMI}, + {"XF86UsbHub", ui::VKEY_USBHUB_SWITCH}, + {"XF86EManual", ui::VKEY_EMANUAL}, {"XF86SimpleMenu", ui::VKEY_TOOLS}, + {"XF86More", ui::VKEY_MORE}, {"XF86FactoryMode", ui::VKEY_FACTORY}, + {"XF86Sleep", ui::VKEY_SLEEP}, {"XF86TV", ui::VKEY_TV}, + {"XF86DTV", ui::VKEY_DTV}, {"XF86STBPower", ui::VKEY_STB_POWER}, + {"XF86PanelDown", ui::VKEY_PANEL_DOWN}, + {"XF86WWW", ui::VKEY_CONVERGENCE}, + {"XF86BTColorMecha", ui::VKEY_BT_COLOR_MECHA}, + {"XF86StillPicture", ui::VKEY_STILL_PICTURE}, + {"XF86BTPairing", ui::VKEY_BT_TRIGGER}, + {"XF86BTHotkey", ui::VKEY_BT_HOTVK}, + {"XF86BTDevice", ui::VKEY_BT_DEVICE}, + {"XF86BTContentsBar", ui::VKEY_BT_CONTENTSBAR}, + {"XF86Game", ui::VKEY_GAME}, {"XF86PIPChannelUp", ui::VKEY_PIP_CHUP}, + {"XF86PIPChannelDown", ui::VKEY_PIP_CHDOWN}, + {"XF86Antena", ui::VKEY_ANTENA}, + {"XF86PanelEnter", ui::VKEY_PANEL_ENTER}, + {"XF86MBRLink", ui::VKEY_LINK}, {"XF86PanelUp", ui::VKEY_PANEL_UP}, + {"XF86Game3D", ui::VKEY_ANGLE}, + {"XF86WheelLeftKey", ui::VKEY_WHEEL_LEFT}, + {"XF86WheelRightKey", ui::VKEY_WHEEL_RIGHT}, + {"XF86PanelExit", ui::VKEY_PANEL_EXIT}, {"XF86Exit", ui::VKEY_EXIT}, + {"XF86MBRTV", ui::VKEY_MBR_TV}, + {"XF86MBRSTBGuide", ui::VKEY_MBR_STB_GUIDE}, + {"XF86MBRBDPopup", ui::VKEY_MBR_BD_POPUP}, + {"XF86MBRBDDVDPower", ui::VKEY_MBR_BDDVD_POWER}, + {"XF86MBRSetupFailure", ui::VKEY_MBR_SETUP_FAILURE}, + {"XF86MBRSetup", ui::VKEY_MBR_SETUP}, + {"XF86MBRWatchTV", ui::VKEY_MBR_WATCH_TV}, + {"XF86PreviousChannel", ui::VKEY_PRECH}, + {"XF86Recommend", ui::VKEY_RECOMMEND_SEARCH_TOGGLE}, + {"XF86NumberPad", ui::VKEY_BT_NUMBER}, + {"XF86AspectRatio169", ui::VKEY_16_9}, {"XF86MTS", ui::VKEY_MTS}, + {"XF86SoundMode", ui::VKEY_SMODE}, {"XF863XSpeed", ui::VKEY_3SPEED}, + {"XF863D", ui::VKEY_3D}, {"XF86TTXMIX", ui::VKEY_TTX_MIX}, + {"XF86SRSSXT", ui::VKEY_SRSTSXT}, + {"XF86WIFIPairing", ui::VKEY_WIFI_PAIRING}, + {"XF86BTApps", ui::VKEY_BT_SAMSUNG_APPS}, + {"XF86EnergySaving", ui::VKEY_ESAVING}, + {"XF86MBRClear", ui::VKEY_CLEAR}, {"XF86TVSNS", ui::VKEY_TV_SNS}, + {"XF86DVR", ui::VKEY_DVR}, {"XF86Apps", ui::VKEY_APP_LIST}, + {"XF86Camera", ui::VKEY_CAMERA}, {"XF86Caption", ui::VKEY_CAPTION}, + {"XF86ZoomIn", ui::VKEY_ZOOM1}, {"XF86PanelPlus", ui::VKEY_PANEL_PLUS}, + {"XF86BTVoice", ui::VKEY_BT_VOICE}, {"XF86Search", ui::VKEY_SEARCH}, + {"XF86PanelMinus", ui::VKEY_PANEL_MINUS}, + {"XF86SoccerMode", ui::VKEY_SOCCER_MODE}, + {"XF86Amazon", ui::VKEY_FUNCTIONS_AMAZON}, + {"XF86AudioDescription", ui::VKEY_AD}, + {"XF86PreviousChapter", ui::VKEY_REWIND_}, + {"XF86NextChapter", ui::VKEY_FF_}, + {"XF86Netflix", ui::VKEY_FUNCTIONS_NETFLIX}, + {"XF86PIP", ui::VKEY_PIP_ONOFF}, + {"XF86MBRWatchMovie", ui::VKEY_MBR_WATCH_MOVIE}, + {"XF86MBRMenu", ui::VKEY_MBR_STBBD_MENU}, + {"XF86MBRConfirm", ui::VKEY_MBR_SETUP_CONFIRM}, + {"XF86FamilyHub", ui::VKEY_FAMILYHUB}, + {"XF86HDMICEC", ui::VKEY_ANYVIEW}, {"XF86LeftPage", ui::VKEY_PAGE_LEFT}, + {"XF86RightPage", ui::VKEY_PAGE_RIGHT}, + {"XF86PowerOff", ui::VKEY_POWER}, {"XF86SysMenu", ui::VKEY_DTV_MENU}, + {"XF86ChannelGuide", ui::VKEY_GUIDE}, + {"XF86ChannelAddDel", ui::VKEY_ADDDEL}, + {"XF86ChannelAutoTune", ui::VKEY_AUTO_PROGRAM}, + {"XF86FavoriteChannel", ui::VKEY_FAVCH}, + {"XF86DualView", ui::VKEY_BT_DUALVIEW}, + {"XF86Subtitle", ui::VKEY_SUB_TITLE}, + {"XF86SoftWakeup", ui::VKEY_SOFT_WAKE_UP}, + {"XF86PlayBack", ui::VKEY_PLAY_BACK}, {"XF86ExtraApp", ui::VKEY_EXTRA}, + {"XF86Color", ui::VKEY_COLOR}, + + {"XF86NoiseReduction", ui::VKEY_NOISE_REDUCTION}, + {"XF86Help", ui::VKEY_HELP}, + {"XF86HotelAppsGuest", ui::VKEY_HOTEL_APPS_GUEST}, + {"XF86HotelMovies", ui::VKEY_HOTEL_MOVIES}, + {"XF86HotelLanguage", ui::VKEY_HOTEL_LANGUAGE}, + {"XF86HotelTVGuide", ui::VKEY_HOTEL_TV_GUIDE}, {"XF86NR", ui::VKEY_NR}, + {"XF86HotelRoomControl", ui::VKEY_HOTEL_ROOM_CONTROL}, + {"XF86Alarm", ui::VKEY_ALARM}, + + // TV IME Keys + {"Select", ui::VKEY_RETURN}, {"Clear", ui::VKEY_DELETE}, +#endif + {"0", ui::VKEY_0}, {"1", ui::VKEY_1}, {"2", ui::VKEY_2}, {"3", ui::VKEY_3}, {"4", ui::VKEY_4}, {"5", ui::VKEY_5}, {"6", ui::VKEY_6}, {"7", ui::VKEY_7}, {"8", ui::VKEY_8}, diff --git a/ui/events/event.cc b/ui/events/event.cc index 2721ef0..21cafe7 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc @@ -825,6 +825,9 @@ KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags) scan_code_(ScanCodeFromNative(native_event)), #endif // defined(USE_OZONE) code_(CodeFromNative(native_event)), +#if BUILDFLAG(IS_TIZEN) + key_(KeyFromNative(native_event)), +#endif // BUILDFLAG(IS_TIZEN) #if BUILDFLAG(IS_EFL) is_system_key(IsSystemKeyFromNative(native_event)), #endif diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h index 0fa0079..ca4e631 100644 --- a/ui/events/event_utils.h +++ b/ui/events/event_utils.h @@ -116,6 +116,11 @@ KeyboardCodeFromNative(const PlatformEvent& native_event); // keyboard) from a native event. EVENTS_EXPORT DomCode CodeFromNative(const PlatformEvent& native_event); +#if BUILDFLAG(IS_TIZEN) +// Returns the DOM KeyboardEvent key (layout meaning) from a native event. +EVENTS_EXPORT DomKey KeyFromNative(const PlatformEvent& native_event); +#endif + #if BUILDFLAG(IS_EFL) // Returns the |is_system_key| value from a native event. EVENTS_EXPORT bool IsSystemKeyFromNative(const PlatformEvent& native_event); diff --git a/ui/events/events_default.cc b/ui/events/events_default.cc index be759cb..c434740 100644 --- a/ui/events/events_default.cc +++ b/ui/events/events_default.cc @@ -83,6 +83,14 @@ DomCode CodeFromNative(const PlatformEvent& native_event) { return event->code(); } +#if BUILDFLAG(IS_TIZEN) +DomKey KeyFromNative(const PlatformEvent& native_event) { + const ui::KeyEvent* event = static_cast(native_event); + DCHECK(event->IsKeyEvent()); + return event->GetDomKey(); +} +#endif + #if BUILDFLAG(IS_EFL) bool IsSystemKeyFromNative(const PlatformEvent& native_event) { const ui::KeyEvent* event = static_cast(native_event); diff --git a/ui/events/keycodes/dom/dom_key_data.inc b/ui/events/keycodes/dom/dom_key_data.inc index 286fc32..218bd58 100644 --- a/ui/events/keycodes/dom/dom_key_data.inc +++ b/ui/events/keycodes/dom/dom_key_data.inc @@ -536,4 +536,131 @@ DOM_KEY_MAP_DECLARATION { DOM_KEY_MAP("VideoModeNext", VIDEO_MODE_NEXT, 0x0D4C), DOM_KEY_MAP("Wink", WINK, 0x0D4D), DOM_KEY_MAP("ZoomToggle", ZOOM_TOGGLE, 0x0D4E), + +#if BUILDFLAG(IS_TIZEN_TV) + // ================================================================== + // EFL Key + // http://mosaic.sec.samsung.net/club/club.menu.bbs.read.screen?page_num=1&p_club_id=466&p_menu_id=107&p_group_id=80&search_field=&search_query=&search_category=&message_id=4764929 + // ================================================================== + + // Key Enum Value + DOM_KEY_MAP("XF86Back", XF86Back, 0x2719), + DOM_KEY_MAP("XF86RaiseChannel", XF86RaiseChannel, 0x01AB), + DOM_KEY_MAP("XF86LowerChannel", XF86LowerChannel, 0x01AC), + DOM_KEY_MAP("XF86AudioRewind", XF86AudioRewind, 0x019C), + DOM_KEY_MAP("XF86AudioPause", XF86AudioPause, 0x0013), + DOM_KEY_MAP("XF86AudioNext", XF86AudioNext, 0x01A1), + DOM_KEY_MAP("XF86AudioRecord", XF86AudioRecord, 0x01A0), + DOM_KEY_MAP("XF86AudioPlay", XF86AudioPlay, 0x00FA), + DOM_KEY_MAP("XF86AudioStop", XF86AudioStop, 0x019D), + DOM_KEY_MAP("XF86Red", XF86Red, 0x0193), + DOM_KEY_MAP("XF86Green", XF86Green, 0x0194), + DOM_KEY_MAP("XF86Yellow", XF86Yellow, 0x0195), + DOM_KEY_MAP("XF86Blue", XF86Blue, 0x0196), + DOM_KEY_MAP("XF86Info", XF86Info, 0x01C9), + DOM_KEY_MAP("XF86Home", XF86Home, 0x2757), + DOM_KEY_MAP("XF86Display", XF86Display, 0x2758), + DOM_KEY_MAP("XF86ChannelList", XF86ChannelList, 0x2759), + DOM_KEY_MAP("XF86MBRRepeat", XF86MBRRepeat, 0x2799), + DOM_KEY_MAP("XF86PictureSize", XF86PictureSize, 0x279C), + DOM_KEY_MAP("XF86PictureMode", XF86PictureMode, 0x279D), + DOM_KEY_MAP("XF86Hdmi", XF86Hdmi, 0x279F), + DOM_KEY_MAP("XF86UsbHub", XF86UsbHub, 0x27A0), + DOM_KEY_MAP("XF86EManual", XF86EManual, 0x27A2), + DOM_KEY_MAP("XF86SimpleMenu", XF86SimpleMenu, 0x2797), + DOM_KEY_MAP("XF86More", XF86More, 0x27A4), + DOM_KEY_MAP("XF86FactoryMode", XF86FactoryMode, 0x27A5), + DOM_KEY_MAP("XF86Sleep", XF86Sleep, 0x27A6), + DOM_KEY_MAP("XF86TV", XF86TV, 0x27A9), + DOM_KEY_MAP("XF86DTV", XF86DTV, 0x27AA), + DOM_KEY_MAP("XF86STBPower", XF86STBPower, 0x27AB), + DOM_KEY_MAP("XF86PanelDown", XF86PanelDown, 0x27AD), + DOM_KEY_MAP("XF86WWW", XF86WWW, 0x27AE), + DOM_KEY_MAP("XF86BTColorMecha", XF86BTColorMecha, 0x27AF), + DOM_KEY_MAP("XF86StillPicture", XF86StillPicture, 0x27B0), + DOM_KEY_MAP("XF86BTPairing", XF86BTPairing, 0x27B1), + DOM_KEY_MAP("XF86BTHotkey", XF86BTHotkey, 0x27B2), + DOM_KEY_MAP("XF86BTDevice", XF86BTDevice, 0x27B3), + DOM_KEY_MAP("XF86BTContentsBar", XF86BTContentsBar, 0x27B4), + DOM_KEY_MAP("XF86Game", XF86Game, 0x27B5), + DOM_KEY_MAP("XF86PIPChannelUp", XF86PIPChannelUp, 0x27B7), + DOM_KEY_MAP("XF86PIPChannelDown", XF86PIPChannelDown, 0x27B8), + DOM_KEY_MAP("XF86Antena", XF86Antena, 0x27B9), + DOM_KEY_MAP("XF86PanelEnter", XF86PanelEnter, 0x27BB), + DOM_KEY_MAP("XF86MBRLink", XF86MBRLink, 0x27BC), + DOM_KEY_MAP("XF86PanelUp", XF86PanelUp, 0x27BD), + DOM_KEY_MAP("XF86Game3D", XF86Game3D, 0x27C1), + DOM_KEY_MAP("XF86WheelLeftKey", XF86WheelLeftKey, 0x27C2), + DOM_KEY_MAP("XF86WheelRightKey", XF86WheelRightKey, 0x27C3), + DOM_KEY_MAP("XF86PanelExit", XF86PanelExit, 0x27C5), + DOM_KEY_MAP("XF86Exit", XF86Exit, 0x27C6), + DOM_KEY_MAP("XF86MBRTV", XF86MBRTV, 0x27C7), + DOM_KEY_MAP("XF86MBRSTBGuide", XF86MBRSTBGuide, 0x27C8), + DOM_KEY_MAP("XF86MBRBDPopup", XF86MBRBDPopup, 0x27C9), + DOM_KEY_MAP("XF86MBRBDDVDPower", XF86MBRBDDVDPower, 0x27CA), + DOM_KEY_MAP("XF86MBRSetupFailure", XF86MBRSetupFailure, 0x27CB), + DOM_KEY_MAP("XF86MBRSetup", XF86MBRSetup, 0x27CC), + DOM_KEY_MAP("XF86MBRWatchTV", XF86MBRWatchTV, 0x27CD), + DOM_KEY_MAP("XF86PreviousChannel", XF86PreviousChannel, 0x27CE), + DOM_KEY_MAP("XF86Recommend", XF86Recommend, 0x27D0), + DOM_KEY_MAP("XF86NumberPad", XF86NumberPad, 0x27D1), + DOM_KEY_MAP("XF86AspectRatio169", XF86AspectRatio169, 0x27D2), + DOM_KEY_MAP("XF86MTS", XF86MTS, 0x27D3), + DOM_KEY_MAP("XF86SoundMode", XF86SoundMode, 0x27D5), + DOM_KEY_MAP("XF863XSpeed", XF863XSpeed, 0x27D6), + DOM_KEY_MAP("XF863D", XF863D, 0x27D7), + DOM_KEY_MAP("XF86TTXMIX", XF86TTXMIX, 0x27D8), + DOM_KEY_MAP("XF86SRSSXT", XF86SRSSXT, 0x27D9), + DOM_KEY_MAP("XF86WIFIPairing", XF86WIFIPairing, 0x27DA), + DOM_KEY_MAP("XF86BTApps", XF86BTApps, 0x27E3), + DOM_KEY_MAP("XF86EnergySaving", XF86EnergySaving, 0x27E5), + DOM_KEY_MAP("XF86MBRClear", XF86MBRClear, 0x000C), + DOM_KEY_MAP("XF86TVSNS", XF86TVSNS, 0x27E9), + DOM_KEY_MAP("XF86DVR", XF86DVR, 0x27EA), + DOM_KEY_MAP("XF86Apps", XF86Apps, 0x27EB), + DOM_KEY_MAP("XF86Camera", XF86Camera, 0x27EC), + DOM_KEY_MAP("XF86Caption", XF86Caption, 0x27ED), + DOM_KEY_MAP("XF86ZoomIn", XF86ZoomIn, 0x27EE), + DOM_KEY_MAP("XF86PanelPlus", XF86PanelPlus, 0x27EF), + DOM_KEY_MAP("XF86BTVoice", XF86BTVoice, 0x27F0), + DOM_KEY_MAP("XF86Search", XF86Search, 0x27F1), + DOM_KEY_MAP("XF86PanelMinus", XF86PanelMinus, 0x27F3), + DOM_KEY_MAP("XF86SoccerMode", XF86SoccerMode, 0x27F4), + DOM_KEY_MAP("XF86Amazon", XF86Amazon, 0x27F5), + DOM_KEY_MAP("XF86AudioDescription", XF86AudioDescription, 0x27F6), + DOM_KEY_MAP("XF86PreviousChapter", XF86PreviousChapter, 0x27F8), + DOM_KEY_MAP("XF86NextChapter", XF86NextChapter, 0x27F9), + DOM_KEY_MAP("XF86Netflix", XF86Netflix, 0x27FA), + DOM_KEY_MAP("XF86PIP", XF86PIP, 0x27FB), + DOM_KEY_MAP("XF86MBRWatchMovie", XF86MBRWatchMovie, 0x27FC), + DOM_KEY_MAP("XF86MBRMenu", XF86MBRMenu, 0x27FD), + DOM_KEY_MAP("XF86MBRConfirm", XF86MBRConfirm, 0x27FE), + DOM_KEY_MAP("XF86FamilyHub", XF86FamilyHub, 0x27FF), + DOM_KEY_MAP("XF86HDMICEC", XF86HDMICEC, 0x2800), + DOM_KEY_MAP("XF86LeftPage", XF86LeftPage, 0x2809), + DOM_KEY_MAP("XF86RightPage", XF86RightPage, 0x280A), + DOM_KEY_MAP("XF86PowerOff", XF86PowerOff, 0x0199), + DOM_KEY_MAP("XF86SysMenu", XF86SysMenu, 0x2795), + DOM_KEY_MAP("XF86ChannelGuide", XF86ChannelGuide, 0x01CA), + DOM_KEY_MAP("XF86ChannelAddDel", XF86ChannelAddDel, 0x01AD), + DOM_KEY_MAP("XF86ChannelAutoTune", XF86ChannelAutoTune, 0x01B9), + DOM_KEY_MAP("XF86FavoriteChannel", XF86FavoriteChannel, 0x01B1), + DOM_KEY_MAP("XF86DualView", XF86DualView, 0x01BB), + DOM_KEY_MAP("XF86Subtitle", XF86Subtitle, 0x01CC), + DOM_KEY_MAP("XF86SoftWakeup", XF86SoftWakeup, 0x2804), + DOM_KEY_MAP("XF86PlayBack", XF86PlayBack, 0x280C), + DOM_KEY_MAP("XF86ExtraApp", XF86ExtraApp, 0x280D), + DOM_KEY_MAP("XF86Color", XF86Color, 0x2891), + DOM_KEY_MAP("XF86Alarm", XF86Alarm, 0x28B2), + DOM_KEY_MAP("XF86HotelMovies", XF86HotelMovies, 0x28FE), + DOM_KEY_MAP("XF86HotelLanguage", XF86HotelLanguage, 0x28FF), + DOM_KEY_MAP("XF86HotelTVGuide", XF86HotelTVGuide, 0x2900), + DOM_KEY_MAP("XF86HotelAppsGuest", XF86HotelAppsGuest, 0x2901), + DOM_KEY_MAP("XF86NoiseReduction", XF86NoiseReduction, 0x2917), + DOM_KEY_MAP("XF86Help", XF86Help, 0x2918), + DOM_KEY_MAP("XF86NR", XF86NR, 0x2919), + DOM_KEY_MAP("XF86HotelRoomControl", XF86HotelRoomControl, 0x291A), + DOM_KEY_MAP("Select", Select, 0x000D), + DOM_KEY_MAP("Clear", Clear, 0x002E), +#endif }; diff --git a/ui/events/keycodes/keyboard_codes_posix.h b/ui/events/keycodes/keyboard_codes_posix.h index e8f04f4..56f2b9a 100644 --- a/ui/events/keycodes/keyboard_codes_posix.h +++ b/ui/events/keycodes/keyboard_codes_posix.h @@ -42,7 +42,9 @@ enum KeyboardCode { VKEY_BACK = 0x08, VKEY_TAB = 0x09, VKEY_BACKTAB = 0x0A, +#if !BUILDFLAG(IS_TIZEN_TV) VKEY_CLEAR = 0x0C, +#endif VKEY_RETURN = 0x0D, VKEY_SHIFT = 0x10, VKEY_CONTROL = 0x11, @@ -76,7 +78,9 @@ enum KeyboardCode { VKEY_SNAPSHOT = 0x2C, // Print Screen / SysRq VKEY_INSERT = 0x2D, VKEY_DELETE = 0x2E, +#if !BUILDFLAG(IS_TIZEN_TV) VKEY_HELP = 0x2F, +#endif VKEY_0 = 0x30, VKEY_1 = 0x31, VKEY_2 = 0x32, @@ -117,7 +121,9 @@ enum KeyboardCode { VKEY_COMMAND = VKEY_LWIN, // Provide the Mac name for convenience. VKEY_RWIN = 0x5C, VKEY_APPS = 0x5D, +#if !BUILDFLAG(IS_TIZEN_TV) VKEY_SLEEP = 0x5F, +#endif VKEY_NUMPAD0 = 0x60, VKEY_NUMPAD1 = 0x61, VKEY_NUMPAD2 = 0x62, @@ -173,9 +179,11 @@ enum KeyboardCode { VKEY_BROWSER_SEARCH = 0xAA, VKEY_BROWSER_FAVORITES = 0xAB, VKEY_BROWSER_HOME = 0xAC, +#if !BUILDFLAG(IS_TIZEN_TV) VKEY_VOLUME_MUTE = 0xAD, VKEY_VOLUME_DOWN = 0xAE, VKEY_VOLUME_UP = 0xAF, +#endif VKEY_MEDIA_NEXT_TRACK = 0xB0, VKEY_MEDIA_PREV_TRACK = 0xB1, VKEY_MEDIA_STOP = 0xB2, @@ -211,7 +219,9 @@ enum KeyboardCode { VKEY_CRSEL = 0xF7, VKEY_EXSEL = 0xF8, VKEY_EREOF = 0xF9, +#if !BUILDFLAG(IS_TIZEN_TV) VKEY_PLAY = 0xFA, +#endif VKEY_ZOOM = 0xFB, VKEY_NONAME = 0xFC, VKEY_PA1 = 0xFD, @@ -221,7 +231,9 @@ enum KeyboardCode { // POSIX specific VKEYs. Note that as of Windows SDK 7.1, 0x97-9F, 0xD8-DA, // and 0xE8 are unassigned. VKEY_WLAN = 0x97, +#if !BUILDFLAG(IS_TIZEN_TV) VKEY_POWER = 0x98, +#endif VKEY_ASSISTANT = 0x99, VKEY_SETTINGS = 0x9A, VKEY_PRIVACY_SCREEN_TOGGLE = 0x9B, @@ -257,10 +269,157 @@ enum KeyboardCode { VKEY_ALL_APPLICATIONS = 0xEF, #if BUILDFLAG(IS_TIZEN_TV) + // TV keys on remote controller. + // Virtual keys defined in http://www.atsc.org/cms/standards/a100/a_100_2.pdf + // Same volume virtual keys are already defined in Windows virtual keys but we + // overlap with the keys defined in DTV. + // VKEY_PLAY + // VKEY_VOLUME_UP + // VKEY_VOLUME_DOWN + // VKEY_VOLUME_MUTE + + VKEY_RED = 0x193, + VKEY_GREEN = 0x194, + VKEY_YELLOW = 0x195, + VKEY_BLUE = 0x196, + VKEY_GREY = 0x197, + VKEY_BROWN = 0x198, + + VKEY_DTV_RETURN = 0x2719, + VKEY_DTV_HOME = 0x2757, + VKEY_SOURCE = 0x2758, + VKEY_CH_LIST = 0x2759, + + VKEY_POWER = 0x199, + VKEY_DTV_MENU = 0x2795, + VKEY_GUIDE = 0x1CA, + VKEY_ADDDEL = 0x1AD, + VKEY_AUTO_PROGRAM = 0x1B9, + VKEY_FAVCH = 0x1B1, + VKEY_BT_DUALVIEW = 0x1BB, + VKEY_SUB_TITLE = 0x1CC, + + VKEY_REWIND = 0x19C, + VKEY_STOP = 0x19D, + VKEY_PLAY = 0x19F, + VKEY_RECORD = 0x1A0, + VKEY_FAST_FWD = 0x1A1, + + VKEY_CHANNEL_UP = 0x1AB, + VKEY_CHANNEL_DOWN = 0x1AC, + + VKEY_VOLUME_UP = 0x1BF, + VKEY_VOLUME_DOWN = 0x1C0, + VKEY_VOLUME_MUTE = 0x1C1, + + VKEY_INFO = 0x1C9, + + VKEY_REPEAT = 0x2799, + VKEY_ASPECT = 0x279C, + VKEY_PMODE = 0x279D, + VKEY_HDMI = 0x279F, + VKEY_USBHUB_SWITCH = 0x27A0, + VKEY_EMANUAL = 0x27A2, + VKEY_TOOLS = 0x2797, + VKEY_MORE = 0x27A4, + VKEY_FACTORY = 0x27A5, + VKEY_SLEEP = 0x27A6, + VKEY_TV = 0x27A9, + VKEY_DTV = 0x27AA, + VKEY_STB_POWER = 0x27AB, + VKEY_PANEL_DOWN = 0x27AD, + VKEY_CONVERGENCE = 0x27AE, + VKEY_BT_COLOR_MECHA = 0x27AF, + VKEY_STILL_PICTURE = 0x27B0, + VKEY_BT_TRIGGER = 0x27B1, + VKEY_BT_HOTVK = 0x27B2, + VKEY_BT_DEVICE = 0x27B3, + VKEY_BT_CONTENTSBAR = 0x27B4, + VKEY_GAME = 0x27B5, + VKEY_PIP_CHUP = 0x27B7, + VKEY_PIP_CHDOWN = 0x27B8, + VKEY_ANTENA = 0x27B9, + VKEY_PANEL_ENTER = 0x27BB, + VKEY_LINK = 0x27BC, + VKEY_PANEL_UP = 0x27BD, + + VKEY_ANGLE = 0x27C1, + VKEY_WHEEL_LEFT = 0x27C2, + VKEY_WHEEL_RIGHT = 0x27C3, + VKEY_CONTENTS = 0x2757, + VKEY_PANEL_EXIT = 0x27C5, + VKEY_EXIT = 0x27C6, + + VKEY_MBR_TV = 0x27C7, + VKEY_MBR_STB_GUIDE = 0x27C8, + VKEY_MBR_BD_POPUP = 0x27C9, + VKEY_MBR_BDDVD_POWER = 0x27CA, + VKEY_MBR_SETUP_FAILURE = 0x27CB, + VKEY_MBR_SETUP = 0x27CC, + VKEY_MBR_WATCH_TV = 0x27CD, + + VKEY_PRECH = 0x27CE, + VKEY_RECOMMEND_SEARCH_TOGGLE = 0x27D0, + VKEY_BT_NUMBER = 0x27D1, + VKEY_16_9 = 0x27D2, + VKEY_MTS = 0x27D3, + VKEY_SMODE = 0x27D5, + VKEY_3SPEED = 0x27D6, + VKEY_3D = 0x27D7, + VKEY_TTX_MIX = 0x27D8, + VKEY_SRSTSXT = 0x27D9, + VKEY_WIFI_PAIRING = 0x27DA, + VKEY_BT_SAMSUNG_APPS = 0x27E3, + VKEY_W_LINK = 0x2757, + VKEY_ESAVING = 0x27E5, + VKEY_CLEAR = 0x27E6, + VKEY_TV_SNS = 0x27E9, + VKEY_DVR = 0x27EA, + VKEY_APP_LIST = 0x27EB, + VKEY_CAMERA = 0x27EC, + VKEY_CAPTION = 0x27ED, + VKEY_ZOOM1 = 0x27EE, + VKEY_PANEL_PLUS = 0x27EF, + VKEY_BT_VOICE = 0x27F0, + VKEY_SEARCH = 0x27F1, + VKEY_PANEL_MINUS = 0x27F3, + VKEY_SOCCER_MODE = 0x27F4, + VKEY_FUNCTIONS_AMAZON = 0x27F5, + VKEY_AD = 0x27F6, + VKEY_REWIND_ = 0x27F8, + VKEY_FF_ = 0x27F9, + VKEY_FUNCTIONS_NETFLIX = 0x27FA, + VKEY_PIP_ONOFF = 0x27FB, + VKEY_MBR_WATCH_MOVIE = 0x27FC, + VKEY_MBR_STBBD_MENU = 0x27FD, + VKEY_MBR_SETUP_CONFIRM = 0x27FE, + VKEY_FAMILYHUB = 0x27FF, + VKEY_ANYVIEW = 0x2800, + + VKEY_PAGE_LEFT = 0x2809, + VKEY_PAGE_RIGHT = 0x280A, + + VKEY_SOFT_WAKE_UP = 0x2804, + VKEY_PANEL_ON = 0x280B, + VKEY_PLAY_BACK = 0x280C, + VKEY_EXTRA = 0x280D, + VKEY_COLOR = 0x2891, + + VKEY_ALARM = 0x28B2, + VKEY_HOTEL_MOVIES = 0x28FE, + VKEY_HOTEL_LANGUAGE = 0x28FF, + VKEY_HOTEL_TV_GUIDE = 0x2900, + VKEY_HOTEL_APPS_GUEST = 0x2901, + VKEY_NOISE_REDUCTION = 0x2917, + VKEY_HELP = 0x2918, + VKEY_NR = 0x2919, + VKEY_HOTEL_ROOM_CONTROL = 0x291A, + // TV IME "Select" key, no X Server keycode, 0xFF60 ISF code. VKEY_IME_DONE = 0xFF60, // TV IME "Cancel" key, no X Server keycode, 0xFF69 ISF code. VKEY_IME_CANCEL = 0xFF69, + #endif }; -- 2.7.4 From 008476a8941389bec8bdeb1f907d3d4da501b042 Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Wed, 25 Jan 2023 01:20:55 +0530 Subject: [PATCH 12/16] [M108 Migration] Bring up ttrace Add '--ttrace' build option Import ttrace package Define USE_TTRACE macro Add use_ttrace GN variable Add helper macro functions for TTRACE Add TTRACE backend under TRACE_EVENT macro Enable TTRACE except chrome trace log for TV product by default. Reference: https://review.tizen.org/gerrit/c/277764 Change-Id: I40e2ec67c3619827a8b7de9c7e3bbcc22722d8a4 Signed-off-by: Bakka Uday Kiran --- base/trace_event/trace_event.h | 29 +++++++++++++++++ packaging/chromium-efl.spec | 4 +++ third_party/skia/src/core/SkTraceEvent.h | 31 +++++++++++++++++- tizen_src/build/BUILD.gn | 9 ++++- tizen_src/build/common.sh | 5 +++ tizen_src/build/config/BUILD.gn | 14 ++++++-- tizen_src/build/config/tizen_features.gni | 12 +++++++ tizen_src/chromium_impl/base/BUILD.gn | 11 +++++++ tizen_src/chromium_impl/base/base_efl.gni | 8 +++++ .../base/trace_event/trace_event_ttrace.cc | 37 +++++++++++++++++++++ tizen_src/chromium_impl/base/trace_event/ttrace.h | 38 ++++++++++++++++++++++ tizen_src/ewk/efl_integration/public/ewk_view.cc | 2 ++ .../efl_integration/web_contents_delegate_efl.cc | 3 +- v8/BUILD.gn | 4 +++ v8/src/tracing/trace-event.h | 32 ++++++++++++++++-- 15 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 tizen_src/chromium_impl/base/BUILD.gn create mode 100644 tizen_src/chromium_impl/base/trace_event/trace_event_ttrace.cc create mode 100644 tizen_src/chromium_impl/base/trace_event/ttrace.h diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index 02f96b1..2283ae7c 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h @@ -29,6 +29,10 @@ #include "base/trace_event/traced_value_support.h" #include "base/tracing_buildflags.h" +#if BUILDFLAG(IS_EFL) +#include "base/trace_event/ttrace.h" +#endif + #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) // By default, const char* argument values are assumed to have long-lived scope @@ -253,9 +257,16 @@ // Implementation detail: internal macro to create static category and add begin // event if the category is enabled. Also adds the end event when the scope // ends. +#if defined(USE_TTRACE_TRACE_EVENT_WEBCORE) +#define TTRACE_TRACE_EVENT(tracer, category_group, name) \ + INTERNAL_TRACE_EVENT_UID(tracer).TTraceBegin(category_group, name); +#else +#define TTRACE_TRACE_EVENT(tracer, category_group, name) +#endif #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ + TTRACE_TRACE_EVENT(tracer, category_group, name) \ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \ base::trace_event::TraceEventHandle INTERNAL_TRACE_EVENT_UID(h) = \ trace_event_internal::AddTraceEvent( \ @@ -712,9 +723,17 @@ static void AddMetadataEvent(const unsigned char* category_group_enabled, // Used by TRACE_EVENTx macros. Do not use directly. class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { public: +#if defined(USE_TTRACE_TRACE_EVENT_WEBCORE) + ScopedTracer() : use_ttrace_(false) {} +#else ScopedTracer() = default; +#endif ~ScopedTracer() { +#if defined(USE_TTRACE_TRACE_EVENT_WEBCORE) + if (use_ttrace_) + TTRACE_WEB_TRACE_EVENT_END(); +#endif if (category_group_enabled_ && *category_group_enabled_) { TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, event_handle_); @@ -729,6 +748,12 @@ class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { event_handle_ = event_handle; } +#if defined(USE_TTRACE_TRACE_EVENT_WEBCORE) + void TTraceBegin(const char* category_group, const char* name) { + use_ttrace_ = TTRACE_WEB_TRACE_EVENT_BEGIN(category_group, name); + } +#endif + private: // NOTE: Only initialize the first member to reduce generated code size, // since there is no point in initializing the other members if Initialize() @@ -736,6 +761,10 @@ class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { const unsigned char* category_group_enabled_ = nullptr; const char* name_; base::trace_event::TraceEventHandle event_handle_; + +#if defined(USE_TTRACE_TRACE_EVENT_WEBCORE) + bool use_ttrace_; +#endif }; // Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly. diff --git a/packaging/chromium-efl.spec b/packaging/chromium-efl.spec index baa95b3..d5b0dac 100644 --- a/packaging/chromium-efl.spec +++ b/packaging/chromium-efl.spec @@ -107,6 +107,7 @@ BuildRequires: pkgconfig(scim) BuildRequires: pkgconfig(security-manager) BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(stt) +BuildRequires: pkgconfig(ttrace) BuildRequires: pkgconfig(tts) BuildRequires: pkgconfig(ui-gadget-1) BuildRequires: pkgconfig(vconf) @@ -308,6 +309,9 @@ fi %else "build_chrome=false" \ %endif +%if "%{?_ttrace}" == "1" + "use_ttrace=true" \ +%endif %endif # _skip_gn ninja %{_smp_mflags} -C "%{OUTPUT_FOLDER}" \ diff --git a/third_party/skia/src/core/SkTraceEvent.h b/third_party/skia/src/core/SkTraceEvent.h index c1881e3..273a194 100644 --- a/third_party/skia/src/core/SkTraceEvent.h +++ b/third_party/skia/src/core/SkTraceEvent.h @@ -10,9 +10,14 @@ #ifndef SkTraceEvent_DEFINED #define SkTraceEvent_DEFINED +#include +#include "build/build_config.h" #include "include/utils/SkEventTracer.h" #include "src/core/SkTraceEventCommon.h" -#include + +#if BUILDFLAG(IS_EFL) +#include "base/trace_event/ttrace.h" +#endif //////////////////////////////////////////////////////////////////////////////// // Implementation specific tracing API definitions. @@ -149,9 +154,16 @@ // Implementation detail: internal macro to create static category and add begin // event if the category is enabled. Also adds the end event when the scope // ends. +#if defined(USE_TTRACE_TRACE_EVENT_SKIA) +#define TTRACE_TRACE_EVENT(tracer, category_group, name) \ + INTERNAL_TRACE_EVENT_UID(tracer).TTraceBegin(category_group, name); +#else +#define TTRACE_TRACE_EVENT(tracer, category_group, name) +#endif #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ skia::tracing_internals::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ + TTRACE_TRACE_EVENT(tracer, category_group, name) \ do { \ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ SkEventTracer::Handle h = skia::tracing_internals::AddTraceEvent( \ @@ -334,9 +346,17 @@ AddTraceEvent( class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { public: // Note: members of data_ intentionally left uninitialized. See Initialize. +#if defined(USE_TTRACE_TRACE_EVENT_SKIA) + ScopedTracer() : p_data_(NULL), use_ttrace_(false) {} +#else ScopedTracer() : p_data_(nullptr) {} +#endif ~ScopedTracer() { +#if defined(USE_TTRACE_TRACE_EVENT_SKIA) + if (use_ttrace_) + TTRACE_WEB_TRACE_EVENT_END(); +#endif if (p_data_ && *data_.category_group_enabled) TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( data_.category_group_enabled, data_.name, data_.event_handle); @@ -351,6 +371,12 @@ class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { p_data_ = &data_; } +#if defined(USE_TTRACE_TRACE_EVENT_SKIA) + void TTraceBegin(const char* category_group, const char* name) { + use_ttrace_ = TTRACE_WEB_TRACE_EVENT_BEGIN(category_group, name); + } +#endif + private: ScopedTracer(const ScopedTracer&) = delete; ScopedTracer& operator=(const ScopedTracer&) = delete; @@ -367,6 +393,9 @@ class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer { }; Data* p_data_; Data data_; +#if defined(USE_TTRACE_TRACE_EVENT_SKIA) + bool use_ttrace_; +#endif }; } // namespace tracing_internals diff --git a/tizen_src/build/BUILD.gn b/tizen_src/build/BUILD.gn index ce7e0ba..bee9081 100644 --- a/tizen_src/build/BUILD.gn +++ b/tizen_src/build/BUILD.gn @@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//tizen_src/build/config/tizen_features.gni") import("//tizen_src/build/config/linux/pkg_config.gni") +import("//tizen_src/build/config/tizen_features.gni") config("evas") { ldflags = [ "-levas" ] @@ -179,6 +179,13 @@ config("ui-gadget-public") { } } +tizen_pkg_config("libttrace") { + packages = [] + if (is_tizen) { + packages = [ "ttrace" ] + } +} + config("capi-appfw-application") { if (is_tizen) { ldflags = [ "-lcapi-appfw-application" ] diff --git a/tizen_src/build/common.sh b/tizen_src/build/common.sh index deca03d..a8ebf16 100755 --- a/tizen_src/build/common.sh +++ b/tizen_src/build/common.sh @@ -242,6 +242,11 @@ function setupAndExecuteTargetBuild() { --skip-gn) ARGS+=(--define "_skip_gn 1") ;; + --ttrace) + ARGS[$count]=--define + count=$(( $count + 1 )) + ARGS[$count]="_ttrace 1" + ;; --component-build) ARGS+=(--define "component_build 1") ;; diff --git a/tizen_src/build/config/BUILD.gn b/tizen_src/build/config/BUILD.gn index 3b4e9c1..eb89768 100644 --- a/tizen_src/build/config/BUILD.gn +++ b/tizen_src/build/config/BUILD.gn @@ -49,12 +49,20 @@ config("tizen_feature_flags") { defines += [ "WAYLAND_BRINGUP" ] } if (tizen_product_tv) { - defines += [ - "OS_TIZEN_TV_PRODUCT", - ] + defines += [ "OS_TIZEN_TV_PRODUCT" ] } if (tizen_multimedia) { defines += [ "TIZEN_MULTIMEDIA" ] } + if (use_ttrace) { + defines += [ "USE_TTRACE" ] + if (use_ttrace_chrome_trace) { + defines += [ + "USE_TTRACE_TRACE_EVENT_SKIA", + "USE_TTRACE_TRACE_EVENT_V8", + "USE_TTRACE_TRACE_EVENT_WEBCORE", + ] + } + } } } diff --git a/tizen_src/build/config/tizen_features.gni b/tizen_src/build/config/tizen_features.gni index 5e1ec9a..de32d58 100644 --- a/tizen_src/build/config/tizen_features.gni +++ b/tizen_src/build/config/tizen_features.gni @@ -22,6 +22,9 @@ declare_args() { use_cairo = false use_pango = false + use_ttrace = false + use_ttrace_chrome_trace = false + werror = false tizen_clang_base_path = "//tizen_src/buildtools/llvm" @@ -49,6 +52,15 @@ declare_args() { tizen_web_speech_recognition = false } +if (use_ttrace) { + use_ttrace_chrome_trace = true +} + +# Enable ttrace except chrome trace log for TV profile by default +if (tizen_product_tv) { + use_ttrace = true +} + if (is_tizen && tizen_multimedia_support) { tizen_multimedia_eme_support = true } else { diff --git a/tizen_src/chromium_impl/base/BUILD.gn b/tizen_src/chromium_impl/base/BUILD.gn new file mode 100644 index 0000000..0864461 --- /dev/null +++ b/tizen_src/chromium_impl/base/BUILD.gn @@ -0,0 +1,11 @@ +# Copyright (c) 2021 samsung electronics. all rights reserved. +# use of this source code is governed by a bsd-style license that can be +# found in the license file. + +static_library("trace_event_ttrace") { + configs += [ "//tizen_src/build:libttrace" ] + sources = [ + "//tizen_src/chromium_impl/base/trace_event/trace_event_ttrace.cc", + "//tizen_src/chromium_impl/base/trace_event/ttrace.h", + ] +} diff --git a/tizen_src/chromium_impl/base/base_efl.gni b/tizen_src/chromium_impl/base/base_efl.gni index 61a9e08..83210b2 100644 --- a/tizen_src/chromium_impl/base/base_efl.gni +++ b/tizen_src/chromium_impl/base/base_efl.gni @@ -3,6 +3,13 @@ # found in the LICENSE file. import("//build/config/ui.gni") +import("//tizen_src/build/config/tizen_features.gni") + +external_base_public_deps = [] +if (use_ttrace) { + external_base_public_deps += + [ "//tizen_src/chromium_impl/base:trace_event_ttrace" ] +} external_base_configs = [ "//tizen_src/build:ecore", @@ -13,4 +20,5 @@ external_base_sources = [ "//tizen_src/chromium_impl/base/message_loop/message_pump_ecore.h", "//tizen_src/chromium_impl/base/message_loop/message_pump_for_ui_efl.cc", "//tizen_src/chromium_impl/base/message_loop/message_pump_for_ui_efl.h", + "//tizen_src/chromium_impl/base/trace_event/ttrace.h", ] diff --git a/tizen_src/chromium_impl/base/trace_event/trace_event_ttrace.cc b/tizen_src/chromium_impl/base/trace_event/trace_event_ttrace.cc new file mode 100644 index 0000000..0802abd --- /dev/null +++ b/tizen_src/chromium_impl/base/trace_event/trace_event_ttrace.cc @@ -0,0 +1,37 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ttrace.h" + +#if defined(USE_TTRACE) +#include +#include + +bool TraceEventTTraceBegin(uint64_t tag, + const char* category_group, + const char* name) { + bool result = false; + std::string tokens[] = {"!disabled", "!debug", "blink", "cc", "gpu", + "media", "sandbox_ipc", "skia", "v8"}; + for (int i = 0; i < 9; i++) { + const char* category_group_token = tokens[i].c_str(); + if (category_group_token[0] == '!') { + category_group_token++; + if ((*category_group_token == '*') || + strstr(category_group, category_group_token)) + return false; + } else { + if ((*category_group_token == '*') || + strstr(category_group, category_group_token)) { + result = true; + break; + } + } + } + + if (result) + traceBegin(tag, "[%s]%s", category_group, name); + return result; +} +#endif diff --git a/tizen_src/chromium_impl/base/trace_event/ttrace.h b/tizen_src/chromium_impl/base/trace_event/ttrace.h new file mode 100644 index 0000000..e90f737 --- /dev/null +++ b/tizen_src/chromium_impl/base/trace_event/ttrace.h @@ -0,0 +1,38 @@ +// Copyright 2021 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TRACE_EVENT_TTRACE_H_ +#define BASE_TRACE_EVENT_TTRACE_H_ + +#ifdef USE_TTRACE +#include + +bool TraceEventTTraceBegin(uint64_t tag, + const char* category_group, + const char* name); + +#define __TTRACE_WEB_SCOPE_VAR_HELPER(A, B) A##B +#define __TTRACE_WEB_SCOPE_VAR(V, L) __TTRACE_WEB_SCOPE_VAR_HELPER(V, L) +#define TTRACE_WEB_SCOPE(...) \ + TTraceWrapper __TTRACE_WEB_SCOPE_VAR(ttrace, __LINE__)(TTRACE_TAG_WEB, \ + __VA_ARGS__) +#define TTRACE_WEB_MARK(...) traceMark(TTRACE_TAG_WEB, __VA_ARGS__) +#define TTRACE_WEB_ASYNC_BEGIN(uid, ...) \ + traceAsyncBegin(TTRACE_TAG_WEB, uid, __VA_ARGS__) +#define TTRACE_WEB_ASYNC_END(uid, ...) \ + traceAsyncEnd(TTRACE_TAG_WEB, uid, __VA_ARGS__) + +#define TTRACE_WEB_TRACE_EVENT_BEGIN(category_group, name) \ + TraceEventTTraceBegin(TTRACE_TAG_WEB, category_group, name) +#define TTRACE_WEB_TRACE_EVENT_END() traceEnd(TTRACE_TAG_WEB) +#else +#define TTRACE_WEB_SCOPE(...) +#define TTRACE_WEB_MARK(...) +#define TTRACE_WEB_ASYNC_BEGIN(...) +#define TTRACE_WEB_ASYNC_END(...) +#endif + +#define TTRACE_WEB TTRACE_WEB_SCOPE + +#endif // BASE_TRACE_EVENT_TTRACE_H_ diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 9392ea8..0e7b349 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -24,6 +24,7 @@ #include #include "authentication_challenge_popup.h" +#include "base/trace_event/ttrace.h" #include "content/public/browser/navigation_controller.h" #include "cookie_manager.h" #include "eweb_view.h" @@ -133,6 +134,7 @@ Ewk_Context *ewk_view_context_get(const Evas_Object *view) Eina_Bool ewk_view_url_set(Evas_Object* view, const char* url_string) { + TTRACE_WEB("ewk_view_url_set url: %s", url_string); EWK_VIEW_IMPL_GET_OR_RETURN(view, impl, false); EINA_SAFETY_ON_NULL_RETURN_VAL(url_string, false); GURL url(url_string); 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 2d6149d..67a2e18 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -5,6 +5,7 @@ #include "web_contents_delegate_efl.h" #include "base/strings/utf_string_conversions.h" +#include "base/trace_event/ttrace.h" #include "browser/favicon/favicon_database.h" #include "browser/input_picker/color_chooser_efl.h" #include "browser/javascript_dialog_manager_efl.h" @@ -567,9 +568,7 @@ void WebContentsDelegateEfl::DidRenderFrame() { (web_view_->GetProgressValue() > 0.1)) { did_first_visually_non_empty_paint_ = false; did_render_frame_ = true; -#if defined(USE_TTRACE) TTRACE_WEB("WebContentsDelegateEfl::DidRenderFrame"); -#endif LOG(INFO) << "WebContentsDelegateEfl::DidRenderFrame"; // "frame,rendered" message is triggered as soon as rendering of a frame diff --git a/v8/BUILD.gn b/v8/BUILD.gn index be07049..53d0a15 100644 --- a/v8/BUILD.gn +++ b/v8/BUILD.gn @@ -9,6 +9,7 @@ import("//build/config/host_byteorder.gni") import("//build/config/mips.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build_overrides/build.gni") +import("//tizen_src/build/config/tizen_features.gni") if (is_android) { import("//build/config/android/rules.gni") @@ -5495,6 +5496,9 @@ v8_component("v8_libbase") { "pthread", ] } + if (use_ttrace) { + deps += [ "//tizen_src/chromium_impl/base:trace_event_ttrace" ] + } } else if (current_os == "aix") { sources += [ "src/base/debug/stack_trace_posix.cc", diff --git a/v8/src/tracing/trace-event.h b/v8/src/tracing/trace-event.h index ed53d55..61df648 100644 --- a/v8/src/tracing/trace-event.h +++ b/v8/src/tracing/trace-event.h @@ -18,10 +18,14 @@ #include "base/trace_event/common/trace_event_common.h" #endif // !defined(V8_USE_PERFETTO) +#include "build/build_config.h" #include "include/v8-platform.h" #include "src/base/atomicops.h" #include "src/base/macros.h" +#if BUILDFLAG(IS_EFL) +#include "base/trace_event/ttrace.h" +#endif // This header file defines implementation details of how the trace macros in // trace_event_common.h collect and store trace events. Anything not // implementation-specific should go in trace_macros_common.h instead of here. @@ -192,18 +196,24 @@ enum CategoryGroupEnabledFlags { // Implementation detail: internal macro to create static category and add begin // event if the category is enabled. Also adds the end event when the scope // ends. +#if defined(USE_TTRACE_TRACE_EVENT_V8) +#define TTRACE_TRACE_EVENT(tracer, category_group, name) \ + INTERNAL_TRACE_EVENT_UID(tracer).TTraceBegin(category_group, name); +#else +#define TTRACE_TRACE_EVENT(tracer, category_group, name) +#endif #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ + TTRACE_TRACE_EVENT(tracer, category_group, name) \ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ uint64_t h = v8::internal::tracing::AddTraceEvent( \ TRACE_EVENT_PHASE_COMPLETE, \ INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \ v8::internal::tracing::kNoId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ - INTERNAL_TRACE_EVENT_UID(tracer) \ - .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ - h); \ + INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \ + INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \ } #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \ @@ -562,9 +572,16 @@ static V8_INLINE uint64_t AddTraceEventWithTimestamp( class ScopedTracer { public: // Note: members of data_ intentionally left uninitialized. See Initialize. +#if defined(USE_TTRACE_TRACE_EVENT_V8) + ScopedTracer() : p_data_(nullptr), use_ttrace_(false) {} +#else ScopedTracer() : p_data_(nullptr) {} +#endif ~ScopedTracer() { +#if defined(USE_TTRACE_TRACE_EVENT_V8) + if (use_ttrace_) TTRACE_WEB_TRACE_EVENT_END(); +#endif if (p_data_ && base::Relaxed_Load(reinterpret_cast( data_.category_group_enabled))) { TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( @@ -572,6 +589,12 @@ class ScopedTracer { } } +#if defined(USE_TTRACE_TRACE_EVENT_V8) + void TTraceBegin(const char* category_group, const char* name) { + use_ttrace_ = TTRACE_WEB_TRACE_EVENT_BEGIN(category_group, name); + } +#endif + void Initialize(const uint8_t* category_group_enabled, const char* name, uint64_t event_handle) { data_.category_group_enabled = category_group_enabled; @@ -593,6 +616,9 @@ class ScopedTracer { }; Data* p_data_; Data data_; +#if defined(USE_TTRACE_TRACE_EVENT_V8) + bool use_ttrace_; +#endif }; #ifdef V8_RUNTIME_CALL_STATS -- 2.7.4 From 139dd4101cddf1c842679cf14a2f910889f22073 Mon Sep 17 00:00:00 2001 From: Suhaspoornachandra Date: Wed, 25 Jan 2023 14:52:59 +0530 Subject: [PATCH 13/16] [M108 Migration][MM] Migrate Tbm feature for Tizen Multimedia This commit migrates below patches and their fixup's 1) Add Tbm Surface support 2) Add support for tbm buffer handling 3) [MM] Handle TBM on video frame drop 4) [MM] Fix memory leak during playing video using TBM 5) [MM] Fix the crash when player is destroyed before tbm media packet (partial) Reference: https://review.tizen.org/gerrit/269846/ https://review.tizen.org/gerrit/270726/ https://review.tizen.org/gerrit/272817/ https://review.tizen.org/gerrit/273650/ https://review.tizen.org/gerrit/274633/ https://review.tizen.org/gerrit/279208/ https://review.tizen.org/gerrit/282988/ Change-Id: Id65cfea36a7469c81c764d5d84d0ff9f84013244 Signed-off-by: Suhaspoornachandra --- cc/layers/video_layer_impl.cc | 97 +++++++++++++++ cc/layers/video_layer_impl.h | 16 +++ .../public/remoting_proto_enum_utils.cc | 3 + components/viz/common/features.cc | 2 + content/renderer/render_thread_impl.cc | 3 + gpu/GLES2/gl2chromium_autogen.h | 2 + gpu/command_buffer/build_gles2_cmd_buffer.py | 11 ++ gpu/command_buffer/client/gles2_c_lib_autogen.h | 18 +++ gpu/command_buffer/client/gles2_implementation.cc | 70 ++++++++++- gpu/command_buffer/client/gles2_implementation.h | 7 ++ .../client/gles2_implementation_autogen.h | 7 ++ gpu/command_buffer/client/gles2_interface.h | 1 + .../client/gles2_interface_autogen.h | 5 + .../client/gles2_interface_stub_autogen.h | 5 + .../client/gles2_interface_stub_impl_autogen.h | 8 ++ .../client/gles2_trace_implementation_autogen.h | 5 + .../gles2_trace_implementation_impl_autogen.h | 14 +++ gpu/command_buffer/client/gpu_control.h | 14 +++ gpu/command_buffer/gles2_cmd_buffer_functions.txt | 4 + gpu/ipc/client/command_buffer_proxy_impl.cc | 49 ++++++++ gpu/ipc/client/command_buffer_proxy_impl.h | 8 ++ .../gpu_memory_buffer_factory_native_pixmap.cc | 11 +- media/base/video_frame.cc | 138 +++++++++++++++++++++ media/base/video_frame.h | 51 ++++++++ media/base/video_frame_layout.cc | 3 + media/base/video_types.cc | 13 ++ media/base/video_types.h | 7 +- media/capture/mojom/BUILD.gn | 9 ++ media/capture/mojom/video_capture_types.mojom | 3 + .../mojom/video_capture_types_mojom_traits.cc | 9 ++ media/mojo/mojom/renderer_extensions.mojom | 9 ++ media/renderers/paint_canvas_video_renderer.cc | 39 +++++- media/renderers/video_resource_updater.cc | 14 ++- media/renderers/video_resource_updater.h | 4 +- media/video/gpu_memory_buffer_video_frame_pool.cc | 3 + services/viz/public/mojom/BUILD.gn | 10 ++ .../openscreen/src/cast/streaming/remoting.proto | 1 + tizen_src/build/config/BUILD.gn | 6 +- tizen_src/build/gn_chromiumefl.sh | 2 +- .../chromium_impl/content/browser/browser_efl.gni | 7 -- .../content/browser/media/tizen_renderer_impl.cc | 47 ++++++- .../content/browser/media/tizen_renderer_impl.h | 7 ++ .../media/tizen/media_player_renderer_client.cc | 28 +++++ .../media/tizen/media_player_renderer_client.h | 12 ++ .../filters/media_player_bridge_capi_adapter.cc | 13 +- .../filters/media_player_bridge_capi_adapter.h | 2 + .../media/filters/media_player_esplusplayer.cc | 29 +++++ .../media/filters/media_player_esplusplayer.h | 13 ++ .../media/filters/media_player_registry.cc | 41 ++++++ .../media/filters/media_player_registry.h | 42 +++++++ tizen_src/chromium_impl/media/media_efl.gni | 2 + tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h | 35 ++++++ tizen_src/chromium_impl/ui/ui_efl.gni | 1 + ui/gfx/gpu_memory_buffer.h | 10 ++ ui/gfx/mojom/BUILD.gn | 10 ++ ui/gfx/mojom/buffer_types.mojom | 52 ++++++++ ui/gfx/mojom/buffer_types_mojom_traits.cc | 63 ++++++++++ ui/gfx/mojom/buffer_types_mojom_traits.h | 61 +++++++++ ui/gl/gl_image_egl.cc | 33 +++++ ui/gl/gl_image_egl.h | 11 ++ ui/gl/gl_image_native_pixmap.cc | 20 +++ ui/gl/gl_image_native_pixmap.h | 18 +++ 62 files changed, 1217 insertions(+), 21 deletions(-) create mode 100644 tizen_src/chromium_impl/media/filters/media_player_registry.cc create mode 100644 tizen_src/chromium_impl/media/filters/media_player_registry.h create mode 100644 tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index a6ced88..96080d7 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc @@ -25,6 +25,12 @@ #include "media/renderers/video_resource_updater.h" #include "ui/gfx/color_space.h" +#if defined(TIZEN_TBM_SUPPORT) +#include "components/viz/common/quads/tile_draw_quad.h" +#include "components/viz/service/display/skia_renderer.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#endif + namespace cc { // static @@ -57,6 +63,9 @@ VideoLayerImpl::VideoLayerImpl( } VideoLayerImpl::~VideoLayerImpl() { +#if defined(TIZEN_TBM_SUPPORT) + ReleaseResources(); +#endif if (!provider_client_impl_->Stopped()) { // In impl side painting, we may have a pending and active layer // associated with the video provider at the same time. Both have a ref @@ -107,6 +116,63 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode, return false; } +#if defined(TIZEN_TBM_SUPPORT) + if (frame_->IsTBMBackend()) { + context_provider_ = layer_tree_impl()->context_provider(); + if (!context_provider_) + return false; + // Pass a VideoFrame reference to OnVideoCompositingFinished() callback to + // ensure that VideoFrame object is valid. + // OnVideoCompositingFinished() callback is invoked when finish to use the + // resource on browser process. + // After OnVideoCompositingFinished() is invoked, VideoFrame object can be + // destroyed. + frame_->SetContextProvider(context_provider_); + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); + frame_->CreateTbmTextureIfNeeded(gl); + const gpu::MailboxHolder& mailbox_holder = frame_->mailbox_holder(0); + auto transferable_resource = viz::TransferableResource::MakeGpu( + mailbox_holder.mailbox, GL_LINEAR, mailbox_holder.texture_target, + mailbox_holder.sync_token, frame_->visible_rect().size(), + viz::RGBA_8888, false); + resource_id_ = resource_provider->ImportResource( + transferable_resource, + base::BindOnce(&VideoLayerImpl::OnVideoCompositingFinished, + base::Unretained(this), frame_)); +#if defined(_DEBUG_TBM_VIDEO_RENDERING) && _DEBUG_TBM_VIDEO_RENDERING + LOG(INFO) << " Video frame > " + << ", texture_id:" << frame_->GetTbmTexture() + << ", resource_id:" << resource_id_ + << ", size:" << frame_->visible_rect().size().ToString(); +#endif + +#if defined(_DEBUG_TBM_VIDEO_RENDERING_FPS) && _DEBUG_TBM_VIDEO_RENDERING_FPS + static media::VideoFrame* prev_frame = 0; + static int new_frame_cnt = 0; + static int frame_cnt = 0; + static base::TimeTicks last_tick = base::TimeTicks::Now(); + const base::TimeTicks now = base::TimeTicks::Now(); + const base::TimeDelta interval = now - last_tick; + + if (prev_frame != frame_.get()) + new_frame_cnt++; + prev_frame = frame_.get(); + frame_cnt++; + if (interval >= base::TimeDelta::FromSeconds(1)) { + printf("VideoTBM[Draw] > [FPS]%.1f/%.1f\n", + new_frame_cnt / interval.InSecondsF(), + frame_cnt / interval.InSecondsF()); + LOG(INFO) << "VideoTBM[Draw] > [FPS]" + << (new_frame_cnt / interval.InSecondsF()) << "/" + << (frame_cnt / interval.InSecondsF()); + last_tick = now; + frame_cnt = 0; + new_frame_cnt = 0; + } +#endif + } +#endif + if (!updater_) { const LayerTreeSettings& settings = layer_tree_impl()->settings(); // TODO(sergeyu): Pass RasterContextProvider when it's available. Then @@ -121,7 +187,11 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode, settings.resource_settings.use_r16_texture, layer_tree_impl()->max_texture_size()); } +#if defined(TIZEN_TBM_SUPPORT) + updater_->ObtainFrameResources(frame_, resource_id_); +#else updater_->ObtainFrameResources(frame_); +#endif return true; } @@ -195,6 +265,23 @@ void VideoLayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) { provider_client_impl_->ReleaseLock(); } +#if defined(TIZEN_TBM_SUPPORT) +void VideoLayerImpl::OnVideoCompositingFinished( + const scoped_refptr video_frame, + const gpu::SyncToken& sync_token, + bool lost_resource) { +#if defined(USE_TTRACE) + TTRACE_WEB("VideoLayerImpl::OnVideoCompositingFinished"); +#endif +#if defined(_DEBUG_TBM_VIDEO_RENDERING) && _DEBUG_TBM_VIDEO_RENDERING + LOG(INFO) + << "OnVideoCompositingFinished > resource was removed in ResourceProvider" + << ", tbm:" << video_frame->GetTbmBuffer().tbm_surface + << ", txt:" << video_frame->GetTbmTexture(); +#endif +} +#endif + SimpleEnclosedRegion VideoLayerImpl::VisibleOpaqueRegion() const { // If we don't have a frame yet, then we don't have an opaque region. if (!provider_client_impl_->HasCurrentFrame()) @@ -203,6 +290,16 @@ SimpleEnclosedRegion VideoLayerImpl::VisibleOpaqueRegion() const { } void VideoLayerImpl::ReleaseResources() { +#if defined(TIZEN_TBM_SUPPORT) + scoped_refptr last_frame = frame_; + if (!frame_) + last_frame = provider_client_impl_->AcquireLockAndCurrentFrame(); + if (last_frame) + last_frame->ReleaseTbm(); + last_frame = nullptr; + if (!frame_) + provider_client_impl_->ReleaseLock(); +#endif updater_ = nullptr; } diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h index 3bad972..99c89dc 100644 --- a/cc/layers/video_layer_impl.h +++ b/cc/layers/video_layer_impl.h @@ -13,6 +13,10 @@ #include "components/viz/common/resources/release_callback.h" #include "media/base/video_transformation.h" +#if defined(TIZEN_TBM_SUPPORT) +#include "components/viz/common/gpu/context_provider.h" +#endif + namespace media { class VideoFrame; class VideoResourceUpdater; @@ -64,12 +68,24 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl { const char* LayerTypeAsString() const override; +#if defined(TIZEN_TBM_SUPPORT) + void OnVideoCompositingFinished( + const scoped_refptr video_frame, + const gpu::SyncToken& sync_token, + bool lost_resource); +#endif + scoped_refptr provider_client_impl_; scoped_refptr frame_; media::VideoTransformation video_transform_; +#if defined(TIZEN_TBM_SUPPORT) + scoped_refptr context_provider_; + viz::ResourceId resource_id_; +#endif + std::unique_ptr updater_; }; diff --git a/components/cast_streaming/public/remoting_proto_enum_utils.cc b/components/cast_streaming/public/remoting_proto_enum_utils.cc index 9a173e6..98af814 100644 --- a/components/cast_streaming/public/remoting_proto_enum_utils.cc +++ b/components/cast_streaming/public/remoting_proto_enum_utils.cc @@ -374,6 +374,9 @@ absl::optional ToMediaVideoPixelFormat( CASE_RETURN_OTHER(PIXEL_FORMAT_P016LE); CASE_RETURN_OTHER(PIXEL_FORMAT_XR30); CASE_RETURN_OTHER(PIXEL_FORMAT_XB30); +#if defined(TIZEN_TBM_SUPPORT) + CASE_RETURN_OTHER(PIXEL_FORMAT_TBM_SURFACE); +#endif // PIXEL_FORMAT_UYVY, PIXEL_FORMAT_RGB32 and PIXEL_FORMAT_Y8 are deprecated. case openscreen::cast::VideoDecoderConfig_Format_PIXEL_FORMAT_RGB32: return absl::nullopt; diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index dbd3021..4d16116 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc @@ -331,6 +331,8 @@ bool UseSurfaceLayerForVideo() { return true; } return base::FeatureList::IsEnabled(kUseSurfaceLayerForVideoDefault); +#elif defined(TIZEN_MULTIMEDIA) + return false; #else return true; #endif diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 17b6280..617b57f 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -1147,6 +1147,9 @@ RenderThreadImpl::SharedMainThreadContextProvider() { .status_values[gpu::GPU_FEATURE_TYPE_CANVAS_OOP_RASTERIZATION] == gpu::kGpuFeatureStatusEnabled; bool support_gles2_interface = false; +#if defined(TIZEN_TBM_SUPPORT) + support_gles2_interface = true; +#endif bool support_grcontext = !support_oop_rasterization; // Enable automatic flushes to improve canvas throughput. // See https://crbug.com/880901 diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index efcb0d37..014d040 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -348,6 +348,8 @@ #define glCoverageModulationCHROMIUM GLES2_GET_FUN(CoverageModulationCHROMIUM) #define glGetGraphicsResetStatusKHR GLES2_GET_FUN(GetGraphicsResetStatusKHR) #define glBlendBarrierKHR GLES2_GET_FUN(BlendBarrierKHR) +#define glCreateTizenImageCHROMIUM GLES2_GET_FUN(CreateTizenImageCHROMIUM) +#define glDestroyTizenImageCHROMIUM GLES2_GET_FUN(DestroyTizenImageCHROMIUM) #define glBindFragDataLocationIndexedEXT \ GLES2_GET_FUN(BindFragDataLocationIndexedEXT) #define glBindFragDataLocationEXT GLES2_GET_FUN(BindFragDataLocationEXT) diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index b8bef5e..849dc9b 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3958,6 +3958,17 @@ _FUNCTION_INFO = { 'extension': True, 'trace_level': 2, }, + 'CreateTizenImageCHROMIUM': { + 'type': 'NoCommand', + 'cmd_args':'gfx::TbmBufferHandle handle, GLsizei width,' + ' GLsizei height, GLenum internalformat', + 'result': ['GLuint'], + 'extension': True, + }, + 'DestroyTizenImageCHROMIUM': { + 'type': 'NoCommand', + 'extension': True, + }, 'InitializeDiscardableTextureCHROMIUM': { 'type': 'Custom', 'cmd_args': 'GLuint texture_id, uint32_t shm_id, ' diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 7114150..dc682bd 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -1601,6 +1601,16 @@ GLenum GL_APIENTRY GLES2GetGraphicsResetStatusKHR() { void GL_APIENTRY GLES2BlendBarrierKHR() { gles2::GetGLContext()->BlendBarrierKHR(); } +GLuint GL_APIENTRY GLES2CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle, + GLsizei width, + GLsizei height, + GLenum internalformat) { + return gles2::GetGLContext()->CreateTizenImageCHROMIUM(handle, width, height, + internalformat); +} +void GL_APIENTRY GLES2DestroyTizenImageCHROMIUM(GLuint image_id) { + gles2::GetGLContext()->DestroyTizenImageCHROMIUM(image_id); +} void GL_APIENTRY GLES2BindFragDataLocationIndexedEXT(GLuint program, GLuint colorNumber, GLuint index, @@ -2986,6 +2996,14 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast(glBlendBarrierKHR), }, { + "glCreateTizenImageCHROMIUM", + reinterpret_cast(glCreateTizenImageCHROMIUM), + }, + { + "glDestroyTizenImageCHROMIUM", + reinterpret_cast(glDestroyTizenImageCHROMIUM), + }, + { "glBindFragDataLocationIndexedEXT", reinterpret_cast( glBindFragDataLocationIndexedEXT), diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 9aed697..d66cb81 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -108,6 +108,10 @@ !ptr || \ (ptr[0] == static_cast(0) || ptr[0] == static_cast(-1))); +#if defined(TIZEN_TBM_SUPPORT) +#include "base/logging.h" +#endif + namespace gpu { namespace gles2 { @@ -244,7 +248,9 @@ GLES2Implementation::GLES2Implementation( aggressively_free_resources_(false), cached_extension_string_(nullptr) { DCHECK(helper); - +#if defined(TIZEN_TBM_SUPPORT) + LOG(INFO) << __FUNCTION__ << " " << this; +#endif std::stringstream ss; ss << std::hex << this; this_in_hex_ = ss.str(); @@ -324,6 +330,9 @@ GLES2Implementation::~GLES2Implementation() { // shared memory (mapped_memory_) which will free the memory used // by the queries. The GPU process when validating that memory is still // shared will fail and abort (ie, it will stop running). +#if defined(TIZEN_TBM_SUPPORT) + LOG(INFO) << __FUNCTION__ << " " << this; +#endif WaitForCmd(); query_tracker_.reset(); @@ -6899,6 +6908,65 @@ bool GLES2Implementation::CanDecodeWithHardwareAcceleration( return false; } +#if defined(TIZEN_TBM_SUPPORT) +GLuint GLES2Implementation::CreateTizenImageCHROMIUMHelper( + gfx::TbmBufferHandle buffer_handle, + GLsizei width, + GLsizei height, + GLenum internalformat) { + if (width <= 0) { + SetGLError(GL_INVALID_VALUE, "glCreateTizenImageCHROMIUM", "width <= 0"); + return 0; + } + + if (height <= 0) { + SetGLError(GL_INVALID_VALUE, "glCreateTizenImageCHROMIUM", "height <= 0"); + return 0; + } + + int32_t image_id = gpu_control_->CreateEGLImage(buffer_handle, width, height, + internalformat); + if (image_id < 0) { + SetGLError(GL_OUT_OF_MEMORY, "glCreateTizenImageCHROMIUM", "image_id < 0"); + return 0; + } + return image_id; +} +#endif + +GLuint GLES2Implementation::CreateTizenImageCHROMIUM( + gfx::TbmBufferHandle buffer_handle, + GLsizei width, + GLsizei height, + GLenum internalformat) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG( + "[" << GetLogPrefix() << "] glCreateTizenImageCHROMIUM(" << buffer_handle + << ", " << width << ", " << height << ", " + << GLES2Util::GetStringTextureInternalFormat(internalformat) << ")"); +#if defined(TIZEN_TBM_SUPPORT) + GLuint image_id = CreateTizenImageCHROMIUMHelper(buffer_handle, width, height, + internalformat); + CheckGLError(); + return image_id; +#else + return 0; +#endif +} + +void GLES2Implementation::DestroyTizenImageCHROMIUM(GLuint image_id) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyTizenImageCHROMIUM(" + << image_id << ")"); +#if defined(TIZEN_TBM_SUPPORT) + // Flush the command stream to make sure all pending commands + // that may refer to the image_id are executed on the service side. + helper_->CommandBufferHelper::Flush(); + gpu_control_->DestroyEGLImage(image_id); + CheckGLError(); +#endif +} + bool GLES2Implementation::ValidateSize(const char* func, GLsizeiptr size) { if (size < 0) { SetGLError(GL_INVALID_VALUE, func, "size < 0"); diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index cf8daae..24934f9 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -523,6 +523,13 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface, const GLuint* baseInstances, GLsizei drawcount); +#if defined(TIZEN_TBM_SUPPORT) + GLuint CreateTizenImageCHROMIUMHelper(gfx::TbmBufferHandle buffer_handle, + GLsizei width, + GLsizei height, + GLenum internalformat); +#endif + // Helper for GetVertexAttrib bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32_t* param); diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index f1c6a51..7e96128 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -1127,6 +1127,13 @@ GLenum GetGraphicsResetStatusKHR() override; void BlendBarrierKHR() override; +GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle, + GLsizei width, + GLsizei height, + GLenum internalformat) override; + +void DestroyTizenImageCHROMIUM(GLuint image_id) override; + void BindFragDataLocationIndexedEXT(GLuint program, GLuint colorNumber, GLuint index, diff --git a/gpu/command_buffer/client/gles2_interface.h b/gpu/command_buffer/client/gles2_interface.h index bcc3cd1..aa59036 100644 --- a/gpu/command_buffer/client/gles2_interface.h +++ b/gpu/command_buffer/client/gles2_interface.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "gpu/command_buffer/client/interface_base.h" +#include "ui/gfx/tbm_buffer_handle.h" namespace cc { class ClientTransferCacheEntry; diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index d24bf67..ab5f1ca 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -835,6 +835,11 @@ virtual void ContextVisibilityHintCHROMIUM(GLboolean visibility) = 0; virtual void CoverageModulationCHROMIUM(GLenum components) = 0; virtual GLenum GetGraphicsResetStatusKHR() = 0; virtual void BlendBarrierKHR() = 0; +virtual GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle, + GLsizei width, + GLsizei height, + GLenum internalformat) = 0; +virtual void DestroyTizenImageCHROMIUM(GLuint image_id) = 0; virtual void BindFragDataLocationIndexedEXT(GLuint program, GLuint colorNumber, GLuint index, diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index c799d22..cb8e5d0 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -811,6 +811,11 @@ void ContextVisibilityHintCHROMIUM(GLboolean visibility) override; void CoverageModulationCHROMIUM(GLenum components) override; GLenum GetGraphicsResetStatusKHR() override; void BlendBarrierKHR() override; +GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle, + GLsizei width, + GLsizei height, + GLenum internalformat) override; +void DestroyTizenImageCHROMIUM(GLuint image_id) override; void BindFragDataLocationIndexedEXT(GLuint program, GLuint colorNumber, GLuint index, diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 0dc071a..2dd74a0 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -1088,6 +1088,14 @@ GLenum GLES2InterfaceStub::GetGraphicsResetStatusKHR() { return 0; } void GLES2InterfaceStub::BlendBarrierKHR() {} +GLuint GLES2InterfaceStub::CreateTizenImageCHROMIUM( + gfx::TbmBufferHandle /* handle */, + GLsizei /* width */, + GLsizei /* height */, + GLenum /* internalformat */) { + return 0; +} +void GLES2InterfaceStub::DestroyTizenImageCHROMIUM(GLuint /* image_id */) {} void GLES2InterfaceStub::BindFragDataLocationIndexedEXT( GLuint /* program */, GLuint /* colorNumber */, diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 2103e9e..63b3b61 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -811,6 +811,11 @@ void ContextVisibilityHintCHROMIUM(GLboolean visibility) override; void CoverageModulationCHROMIUM(GLenum components) override; GLenum GetGraphicsResetStatusKHR() override; void BlendBarrierKHR() override; +GLuint CreateTizenImageCHROMIUM(gfx::TbmBufferHandle handle, + GLsizei width, + GLsizei height, + GLenum internalformat) override; +void DestroyTizenImageCHROMIUM(GLuint image_id) override; void BindFragDataLocationIndexedEXT(GLuint program, GLuint colorNumber, GLuint index, diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index e22cb21..1a6c4c5 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -2313,6 +2313,20 @@ void GLES2TraceImplementation::BlendBarrierKHR() { gl_->BlendBarrierKHR(); } +GLuint GLES2TraceImplementation::CreateTizenImageCHROMIUM( + gfx::TbmBufferHandle handle, + GLsizei width, + GLsizei height, + GLenum internalformat) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CreateTizenImageCHROMIUM"); + return gl_->CreateTizenImageCHROMIUM(handle, width, height, internalformat); +} + +void GLES2TraceImplementation::DestroyTizenImageCHROMIUM(GLuint image_id) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DestroyTizenImageCHROMIUM"); + gl_->DestroyTizenImageCHROMIUM(image_id); +} + void GLES2TraceImplementation::BindFragDataLocationIndexedEXT( GLuint program, GLuint colorNumber, diff --git a/gpu/command_buffer/client/gpu_control.h b/gpu/command_buffer/client/gpu_control.h index eadc592..a45ac1a 100644 --- a/gpu/command_buffer/client/gpu_control.h +++ b/gpu/command_buffer/client/gpu_control.h @@ -18,6 +18,10 @@ #include "gpu/gpu_export.h" #include "ui/gfx/overlay_transform.h" +#if defined(TIZEN_TBM_SUPPORT) +#include "ui/gfx/tbm_buffer_handle.h" +#endif + extern "C" typedef struct _ClientBuffer* ClientBuffer; extern "C" typedef struct _ClientGpuFence* ClientGpuFence; @@ -47,6 +51,16 @@ class GPU_EXPORT GpuControl { virtual const Capabilities& GetCapabilities() const = 0; +#if defined(TIZEN_TBM_SUPPORT) + virtual int32_t CreateEGLImage(gfx::TbmBufferHandle buffer_handle, + size_t width, + size_t height, + unsigned internalformat) { + return -1; + } + virtual void DestroyEGLImage(int32_t image_id) {} +#endif + // Runs |callback| when a query created via glCreateQueryEXT() has cleared // passed the glEndQueryEXT() point. virtual void SignalQuery(uint32_t query, base::OnceClosure callback) = 0; diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt index a2801cd..15dae8d 100644 --- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt +++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt @@ -348,6 +348,10 @@ GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); // Extension KHR_blend_equation_advanced GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void); +// for tizen +GL_APICALL GLuint GL_APIENTRY glCreateTizenImageCHROMIUM (gfx::TbmBufferHandle handle, GLsizei width, GLsizei height, GLenum internalformat); +GL_APICALL void GL_APIENTRY glDestroyTizenImageCHROMIUM (GLuint image_id); + // Extension EXT_blend_func_extended GL_APICALL void GL_APIENTRY glBindFragDataLocationIndexedEXT (GLidProgram program, GLuint colorNumber, GLuint index, const char* name); GL_APICALL void GL_APIENTRY glBindFragDataLocationEXT (GLidProgram program, GLuint colorNumber, const char* name); diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc index 682ed9f..a6af84d 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.cc +++ b/gpu/ipc/client/command_buffer_proxy_impl.cc @@ -415,6 +415,55 @@ const gpu::Capabilities& CommandBufferProxyImpl::GetCapabilities() const { return capabilities_; } +#if defined(TIZEN_TBM_SUPPORT) +int32_t CommandBufferProxyImpl::CreateEGLImage( + gfx::TbmBufferHandle buffer_handle, + size_t width, + size_t height, + unsigned internalformat) { + CheckLock(); + base::AutoLock lock(last_state_lock_); + if (last_state_.error != gpu::error::kNoError) + return -1; + + int32_t new_id = channel_->ReserveImageId(); + + auto params = mojom::CreateImageParams::New(); + params->id = new_id; + params->size = gfx::Size(width, height); + params->format = gfx::BufferFormat::RGBA_8888; + params->plane = gfx::BufferPlane::DEFAULT; + params->image_release_count = 0; + + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::NATIVE_PIXMAP; + handle.tbm_surface = reinterpret_cast(buffer_handle.tbm_surface); + handle.media_packet = reinterpret_cast(buffer_handle.media_packet); + handle.player_id = buffer_handle.player_id; + handle.key_num = buffer_handle.key_num; + for (int i = 0; i < handle.key_num; ++i) { + handle.key[i] = buffer_handle.key[i]; + handle.strides[i] = buffer_handle.strides[i]; + LOG(ERROR) << "exported key values " << handle.key[i]; + } + handle.width = width; + handle.height = height; + + params->gpu_memory_buffer = std::move(handle); + command_buffer_->CreateImage(std::move(params)); + return new_id; +} + +void CommandBufferProxyImpl::DestroyEGLImage(int32_t image_id) { + CheckLock(); + base::AutoLock lock(last_state_lock_); + if (last_state_.error != gpu::error::kNoError) + return; + + command_buffer_->DestroyImage(image_id); +} +#endif + void CommandBufferProxyImpl::SetLock(base::Lock* lock) { lock_ = lock; } diff --git a/gpu/ipc/client/command_buffer_proxy_impl.h b/gpu/ipc/client/command_buffer_proxy_impl.h index 80369c9..969320f 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.h +++ b/gpu/ipc/client/command_buffer_proxy_impl.h @@ -163,6 +163,14 @@ class GPU_EXPORT CommandBufferProxyImpl : public gpu::CommandBuffer, return shared_state_shm_; } +#if defined(TIZEN_TBM_SUPPORT) + int32_t CreateEGLImage(gfx::TbmBufferHandle buffer_handle, + size_t width, + size_t height, + unsigned internalformat) override; + void DestroyEGLImage(int32_t image_id) override; +#endif + private: typedef std::map> TransferBufferMap; typedef std::unordered_map SignalTaskMap; diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc index 2dff68b..cdd61b8 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc @@ -129,7 +129,15 @@ GpuMemoryBufferFactoryNativePixmap::CreateImageForGpuMemoryBuffer( SurfaceHandle surface_handle) { if (handle.type != gfx::NATIVE_PIXMAP) return nullptr; - +#if defined(TIZEN_TBM_SUPPORT) + scoped_refptr image( + new gl::GLImageNativePixmap(size, format)); + if (!image->Initialize(handle)) { + LOG(ERROR) << "Failed to create GLImage"; + return nullptr; + } + return image; +#else scoped_refptr pixmap; // If CreateGpuMemoryBuffer was used to allocate this buffer then avoid @@ -180,6 +188,7 @@ GpuMemoryBufferFactoryNativePixmap::CreateImageForGpuMemoryBuffer( NOTREACHED(); return nullptr; } +#endif } bool GpuMemoryBufferFactoryNativePixmap::SupportsCreateAnonymousImage() const { diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 4aa077a..ef1213f 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc @@ -31,6 +31,13 @@ #if BUILDFLAG(IS_MAC) #include "ui/gfx/mac/io_surface.h" #endif +#if defined(TIZEN_TBM_SUPPORT) +#include "base/threading/thread_task_runner_handle.h" +#include "base/trace_event/trace_event.h" +#include "gpu/GLES2/gl2extchromium.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "media/base/bind_to_current_loop.h" +#endif namespace media { @@ -79,6 +86,10 @@ std::string VideoFrame::StorageTypeToString( case VideoFrame::STORAGE_DMABUFS: return "DMABUFS"; #endif +#if defined(TIZEN_TBM_SUPPORT) + case VideoFrame::STORAGE_TBM_SURFACE: + return "TBM_SURFACE"; +#endif case VideoFrame::STORAGE_GPU_MEMORY_BUFFER: return "GPU_MEMORY_BUFFER"; } @@ -164,6 +175,9 @@ gfx::Size VideoFrame::SampleSize(VideoPixelFormat format, size_t plane) { case PIXEL_FORMAT_XB30: case PIXEL_FORMAT_BGRA: case PIXEL_FORMAT_RGBAF16: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif break; } } @@ -197,6 +211,9 @@ static bool RequiresEvenSizeAllocation(VideoPixelFormat format) { case PIXEL_FORMAT_XB30: case PIXEL_FORMAT_BGRA: case PIXEL_FORMAT_RGBAF16: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif return false; case PIXEL_FORMAT_NV12: case PIXEL_FORMAT_NV21: @@ -354,6 +371,34 @@ scoped_refptr VideoFrame::CreateZeroInitializedFrame( } // static +#if defined(TIZEN_TBM_SUPPORT) +scoped_refptr VideoFrame::WrapTBMSurface( + const gfx::Size& size, + base::TimeDelta timestamp, + gfx::TbmBufferHandle handle) { + const VideoPixelFormat format = PIXEL_FORMAT_TBM_SURFACE; + const StorageType storage = STORAGE_TBM_SURFACE; + const gfx::Rect visible_rect = gfx::Rect(size); + if (!IsValidConfig(format, storage, size, visible_rect, size)) { + LOG(ERROR) << __FUNCTION__ << " WrapTBMSurface Invalid config." + << ConfigToString(format, storage, size, visible_rect, size); + return nullptr; + } + + auto layout = VideoFrameLayout::Create(format, size); + if (!layout) { + LOG(ERROR) << "Invalid layout."; + return nullptr; + } + + scoped_refptr frame( + new VideoFrame(*layout, storage, gfx::Rect(size), size, timestamp)); + frame->buffer_handle_ = handle; + return frame; +} +#endif + +// static scoped_refptr VideoFrame::WrapNativeTextures( VideoPixelFormat format, const gpu::MailboxHolder (&mailbox_holders)[kMaxPlanes], @@ -1086,6 +1131,9 @@ int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) { return 1; case PIXEL_FORMAT_MJPEG: return 0; +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif case PIXEL_FORMAT_UNKNOWN: break; } @@ -1269,7 +1317,11 @@ uint8_t* VideoFrame::GetWritableVisibleData(size_t plane) { const gpu::MailboxHolder& VideoFrame::mailbox_holder( size_t texture_index) const { +#if defined(TIZEN_TBM_SUPPORT) + DCHECK(IsTBMBackend() || HasTextures()); +#else DCHECK(HasTextures()); +#endif DCHECK(IsValidPlane(format(), texture_index)); return wrapped_frame_ ? wrapped_frame_->mailbox_holder(texture_index) : mailbox_holders_[texture_index]; @@ -1330,7 +1382,11 @@ void VideoFrame::AddDestructionObserver(base::OnceClosure callback) { } gpu::SyncToken VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) { +#if defined(TIZEN_TBM_SUPPORT) + DCHECK(IsTBMBackend() || HasTextures()); +#else DCHECK(HasTextures()); +#endif if (wrapped_frame_) { return wrapped_frame_->UpdateReleaseSyncToken(client); } @@ -1390,6 +1446,11 @@ VideoFrame::VideoFrame(const VideoFrameLayout& layout, #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) dmabuf_fds_(base::MakeRefCounted()), #endif +#if defined(TIZEN_TBM_SUPPORT) + texture_id_(0), + gl_(nullptr), + image_id_(0), +#endif timestamp_(timestamp), unique_id_(g_unique_id_generator.GetNext()) { DCHECK(IsValidConfigInternal(format(), frame_control_type, coded_size(), @@ -1631,4 +1692,81 @@ std::vector VideoFrame::CalculatePlaneSize() const { return plane_size; } +#if defined(TIZEN_TBM_SUPPORT) +void ReleaseTbmTexture(scoped_refptr task_runner, + gpu::gles2::GLES2Interface* gl, + uint32_t texture, + uint32_t image, + scoped_refptr context_provider, + const gpu::SyncToken& release_sync_point) { +#if defined(USE_TTRACE) + TTRACE(TTRACE_TAG_WEB, "ReleaseTbmTexture"); +#endif + DCHECK(task_runner->BelongsToCurrentThread()); + const uint32_t target = GL_TEXTURE_EXTERNAL_OES; + LOG(INFO) << "VideoFrame > --ReleaseTbmTexture >" + << ", img:" << image << ", txt:" << texture; + if (release_sync_point.HasData()) + gl->WaitSyncTokenCHROMIUM(release_sync_point.GetConstData()); + if (image) { + gl->BindTexture(target, texture); + gl->ReleaseTexImage2DCHROMIUM(target, image); + gl->DestroyTizenImageCHROMIUM(image); + } + gl->DeleteTextures(1, &texture); +} + +void VideoFrame::ReleaseTbm() { + if (mailbox_holders_and_gmb_release_cb_) { + gpu::SyncToken release_sync_token; + { + // To ensure that changes to |release_sync_token_| are visible on this + // thread (imply a memory barrier). + base::AutoLock locker(release_sync_token_lock_); + release_sync_token = release_sync_token_; + } + std::move(mailbox_holders_and_gmb_release_cb_) + .Run(release_sync_token, std::move(gpu_memory_buffer_)); + } +} + +unsigned VideoFrame::CreateTbmTextureIfNeeded(gpu::gles2::GLES2Interface* gl) { +#if defined(USE_TTRACE) + TTRACE(TTRACE_TAG_WEB, "VideoFrameCompositor::CreateTbmTextureIfNeeded"); +#endif + base::AutoLock autolock(tbm_lock_); + if (!gl || texture_id_) + return (gl_ == gl) ? texture_id_ : 0; + + gl_ = gl; + unsigned image = gl->CreateTizenImageCHROMIUM( + buffer_handle_, visible_rect().width(), visible_rect().height(), GL_RGBA); + gl->GenTextures(1, &texture_id_); + gl->BindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_); + gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + gl->BindTexImage2DCHROMIUM(GL_TEXTURE_EXTERNAL_OES, image); + + LOG(INFO) << "CreateTbmTextureIfNeeded img:" << image + << ", txt:" << texture_id_; + + gpu::Mailbox mailbox; + gl->ProduceTextureDirectCHROMIUM(texture_id_, mailbox.name); + gl->ShallowFlushCHROMIUM(); + gpu::SyncToken sync_token; + gl->GenSyncTokenCHROMIUM(sync_token.GetData()); + mailbox_holders_[kARGBPlane] = + gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_EXTERNAL_OES); + + SetReleaseMailboxCB(base::BindOnce(ReleaseTbmTexture, + base::ThreadTaskRunnerHandle::Get(), gl, + texture_id_, image, context_provider_)); + return texture_id_; +} +#endif + } // namespace media diff --git a/media/base/video_frame.h b/media/base/video_frame.h index 8c6d873..ffeb81e 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h @@ -50,8 +50,25 @@ class GpuMemoryBuffer; struct GpuMemoryBufferHandle; } +#if defined(TIZEN_TBM_SUPPORT) +#include +#include +#include +#include "components/viz/common/gpu/context_provider.h" +#include "ui/gfx/tbm_buffer_handle.h" +#define _DEBUG_TBM_VIDEO_RENDERING 0 +#define _DEBUG_TBM_VIDEO_RENDERING_FPS 0 +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} // namespace gpu +#endif + namespace media { +constexpr auto TBM_BO_NUM_MAX = 4; + class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { public: static constexpr size_t kFrameSizeAlignment = 16; @@ -92,7 +109,12 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { STORAGE_DMABUFS = 5, // Each plane is stored into a DmaBuf. #endif STORAGE_GPU_MEMORY_BUFFER = 6, +#if defined(TIZEN_TBM_SUPPORT) + STORAGE_TBM_SURFACE = 7, + STORAGE_MAX = STORAGE_TBM_SURFACE, +#else STORAGE_MAX = STORAGE_GPU_MEMORY_BUFFER, +#endif }; // CB to be called on the mailbox backing this frame and its GpuMemoryBuffers @@ -330,6 +352,25 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { const gfx::Rect& visible_rect, const gfx::Size& natural_size); +#if defined(TIZEN_TBM_SUPPORT) + // Needed when we have video-frame content in tbm surface. + static scoped_refptr WrapTBMSurface(const gfx::Size& size, + base::TimeDelta timestamp, + gfx::TbmBufferHandle handle); + bool IsTBMBackend() const { return storage_type_ == STORAGE_TBM_SURFACE; } + unsigned GetTbmTexture() { return texture_id_; } + unsigned CreateTbmTextureIfNeeded(gpu::gles2::GLES2Interface* gl); + void ReleaseTbm(); + void SetTbmTexture(unsigned texture) { texture_id_ = texture; } + gfx::TbmBufferHandle GetTbmBuffer() { return buffer_handle_; } + unsigned GetImageID() { return image_id_; } + void SetImageID(unsigned image_id) { image_id_ = image_id; } + void SetContextProvider( + scoped_refptr context_provider) { + context_provider_ = context_provider; + } +#endif + // Creates a frame which indicates end-of-stream. static scoped_refptr CreateEOSFrame(); @@ -776,6 +817,16 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { std::vector done_callbacks_; +#if defined(TIZEN_TBM_SUPPORT) + base::Lock tbm_lock_; + mutable base::Lock tbm_map_lock_; + gfx::TbmBufferHandle buffer_handle_; + unsigned texture_id_; + gpu::gles2::GLES2Interface* gl_; + unsigned image_id_; + scoped_refptr context_provider_; +#endif + base::TimeDelta timestamp_; base::Lock release_sync_token_lock_; diff --git a/media/base/video_frame_layout.cc b/media/base/video_frame_layout.cc index b3307c3..47bbbffa 100644 --- a/media/base/video_frame_layout.cc +++ b/media/base/video_frame_layout.cc @@ -85,6 +85,9 @@ size_t VideoFrameLayout::NumPlanes(VideoPixelFormat format) { case PIXEL_FORMAT_UNKNOWN: // Note: PIXEL_FORMAT_UNKNOWN is used for end-of-stream frame. // Set its NumPlanes() to zero to avoid NOTREACHED(). +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif return 0; } NOTREACHED() << "Unsupported video frame format: " << format; diff --git a/media/base/video_types.cc b/media/base/video_types.cc index ea148df..4edcc27 100644 --- a/media/base/video_types.cc +++ b/media/base/video_types.cc @@ -85,6 +85,10 @@ std::string VideoPixelFormatToString(VideoPixelFormat format) { return "PIXEL_FORMAT_YUV422AP10"; case PIXEL_FORMAT_YUV444AP10: return "PIXEL_FORMAT_YUV444AP10"; +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: + return "PIXEL_FORMAT_TBM_SURFACE"; +#endif } NOTREACHED() << "Invalid VideoPixelFormat provided: " << format; return ""; @@ -161,6 +165,9 @@ bool IsYuvPlanar(VideoPixelFormat format) { case PIXEL_FORMAT_XB30: case PIXEL_FORMAT_BGRA: case PIXEL_FORMAT_RGBAF16: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif return false; } return false; @@ -239,6 +246,9 @@ bool IsOpaque(VideoPixelFormat format) { case PIXEL_FORMAT_P016LE: case PIXEL_FORMAT_XR30: case PIXEL_FORMAT_XB30: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif return true; case PIXEL_FORMAT_I420A: case PIXEL_FORMAT_ARGB: @@ -258,6 +268,9 @@ bool IsOpaque(VideoPixelFormat format) { size_t BitDepth(VideoPixelFormat format) { switch (format) { case PIXEL_FORMAT_UNKNOWN: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif NOTREACHED(); [[fallthrough]]; case PIXEL_FORMAT_I420: diff --git a/media/base/video_types.h b/media/base/video_types.h index 7f44dbf..d7dad6d 100644 --- a/media/base/video_types.h +++ b/media/base/video_types.h @@ -88,9 +88,14 @@ enum VideoPixelFormat { PIXEL_FORMAT_YUV422AP10 = 37, PIXEL_FORMAT_YUV444AP10 = 38, - // Please update UMA histogram enumeration when adding new formats here. +// Please update UMA histogram enumeration when adding new formats here. +#if defined(TIZEN_TBM_SUPPORT) + PIXEL_FORMAT_TBM_SURFACE = 39, + PIXEL_FORMAT_MAX = PIXEL_FORMAT_TBM_SURFACE, +#else PIXEL_FORMAT_MAX = PIXEL_FORMAT_YUV444AP10, // Must always be equal to largest entry logged. +#endif }; // These values are persisted to logs. Entries should not be renumbered and diff --git a/media/capture/mojom/BUILD.gn b/media/capture/mojom/BUILD.gn index db44033..65cd420 100644 --- a/media/capture/mojom/BUILD.gn +++ b/media/capture/mojom/BUILD.gn @@ -4,6 +4,15 @@ import("//mojo/public/tools/bindings/mojom.gni") +if (use_aura) { + import("//tizen_src/build/config/tizen_features.gni") +} + +enabled_features = [] +if (tizen_tbm_support) { + enabled_features += [ "tizen_tbm_support" ] +} + mojom("video_capture") { generate_java = true sources = [ "video_capture.mojom" ] diff --git a/media/capture/mojom/video_capture_types.mojom b/media/capture/mojom/video_capture_types.mojom index d8814af..e58304e 100644 --- a/media/capture/mojom/video_capture_types.mojom +++ b/media/capture/mojom/video_capture_types.mojom @@ -44,6 +44,9 @@ enum VideoCapturePixelFormat { [MinVersion=1] YUV420AP10, [MinVersion=1] YUV422AP10, [MinVersion=1] YUV444AP10, + + [EnableIf=tizen_tbm_support] + TBM_SURFACE, }; [Stable, Extensible] diff --git a/media/capture/mojom/video_capture_types_mojom_traits.cc b/media/capture/mojom/video_capture_types_mojom_traits.cc index 2dd7014..aa05fa7 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.cc +++ b/media/capture/mojom/video_capture_types_mojom_traits.cc @@ -159,6 +159,10 @@ EnumTraits (mojo_base.mojom.UnguessableToken request_token); + + [EnableIf=tizen_multimedia] + OnTbmBufferExhausted(gfx.mojom.TbmBufferHandle tbm_buffer_handle); }; // Extension of the mojo::RendererClient communication layer for media flinging, diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index ce72cf6..c2c53c0 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc @@ -982,6 +982,9 @@ void PaintCanvasVideoRenderer::Paint( if (!video_frame.get() || video_frame->natural_size().IsEmpty() || !(media::IsYuvPlanar(video_frame->format()) || video_frame->format() == PIXEL_FORMAT_Y16 || +#if defined(TIZEN_TBM_SUPPORT) + video_frame->IsTBMBackend() || +#endif video_frame->format() == PIXEL_FORMAT_ARGB || video_frame->format() == PIXEL_FORMAT_XRGB || video_frame->format() == PIXEL_FORMAT_ABGR || @@ -1873,7 +1876,11 @@ bool PaintCanvasVideoRenderer::UpdateLastImage( // |video_frame| is software. // Holding |video_frame| longer than this call when using GPUVideoDecoder // could cause problems since the pool of VideoFrames has a fixed size. - if (video_frame->HasTextures()) { + if (video_frame->HasTextures() +#if defined(TIZEN_TBM_SUPPORT) + && !video_frame->IsTBMBackend() +#endif + ) { DCHECK(raster_context_provider); bool supports_oop_raster = raster_context_provider->ContextCapabilities().supports_oop_raster; @@ -2003,8 +2010,38 @@ bool PaintCanvasVideoRenderer::UpdateLastImage( cc::PaintImage::GetNextContentId()); } else { cache_.emplace(video_frame->unique_id()); +#if defined(TIZEN_TBM_SUPPORT) + gpu::gles2::GLES2Interface* gl = raster_context_provider->ContextGL(); + unsigned source_texture = 0; + gl->GenTextures(1, &source_texture); + DCHECK(source_texture); + gl->BindTexture(GL_TEXTURE_2D, source_texture); + + CopyMailboxToTexture( + gl, video_frame->coded_size(), video_frame->visible_rect(), + video_frame->mailbox_holder(0).mailbox, + video_frame->mailbox_holder(0).sync_token, GL_TEXTURE_2D, + source_texture, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 0, false, false); + + GrGLTextureInfo source_texture_info; + source_texture_info.fID = source_texture; + source_texture_info.fTarget = GL_TEXTURE_2D; + source_texture_info.fFormat = GL_RGBA8_OES; + GrBackendTexture source_backend_texture( + video_frame->coded_size().width(), video_frame->coded_size().height(), + GrMipMapped::kNo, source_texture_info); + + paint_image_builder.set_image( + SkImage::MakeFromAdoptedTexture( + raster_context_provider->GrContext(), source_backend_texture, + kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, + kPremul_SkAlphaType, video_frame->ColorSpace().ToSkColorSpace()), + cc::PaintImage::GetNextContentId()); + +#else paint_image_builder.set_paint_image_generator( sk_make_sp(video_frame)); +#endif } cache_->paint_image = paint_image_builder.TakePaintImage(); diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index 7ded363..9b419ca 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc @@ -207,6 +207,9 @@ VideoFrameResourceType ExternalResourceTypeForHardwarePlanes( case PIXEL_FORMAT_YUV422AP10: case PIXEL_FORMAT_YUV444AP10: case PIXEL_FORMAT_UNKNOWN: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif break; } return VideoFrameResourceType::NONE; @@ -550,7 +553,16 @@ VideoResourceUpdater::~VideoResourceUpdater() { } void VideoResourceUpdater::ObtainFrameResources( - scoped_refptr video_frame) { + scoped_refptr video_frame, + viz::ResourceId external_resource_id) { +#if defined(TIZEN_TBM_SUPPORT) + if (video_frame->IsTBMBackend()) { + frame_resources_.emplace_back(external_resource_id, + video_frame->coded_size()); + frame_resource_type_ = VideoFrameResourceType::RGBA; + return; + } +#endif if (video_frame->metadata().overlay_plane_id.has_value()) { // This is a hole punching VideoFrame, there is nothing to display. overlay_plane_id_ = *video_frame->metadata().overlay_plane_id; diff --git a/media/renderers/video_resource_updater.h b/media/renderers/video_resource_updater.h index 9ada870..e3a0783 100644 --- a/media/renderers/video_resource_updater.h +++ b/media/renderers/video_resource_updater.h @@ -108,7 +108,9 @@ class MEDIA_EXPORT VideoResourceUpdater // 2. AppendQuads(): Add DrawQuads to CompositorFrame for video. // 3. ReleaseFrameResources(): After the CompositorFrame has been submitted, // remove imported resources from viz::ClientResourceProvider. - void ObtainFrameResources(scoped_refptr video_frame); + void ObtainFrameResources( + scoped_refptr video_frame, + viz::ResourceId resource_id = viz::kInvalidResourceId); void ReleaseFrameResources(); // Appends a quad representing |frame| to |render_pass|. // At most one quad is expected to be appended, this is enforced by the users diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index 098650d..d402e0f 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc @@ -790,6 +790,9 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( case PIXEL_FORMAT_YUV422AP10: case PIXEL_FORMAT_YUV444AP10: case PIXEL_FORMAT_UNKNOWN: +#if defined(TIZEN_TBM_SUPPORT) + case PIXEL_FORMAT_TBM_SURFACE: +#endif if (is_software_backed_video_frame) { UMA_HISTOGRAM_ENUMERATION( "Media.GpuMemoryBufferVideoFramePool.UnsupportedFormat", diff --git a/services/viz/public/mojom/BUILD.gn b/services/viz/public/mojom/BUILD.gn index d0884a9..b71d563 100644 --- a/services/viz/public/mojom/BUILD.gn +++ b/services/viz/public/mojom/BUILD.gn @@ -3,6 +3,11 @@ # found in the LICENSE file. import("//build/config/chromeos/ui_mode.gni") import("//mojo/public/tools/bindings/mojom.gni") + +if (use_efl) { + import("//tizen_src/build/config/tizen_features.gni") +} + mojom("mojom") { generate_java = true sources = [ @@ -607,6 +612,11 @@ mojom("mojom") { ] }, ] + + enabled_features = [] + if (tizen_tbm_support) { + enabled_features += [ "tizen_tbm_support" ] + } } mojom("resource_format") { generate_java = true diff --git a/third_party/openscreen/src/cast/streaming/remoting.proto b/third_party/openscreen/src/cast/streaming/remoting.proto index 399c97b..af8bbfa 100644 --- a/third_party/openscreen/src/cast/streaming/remoting.proto +++ b/third_party/openscreen/src/cast/streaming/remoting.proto @@ -231,6 +231,7 @@ message VideoDecoderConfig { PIXEL_FORMAT_P016LE = 29; PIXEL_FORMAT_XR30 = 30; PIXEL_FORMAT_XB30 = 31; + PIXEL_FORMAT_TBM_SURFACE = 32; }; // Proto version of Chrome's media::ColorSpace. diff --git a/tizen_src/build/config/BUILD.gn b/tizen_src/build/config/BUILD.gn index eb89768..c8ad9c5 100644 --- a/tizen_src/build/config/BUILD.gn +++ b/tizen_src/build/config/BUILD.gn @@ -17,9 +17,6 @@ config("tizen_feature_flags") { defines += [ "EFL_BETA_API_SUPPORT" ] } } - if (tizen_tbm_support) { - defines += [ "TIZEN_TBM_SUPPORT" ] - } if (ewk_bringup) { defines += [ "EWK_BRINGUP" ] } @@ -33,6 +30,9 @@ config("tizen_feature_flags") { if (use_wayland) { defines += [ "USE_WAYLAND" ] } + if (tizen_tbm_support) { + defines += [ "TIZEN_TBM_SUPPORT" ] + } if (tizen_multimedia_support) { defines += [ "TIZEN_MULTIMEDIA_SUPPORT", diff --git a/tizen_src/build/gn_chromiumefl.sh b/tizen_src/build/gn_chromiumefl.sh index fd9662f..275bef8 100755 --- a/tizen_src/build/gn_chromiumefl.sh +++ b/tizen_src/build/gn_chromiumefl.sh @@ -222,7 +222,7 @@ add_tizen_flags() { ADDITIONAL_GN_PARAMETERS+="tizen_multimedia=true proprietary_codecs=true tizen_web_speech_recognition=true - tizen_tbm_support=false + tizen_tbm_support=true " } diff --git a/tizen_src/chromium_impl/content/browser/browser_efl.gni b/tizen_src/chromium_impl/content/browser/browser_efl.gni index 2586fa5..260330f 100644 --- a/tizen_src/chromium_impl/content/browser/browser_efl.gni +++ b/tizen_src/chromium_impl/content/browser/browser_efl.gni @@ -155,13 +155,6 @@ if (tizen_multimedia) { ] } -if (tizen_tbm_support) { - external_content_browser_efl_sources += [ - "//tizen_src/chromium_impl/content/browser/media/browser_mediapacket_manager.cc", - "//tizen_src/chromium_impl/content/browser/media/browser_mediapacket_manager.h", - ] -} - if (tizen_web_speech_recognition) { external_content_browser_efl_sources += [ "//tizen_src/chromium_impl/content/browser/speech/speech_recognizer_impl_tizen.cc", diff --git a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc index 35b74aa..e5d1313 100644 --- a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc +++ b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc @@ -25,8 +25,24 @@ #include "tizen_src/chromium_impl/content/browser/media/media_player_renderer_web_contents_observer.h" #include "tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h" #include "tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h" +#include "tizen_src/chromium_impl/media/filters/media_player_registry.h" #include "tizen_src/chromium_impl/media/filters/media_player_tizen.h" +#if defined(TIZEN_TBM_SUPPORT) +namespace media { +void DestroyMediaPacket(void* media_packet, int player_id) { + MediaPlayerTizen* player = + MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id); + if (!player) { + // TODO: All media packets should be removed before player is destroyed. + LOG(WARNING) << __func__ + << " player already destroyed. player_id: " << player_id; + return; + } + player->DestroyMediaPacket(media_packet); +} +} // namespace media +#endif namespace content { class TizenRendererImpl::RendererClientInternal final @@ -100,6 +116,14 @@ class TizenRendererImpl::RendererClientInternal final renderer_->OnBufferUpdate(time); } +#if defined(TIZEN_TBM_SUPPORT) + void OnNewTbmFrameAvailable(uint32_t player_id, + const gfx::TbmBufferHandle& tbm_handle, + base::TimeDelta timestamp) override { + DCHECK(type_ == media::DemuxerStream::VIDEO); + renderer_->OnNewTbmFrameAvailable(player_id, tbm_handle, timestamp); + } +#else void OnNewFrameAvailable(uint32_t playerId, base::UnsafeSharedMemoryRegion frame, uint32_t size, @@ -109,6 +133,7 @@ class TizenRendererImpl::RendererClientInternal final renderer_->OnNewFrameAvailable(playerId, std::move(frame), size, timestamp, width, height); } +#endif private: media::DemuxerStream::Type type_; @@ -242,11 +267,17 @@ void TizenRendererImpl::SetStreamInfo() { media::DemuxerStream::VIDEO, this); GetPlayer()->SetStreamInfo(media::DemuxerStream::VIDEO, video_stream_, video_renderer_client_.get()); - +#if defined(TIZEN_TBM_SUPPORT) + media::MediaPlayerESPlusPlayer::GetMediaPlayerESPlusPlayer() + ->SetFrameAvailableCallback( + base::BindRepeating(&TizenRendererImpl::OnNewTbmFrameAvailable, + base::Unretained(this))); +#else // Will be removed later by using |ClientExtention| interface. media::MediaPlayerESPlusPlayer::GetMediaPlayerESPlusPlayer() ->SetFrameAvailableCallback(base::BindRepeating( &TizenRendererImpl::OnNewFrameAvailable, base::Unretained(this))); +#endif } } @@ -451,4 +482,18 @@ void TizenRendererImpl::OnBufferUpdate(base::TimeDelta time) { client_extension_->OnBufferUpdate(time); } +#if defined(TIZEN_TBM_SUPPORT) +void TizenRendererImpl::OnNewTbmFrameAvailable(uint32_t player_id, + gfx::TbmBufferHandle tbm_handle, + base::TimeDelta timestamp) { + client_extension_->OnNewTbmFrameAvailable(player_id, tbm_handle, timestamp); +} + +void TizenRendererImpl::OnTbmBufferExhausted( + const gfx::TbmBufferHandle& tbm_handle) { + media_player_->DestroyMediaPacket( + reinterpret_cast(tbm_handle.media_packet)); +} +#endif + } // namespace content 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 f7c469f..fbb96a8 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 @@ -98,6 +98,13 @@ class CONTENT_EXPORT TizenRendererImpl uint32_t width, uint32_t height); +#if defined(TIZEN_TBM_SUPPORT) + void OnNewTbmFrameAvailable(uint32_t player_id, + gfx::TbmBufferHandle tbm_handle, + base::TimeDelta timestamp); + void OnTbmBufferExhausted(const gfx::TbmBufferHandle& tbm_handle) override; +#endif + private: class RendererClientInternal; const float kDefaultVolume = 1.0; diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc index 4756451..0ae0b6c 100644 --- a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc +++ b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc @@ -134,4 +134,32 @@ void MediaPlayerRendererClient::OnBufferUpdate(base::TimeDelta time) { } #endif +#if defined(TIZEN_TBM_SUPPORT) +void MediaPlayerRendererClient::OnTbmBufferExhausted( + media::VideoFrame* video_frame, + void* media_packet, + int player_id) { + gfx::TbmBufferHandle tbm_handle; + tbm_handle.media_packet = reinterpret_cast(media_packet); + tbm_handle.player_id = player_id; + renderer_extension_remote_->OnTbmBufferExhausted(tbm_handle); +} + +void MediaPlayerRendererClient::OnNewTbmFrameAvailable( + uint32_t playerId, + const gfx::TbmBufferHandle& tbm_buffer_handle, + base::TimeDelta timestamp) { + gfx::Size size(tbm_buffer_handle.width, tbm_buffer_handle.height); + scoped_refptr video_frame = + media::VideoFrame::WrapTBMSurface(size, timestamp, tbm_buffer_handle); + video_frame->AddDestructionObserver(base::BindOnce( + &MediaPlayerRendererClient::OnTbmBufferExhausted, + weak_factory_.GetWeakPtr(), base::Unretained(video_frame.get()), + const_cast((const void*)tbm_buffer_handle.media_packet), + tbm_buffer_handle.player_id)); + + sink_->PaintSingleFrame(std::move(video_frame)); +} +#endif + } // namespace content diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h index 930fbb6..f601a44 100644 --- a/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h +++ b/tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h @@ -23,6 +23,10 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" +#if defined(TIZEN_TBM_SUPPORT) +#include "tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h" +#endif + namespace content { // MediaPlayerRendererClient lives in Renderer process and mirrors a @@ -69,6 +73,14 @@ class CONTENT_EXPORT MediaPlayerRendererClient base::TimeDelta timestamp, uint32_t width, uint32_t height) override; +#if defined(TIZEN_TBM_SUPPORT) + void OnNewTbmFrameAvailable(uint32_t playerId, + const gfx::TbmBufferHandle& tbm_buffer_handle, + base::TimeDelta timestamp) override; + void OnTbmBufferExhausted(media::VideoFrame* video_frame, + void* media_packet, + int player_id); +#endif private: void OnRemoteRendererInitialized(media::PipelineStatus status); diff --git a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc index a122ed2..45e9b99 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc +++ b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.cc @@ -9,14 +9,21 @@ #include "base/logging.h" #include "media/base/renderer_client.h" #include "media/base/tizen/media_player_bridge_capi.h" +#include "tizen_src/chromium_impl/media/filters/media_player_registry.h" namespace media { MediaPlayerBridgeCapiAdapter::MediaPlayerBridgeCapiAdapter(const GURL& url, double volume) - : url_(url), volume_(volume) {} + : url_(url), volume_(volume) { + LOG(INFO) << "(" << static_cast(this) << ") " << __func__; + player_id_ = MediaPlayerRegistry::GetInstance()->RegisterMediaPlayer(this); +} -MediaPlayerBridgeCapiAdapter::~MediaPlayerBridgeCapiAdapter() {} +MediaPlayerBridgeCapiAdapter::~MediaPlayerBridgeCapiAdapter() { + LOG(INFO) << "(" << static_cast(this) << ") " << __func__; + MediaPlayerRegistry::GetInstance()->UnregisterMediaPlayer(player_id_); +} bool MediaPlayerBridgeCapiAdapter::CreatePlayer() { if (media_player_) @@ -193,7 +200,7 @@ void MediaPlayerBridgeCapiAdapter::OnNewTbmBufferAvailable( void* media_packet = reinterpret_cast(tbm_handle.media_packet); tbm_handle.media_packet = reinterpret_cast(media_packet); - tbm_handle.player_handle = reinterpret_cast(this); + tbm_handle.player_id = player_id_; tbm_handle.width = width_; tbm_handle.height = height_; diff --git a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h index 3b348fe..26df8d0 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h +++ b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h @@ -112,6 +112,8 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiAdapter : public MediaPlayerTizen, bool is_initialized_ = false; bool is_prepared_ = false; + int player_id_ = 0; + int width_ = 0; int height_ = 0; }; diff --git a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc index b5f83e3..baab703 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc +++ b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc @@ -14,6 +14,7 @@ #include "media/base/decoder_buffer.h" #include "media/base/renderer_client.h" #include "third_party/libyuv/include/libyuv/convert.h" +#include "tizen_src/chromium_impl/media/filters/media_player_registry.h" namespace media { using player_buffer_size_t = unsigned long long; @@ -125,6 +126,8 @@ MediaPlayerESPlusPlayer::~MediaPlayerESPlusPlayer() { LOG(INFO) << "(" << static_cast(this) << ") " << __func__; weak_factory_.InvalidateWeakPtrs(); + MediaPlayerRegistry::GetInstance()->UnregisterMediaPlayer(player_id_); + int error = esplusplayer_destroy(esplayer_); if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) LOG(ERROR) << "esplusplayer_destroy failed, error #" @@ -181,6 +184,8 @@ void MediaPlayerESPlusPlayer::Initialize(VideoRendererSink* sink) { return; } + player_id_ = MediaPlayerRegistry::GetInstance()->RegisterMediaPlayer(this); + LOG(INFO) << "(" << static_cast(this) << ") " << __func__ << " state:" << GetString(GetPlayerState()); @@ -506,6 +511,20 @@ base::TimeDelta MediaPlayerESPlusPlayer::GetCurrentTime() { return current_position_; } +#if defined(TIZEN_TBM_SUPPORT) +void MediaPlayerESPlusPlayer::DestroyMediaPacket(void* media_packet) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::DestroyMediaPacket, + weak_factory_.GetWeakPtr(), media_packet)); + return; + } + + esplusplayer_decoded_buffer_destroy( + esplayer_, static_cast(media_packet)); +} +#endif + esplusplayer_state MediaPlayerESPlusPlayer::GetPlayerState() { return (esplayer_ ? esplusplayer_get_state(esplayer_) : ESPLUSPLAYER_STATE_NONE); @@ -911,6 +930,15 @@ void MediaPlayerESPlusPlayer::OnFrameReady( << ", duration:" << packet->duration << ", Player(" << esplayer_ << ", state:" << GetString(GetPlayerState()); +#if defined(TIZEN_TBM_SUPPORT) + gfx::TbmBufferHandle tbm_handle; + tbm_handle.tbm_surface = reinterpret_cast(tbm_surface); + tbm_handle.media_packet = reinterpret_cast(packet); + tbm_handle.player_id = player_id_; + tbm_handle.width = width; + tbm_handle.height = height; + data_cb_.Run(0, tbm_handle, timestamp); +#else base::UnsafeSharedMemoryRegion shared_memory; uint32_t shared_memory_size = suf_info.planes[0].size + (suf_info.planes[0].size / 2); @@ -994,6 +1022,7 @@ void MediaPlayerESPlusPlayer::OnFrameReady( sink_->PaintSingleFrame(video_frame); } +#endif } void MediaPlayerESPlusPlayer::OnFlushComplete() { diff --git a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h index a557153..3992847 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h +++ b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h @@ -31,6 +31,10 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen { public: static MediaPlayerESPlusPlayer* GetMediaPlayerESPlusPlayer(); +#if defined(TIZEN_TBM_SUPPORT) + using DataRequestCB = base::RepeatingCallback< + void(uint32_t, gfx::TbmBufferHandle, base::TimeDelta)>; +#else using DataRequestCB = base::RepeatingCallback; +#endif + bool CreatePlayer() override; void Initialize(VideoRendererSink* sink) override; bool IsInitialized() override; @@ -65,6 +71,10 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen { void SetFrameAvailableCallback(const DataRequestCB& datacb) override; +#if defined(TIZEN_TBM_SUPPORT) + void DestroyMediaPacket(void* media_packet) override; +#endif + // Callback handler void OnReadyToPrepare(const esplusplayer_stream_type stream_type); void OnPrepareComplete(bool result); @@ -157,6 +167,9 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen { bool should_set_playback_rate_ = false; base::OnceClosure flush_cb_; + + int player_id_ = 0; + DataRequestCB data_cb_; VideoRendererSink* sink_; diff --git a/tizen_src/chromium_impl/media/filters/media_player_registry.cc b/tizen_src/chromium_impl/media/filters/media_player_registry.cc new file mode 100644 index 0000000..0f21b49 --- /dev/null +++ b/tizen_src/chromium_impl/media/filters/media_player_registry.cc @@ -0,0 +1,41 @@ +// 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 "tizen_src/chromium_impl/media/filters/media_player_registry.h" + +#include "base/logging.h" +#include "base/process/process_handle.h" + +namespace media { + +MediaPlayerRegistry* MediaPlayerRegistry::GetInstance() { + return base::Singleton::get(); +} + +MediaPlayerRegistry::MediaPlayerRegistry() { + next_media_player_id_ = base::GetCurrentProcId(); +} + +MediaPlayerRegistry::~MediaPlayerRegistry() {} + +int MediaPlayerRegistry::RegisterMediaPlayer(MediaPlayerTizen* player) { + LOG(INFO) << __func__ << " player id: " << next_media_player_id_; + media_players_[next_media_player_id_] = player; + return next_media_player_id_++; +} + +void MediaPlayerRegistry::UnregisterMediaPlayer(int player_id) { + LOG(INFO) << __func__ << " player id: " << player_id; + media_players_.erase(player_id); +} + +MediaPlayerTizen* MediaPlayerRegistry::GetMediaPlayer(int player_id) { + std::map::iterator iter = + media_players_.find(player_id); + if (iter != media_players_.end()) + return iter->second; + return nullptr; +} + +} // namespace media diff --git a/tizen_src/chromium_impl/media/filters/media_player_registry.h b/tizen_src/chromium_impl/media/filters/media_player_registry.h new file mode 100644 index 0000000..0576fba --- /dev/null +++ b/tizen_src/chromium_impl/media/filters/media_player_registry.h @@ -0,0 +1,42 @@ +// 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. + +#ifndef MEDIA_FILTERS_MEDIA_PLAYER_REGISTRY_H_ +#define MEDIA_FILTERS_MEDIA_PLAYER_REGISTRY_H_ + +#include + +#include "base/memory/singleton.h" +#include "media/base/media_export.h" + +namespace media { + +class MediaPlayerTizen; + +class MEDIA_EXPORT MediaPlayerRegistry { + public: + static MediaPlayerRegistry* GetInstance(); + + int RegisterMediaPlayer(MediaPlayerTizen* player); + void UnregisterMediaPlayer(int player_id); + + MediaPlayerTizen* GetMediaPlayer(int player_id); + + private: + MediaPlayerRegistry(); + ~MediaPlayerRegistry(); + + MediaPlayerRegistry(const MediaPlayerRegistry&) = delete; + MediaPlayerRegistry& operator=(const MediaPlayerRegistry&) = delete; + + int next_media_player_id_; + + std::map media_players_; + + friend struct base::DefaultSingletonTraits; +}; + +} // namespace media + +#endif // MEDIA_FILTERS_MEDIA_PLAYER_REGISTRY_H_ diff --git a/tizen_src/chromium_impl/media/media_efl.gni b/tizen_src/chromium_impl/media/media_efl.gni index e158e8a..ff1ba71 100644 --- a/tizen_src/chromium_impl/media/media_efl.gni +++ b/tizen_src/chromium_impl/media/media_efl.gni @@ -104,6 +104,8 @@ if (tizen_multimedia) { "//tizen_src/chromium_impl/media/filters/media_player_bridge_capi_adapter.h", "//tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc", "//tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h", + "//tizen_src/chromium_impl/media/filters/media_player_registry.cc", + "//tizen_src/chromium_impl/media/filters/media_player_registry.h", "//tizen_src/chromium_impl/media/filters/media_player_tizen.h", ] diff --git a/tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h b/tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h new file mode 100644 index 0000000..4e82dcd --- /dev/null +++ b/tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h @@ -0,0 +1,35 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_TBM_BUFFER_HANDLE_H +#define UI_GFX_TBM_BUFFER_HANDLE_H + +#include +#include "ui/gfx/gfx_export.h" + +#if defined(TIZEN_TBM_SUPPORT) +#include +#include +#include +#endif + +namespace gfx { + +struct GFX_EXPORT TbmBufferHandle { + TbmBufferHandle() {} +#if defined(TIZEN_TBM_SUPPORT) + uint32_t tbm_surface{0}; + uint32_t media_packet{0}; + int32_t player_id = 0; + int32_t key_num = 0; + int32_t key[4]; + int32_t strides[4]; + int32_t width = 0; + int32_t height = 0; +#endif +}; + +} // namespace gfx + +#endif diff --git a/tizen_src/chromium_impl/ui/ui_efl.gni b/tizen_src/chromium_impl/ui/ui_efl.gni index bb54b8b..3f2beaa 100644 --- a/tizen_src/chromium_impl/ui/ui_efl.gni +++ b/tizen_src/chromium_impl/ui/ui_efl.gni @@ -62,6 +62,7 @@ external_ui_gfx_sources = [ "//tizen_src/chromium_impl/ui/display/device_display_info_efl.cc", "//tizen_src/chromium_impl/ui/display/device_display_info_efl.h", "//tizen_src/chromium_impl/ui/display/device_display_info_observer_efl.h", + "//tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h", ] # For //ui/gfx/x target diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index 8ad8af9..13b77ba 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h @@ -85,6 +85,16 @@ struct GFX_EXPORT GpuMemoryBufferHandle { #elif BUILDFLAG(IS_ANDROID) base::android::ScopedHardwareBufferHandle android_hardware_buffer; #endif +#if defined(TIZEN_TBM_SUPPORT) + uint32_t tbm_surface{0}; + uint32_t media_packet{0}; + int32_t player_id = 0; + int32_t key_num = 0; + int32_t key[4]; + int32_t strides[4]; + int32_t width = 0; + int32_t height = 0; +#endif }; // This interface typically correspond to a type of shared memory that is also diff --git a/ui/gfx/mojom/BUILD.gn b/ui/gfx/mojom/BUILD.gn index 3c8d0eb..91a2f6e 100644 --- a/ui/gfx/mojom/BUILD.gn +++ b/ui/gfx/mojom/BUILD.gn @@ -4,6 +4,9 @@ import("//build/config/ozone.gni") import("//mojo/public/tools/bindings/mojom.gni") +if (use_efl) { + import("//tizen_src/build/config/tizen_features.gni") +} mojom("mojom") { generate_java = true @@ -49,6 +52,9 @@ mojom("mojom") { if (ozone_platform_x11) { enabled_features += [ "enable_x11_params" ] } + if (tizen_tbm_support) { + enabled_features += [ "tizen_tbm_support" ] + } shared_cpp_typemaps = [ { @@ -84,6 +90,10 @@ mojom("mojom") { mojom = "gfx.mojom.GpuMemoryBufferType" cpp = "::gfx::GpuMemoryBufferType" }, + { + mojom = "gfx.mojom.TbmBufferHandle" + cpp = "::gfx::TbmBufferHandle" + }, ] traits_headers = [ "buffer_types_mojom_traits.h" ] diff --git a/ui/gfx/mojom/buffer_types.mojom b/ui/gfx/mojom/buffer_types.mojom index 4fa5ca2..4e989d4 100644 --- a/ui/gfx/mojom/buffer_types.mojom +++ b/ui/gfx/mojom/buffer_types.mojom @@ -65,5 +65,57 @@ struct GpuMemoryBufferHandle { GpuMemoryBufferId id; uint32 offset; uint32 stride; + + [EnableIf=tizen_tbm_support] + uint32 tbm_surface; + + [EnableIf=tizen_tbm_support] + uint32 media_packet; + + [EnableIf=tizen_tbm_support] + int32 player_id; + + [EnableIf=tizen_tbm_support] + int32 key_num; + + [EnableIf=tizen_tbm_support] + array key; + + [EnableIf=tizen_tbm_support] + array strides; + + [EnableIf=tizen_tbm_support] + int32 width; + + [EnableIf=tizen_tbm_support] + int32 height; + GpuMemoryBufferPlatformHandle? platform_handle; }; + +// gfx::TbmBufferHandle +struct TbmBufferHandle { + [EnableIf=tizen_tbm_support] + uint32 tbm_surface; + + [EnableIf=tizen_tbm_support] + uint32 media_packet; + + [EnableIf=tizen_tbm_support] + int32 player_id; + + [EnableIf=tizen_tbm_support] + int32 key_num; + + [EnableIf=tizen_tbm_support] + array key; + + [EnableIf=tizen_tbm_support] + array strides; + + [EnableIf=tizen_tbm_support] + int32 width; + + [EnableIf=tizen_tbm_support] + int32 height; +}; diff --git a/ui/gfx/mojom/buffer_types_mojom_traits.cc b/ui/gfx/mojom/buffer_types_mojom_traits.cc index 0f6ffe1..9b7d0e4 100644 --- a/ui/gfx/mojom/buffer_types_mojom_traits.cc +++ b/ui/gfx/mojom/buffer_types_mojom_traits.cc @@ -98,7 +98,21 @@ bool StructTraitsoffset = data.offset(); out->stride = data.stride(); +#if defined(TIZEN_TBM_SUPPORT) + out->tbm_surface = data.tbm_surface(); + out->media_packet = data.media_packet(); + out->player_id = data.player_id(); + out->key_num = data.key_num(); + out->width = data.width(); + out->height = data.height(); + base::span key(out->key); + if (!data.ReadKey(&key)) + return false; + base::span strides(out->strides); + if (!data.ReadStrides(&strides)) + return false; +#endif gfx::mojom::GpuMemoryBufferPlatformHandlePtr platform_handle; if (!data.ReadPlatformHandle(&platform_handle)) { return false; @@ -168,4 +182,53 @@ bool StructTraits StructTraits< + gfx::mojom::GpuMemoryBufferHandleDataView, + gfx::GpuMemoryBufferHandle>::key(const gfx::GpuMemoryBufferHandle& input) { + return input.key; +} + +// static +base::span StructTraits< + gfx::mojom::GpuMemoryBufferHandleDataView, + gfx::GpuMemoryBufferHandle>::strides(const gfx::GpuMemoryBufferHandle& + input) { + return input.strides; +} + +bool StructTraits:: + Read(gfx::mojom::TbmBufferHandleDataView data, gfx::TbmBufferHandle* out) { + out->tbm_surface = data.tbm_surface(); + out->media_packet = data.media_packet(); + out->player_id = data.player_id(); + out->key_num = data.key_num(); + out->width = data.width(); + out->height = data.height(); + base::span key(out->key); + if (!data.ReadKey(&key)) + return false; + + base::span strides(out->strides); + if (!data.ReadStrides(&strides)) + return false; + return true; +} + +// static +base::span +StructTraits::key( + const gfx::TbmBufferHandle& input) { + return input.key; +} + +// static +base::span +StructTraits::strides(const gfx::TbmBufferHandle& input) { + return input.strides; +} +#endif + } // namespace mojo diff --git a/ui/gfx/mojom/buffer_types_mojom_traits.h b/ui/gfx/mojom/buffer_types_mojom_traits.h index fc160f3..0f62f6c 100644 --- a/ui/gfx/mojom/buffer_types_mojom_traits.h +++ b/ui/gfx/mojom/buffer_types_mojom_traits.h @@ -16,6 +16,10 @@ #include "ui/gfx/mojom/buffer_types.mojom-shared.h" #include "ui/gfx/mojom/native_handle_types.mojom.h" +#if defined(TIZEN_TBM_SUPPORT) +#include "tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h" +#endif + namespace mojo { template <> @@ -233,6 +237,31 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) static uint32_t stride(const gfx::GpuMemoryBufferHandle& handle) { return handle.stride; } +#if defined(TIZEN_TBM_SUPPORT) + static uint32_t tbm_surface(const gfx::GpuMemoryBufferHandle& handle) { + return handle.tbm_surface; + } + static uint32_t media_packet(const gfx::GpuMemoryBufferHandle& handle) { + return handle.media_packet; + } + static int32_t player_id(const gfx::GpuMemoryBufferHandle& handle) { + return handle.player_id; + } + + static int32_t key_num(const gfx::GpuMemoryBufferHandle& handle) { + return handle.key_num; + } + static base::span key(const gfx::GpuMemoryBufferHandle& input); + static base::span strides( + const gfx::GpuMemoryBufferHandle& input); + + static int32_t width(const gfx::GpuMemoryBufferHandle& handle) { + return handle.width; + } + static int32_t height(const gfx::GpuMemoryBufferHandle& handle) { + return handle.height; + } +#endif static mojo::StructPtr platform_handle(gfx::GpuMemoryBufferHandle& handle); @@ -240,6 +269,38 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) gfx::GpuMemoryBufferHandle* handle); }; +#if defined(TIZEN_TBM_SUPPORT) +template <> +struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) + StructTraits { + static uint32_t tbm_surface(const gfx::TbmBufferHandle& handle) { + return handle.tbm_surface; + } + static uint32_t media_packet(const gfx::TbmBufferHandle& handle) { + return handle.media_packet; + } + static int32_t player_id(const gfx::TbmBufferHandle& handle) { + return handle.player_id; + } + + static int32_t key_num(const gfx::TbmBufferHandle& handle) { + return handle.key_num; + } + static base::span key(const gfx::TbmBufferHandle& input); + static base::span strides(const gfx::TbmBufferHandle& input); + + static int32_t width(const gfx::TbmBufferHandle& handle) { + return handle.width; + } + static int32_t height(const gfx::TbmBufferHandle& handle) { + return handle.height; + } + + static bool Read(gfx::mojom::TbmBufferHandleDataView data, + gfx::TbmBufferHandle* handle); +}; +#endif + template <> struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) EnumTraits { diff --git a/ui/gl/gl_image_egl.cc b/ui/gl/gl_image_egl.cc index 84635e5..d72f414 100644 --- a/ui/gl/gl_image_egl.cc +++ b/ui/gl/gl_image_egl.cc @@ -9,6 +9,12 @@ #include "ui/gl/gl_enums.h" #include "ui/gl/gl_surface_egl.h" +#if defined(TIZEN_TBM_SUPPORT) +namespace media { +void DestroyMediaPacket(void* media_packet_handle, int player_id); +} +#endif + namespace gl { GLImageEGL::GLImageEGL(const gfx::Size& size) @@ -23,6 +29,10 @@ GLImageEGL::~GLImageEGL() { GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay(), egl_image_); if (result == EGL_FALSE) DLOG(ERROR) << "Error destroying EGLImage: " << ui::GetLastEGLErrorString(); + +#if defined(TIZEN_TBM_SUPPORT) + media::DestroyMediaPacket(media_packet_, player_id_); +#endif } bool GLImageEGL::Initialize(EGLContext context, @@ -39,6 +49,29 @@ bool GLImageEGL::Initialize(EGLContext context, return success; } +#if defined(TIZEN_TBM_SUPPORT) +bool GLImageEGL::Initialize(EGLenum target, + EGLClientBuffer buffer, + const EGLint* attrs, + void* media_packet, + int player_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); + media_packet_ = media_packet; + player_id_ = player_id; + + egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetGLDisplayEGL()->GetDisplay(), + EGL_NO_CONTEXT, target, buffer, attrs); + if (egl_image_ == EGL_NO_IMAGE_KHR) { + DLOG(ERROR) << "Error creating EGLImage: " << ui::GetLastEGLErrorString(); + media::DestroyMediaPacket(media_packet_, player_id_); + return false; + } + + return true; +} +#endif + gfx::Size GLImageEGL::GetSize() { return size_; } diff --git a/ui/gl/gl_image_egl.h b/ui/gl/gl_image_egl.h index 0afd7d4..d46ae79 100644 --- a/ui/gl/gl_image_egl.h +++ b/ui/gl/gl_image_egl.h @@ -18,6 +18,13 @@ namespace gl { class GL_EXPORT GLImageEGL : public GLImage { public: explicit GLImageEGL(const gfx::Size& size); +#if defined(TIZEN_TBM_SUPPORT) + bool Initialize(unsigned target, + void* buffer, + const EGLint* attrs, + void* media_packet, + int player_id); +#endif GLImageEGL(const GLImageEGL&) = delete; GLImageEGL& operator=(const GLImageEGL&) = delete; @@ -47,6 +54,10 @@ class GL_EXPORT GLImageEGL : public GLImage { const EGLint* attrs); raw_ptr egl_image_ /* EGLImageKHR */; +#if defined(TIZEN_TBM_SUPPORT) + void* media_packet_; + int player_id_; +#endif const gfx::Size size_; base::ThreadChecker thread_checker_; }; diff --git a/ui/gl/gl_image_native_pixmap.cc b/ui/gl/gl_image_native_pixmap.cc index e48a7d5..72b5fca 100644 --- a/ui/gl/gl_image_native_pixmap.cc +++ b/ui/gl/gl_image_native_pixmap.cc @@ -17,6 +17,11 @@ #include "ui/gl/gl_enums.h" #include "ui/gl/gl_surface_egl.h" +#if defined(TIZEN_TBM_SUPPORT) +#include "ui/gfx/gpu_memory_buffer.h" +#define EGL_NATIVE_SURFACE_TIZEN 0x32A1 +#endif + #define FOURCC(a, b, c, d) \ ((static_cast(a)) | (static_cast(b) << 8) | \ (static_cast(c) << 16) | (static_cast(d) << 24)) @@ -138,6 +143,21 @@ GLImageNativePixmap::GLImageNativePixmap(const gfx::Size& size, GLImageNativePixmap::~GLImageNativePixmap() {} +#if defined(TIZEN_TBM_SUPPORT) +bool GLImageNativePixmap::Initialize(const gfx::GpuMemoryBufferHandle& handle) { + EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + tbm_surface_h surface = reinterpret_cast(handle.tbm_surface); + if (!GLImageEGL::Initialize(EGL_NATIVE_SURFACE_TIZEN, + static_cast(surface), attrs, + reinterpret_cast(handle.media_packet), + handle.player_id)) { + return false; + } + + return true; +} +#endif + bool GLImageNativePixmap::Initialize(scoped_refptr pixmap) { DCHECK(!pixmap_); if (GLInternalFormat(format_) == GL_NONE) { diff --git a/ui/gl/gl_image_native_pixmap.h b/ui/gl/gl_image_native_pixmap.h index ea5c883..fbe3dfc9 100644 --- a/ui/gl/gl_image_native_pixmap.h +++ b/ui/gl/gl_image_native_pixmap.h @@ -13,6 +13,15 @@ #include "ui/gl/gl_export.h" #include "ui/gl/gl_image_egl.h" +#if defined(TIZEN_TBM_SUPPORT) +#include +#include +#include +namespace gfx { +struct GpuMemoryBufferHandle; +} +#endif + namespace gl { class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL { @@ -21,6 +30,9 @@ class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL { gfx::BufferFormat format, gfx::BufferPlane plane = gfx::BufferPlane::DEFAULT); +#if defined(TIZEN_TBM_SUPPORT) + bool Initialize(const gfx::GpuMemoryBufferHandle& handle); +#endif // Create an EGLImage from a given NativePixmap. bool Initialize(scoped_refptr pixmap); bool InitializeForOverlay(scoped_refptr pixmap); @@ -53,6 +65,12 @@ class GL_EXPORT GLImageNativePixmap : public gl::GLImageEGL { bool has_image_flush_external_; bool has_image_dma_buf_export_; bool did_initialize_; +#if defined(TIZEN_TBM_SUPPORT) + tbm_bufmgr bufmgr_; + tbm_surface_h tbm_surf_; + tbm_bo bos_[4] = {0}; + tbm_surface_info_s tbmsi_; +#endif }; } // namespace gl -- 2.7.4 From 075464657be3de22a8af1fa73df9b24887dbc620 Mon Sep 17 00:00:00 2001 From: Gajendra N Date: Fri, 27 Jan 2023 11:53:38 +0530 Subject: [PATCH 14/16] [M108 Migration][SAM] Migrate SAM score improvement patches Improves MCD Score from 2.08 to 3.33. Reduces LOC for WebContentsDelegateEfl by ~280 lines. Reduces LOC for ContentBrowserClientEfl by ~85 lines. References: https://review.tizen.org/gerrit/275891 https://review.tizen.org/gerrit/275576 https://review.tizen.org/gerrit/275660 https://review.tizen.org/gerrit/276084 Change-Id: Ic034b902c7ccf9d74c100641aadbf604763c5f95 Signed-off-by: Gajendra N --- tizen_src/ewk/efl_integration/BUILD.gn | 14 +- .../{ => browser}/autofill_popup_view_efl.cc | 0 .../{ => browser}/autofill_popup_view_efl.h | 0 .../notification/notification_controller_efl.cc | 1 + .../browser/policy_response_delegate_efl.cc | 3 +- .../browser/web_view_browser_message_filter.cc | 1 + .../ewk/efl_integration/browser_context_efl.h | 2 +- .../efl_integration/content_browser_client_efl.cc | 257 +++++++++-------- .../efl_integration/content_browser_client_efl.h | 82 +++--- .../efl_integration/context_menu_controller_efl.cc | 3 + .../{browser => }/download_manager_delegate_efl.cc | 2 +- .../{browser => }/download_manager_delegate_efl.h | 0 tizen_src/ewk/efl_integration/eweb_view.cc | 2 + tizen_src/ewk/efl_integration/eweb_view.h | 2 +- .../{browser => }/login_delegate_efl.cc | 0 .../{browser => }/login_delegate_efl.h | 0 .../private/ewk_auth_challenge_private.h | 2 +- .../ewk_context_form_autofill_profile_private.cc | 1 + .../efl_integration/web_contents_delegate_efl.cc | 276 +----------------- .../efl_integration/web_contents_delegate_efl.h | 137 +++------ .../efl_integration/web_contents_observer_efl.cc | 318 +++++++++++++++++++++ .../efl_integration/web_contents_observer_efl.h | 99 +++++++ 22 files changed, 652 insertions(+), 550 deletions(-) rename tizen_src/ewk/efl_integration/{ => browser}/autofill_popup_view_efl.cc (100%) rename tizen_src/ewk/efl_integration/{ => browser}/autofill_popup_view_efl.h (100%) rename tizen_src/ewk/efl_integration/{browser => }/download_manager_delegate_efl.cc (98%) rename tizen_src/ewk/efl_integration/{browser => }/download_manager_delegate_efl.h (100%) rename tizen_src/ewk/efl_integration/{browser => }/login_delegate_efl.cc (100%) rename tizen_src/ewk/efl_integration/{browser => }/login_delegate_efl.h (100%) create mode 100644 tizen_src/ewk/efl_integration/web_contents_observer_efl.cc create mode 100644 tizen_src/ewk/efl_integration/web_contents_observer_efl.h diff --git a/tizen_src/ewk/efl_integration/BUILD.gn b/tizen_src/ewk/efl_integration/BUILD.gn index bfbb46a..feee814 100755 --- a/tizen_src/ewk/efl_integration/BUILD.gn +++ b/tizen_src/ewk/efl_integration/BUILD.gn @@ -185,21 +185,17 @@ shared_library("chromium-ewk") { sources = [ "authentication_challenge_popup.cc", "authentication_challenge_popup.h", - "autofill_popup_view_efl.cc", - "autofill_popup_view_efl.h", + "browser/autofill_popup_view_efl.cc", + "browser/autofill_popup_view_efl.h", "browser/background_sync_controller_efl.cc", "browser/background_sync_controller_efl.h", "browser/browsing_data_remover_efl.cc", "browser/browsing_data_remover_efl.h", - "browser/download_manager_delegate_efl.cc", - "browser/download_manager_delegate_efl.h", "browser/intercept_request_params.h", "browser/javascript_dialog_manager_efl.cc", "browser/javascript_dialog_manager_efl.h", "browser/javascript_modal_dialog_efl.cc", "browser/javascript_modal_dialog_efl.h", - "browser/login_delegate_efl.cc", - "browser/login_delegate_efl.h", "browser/mime_override_manager_efl.cc", "browser/mime_override_manager_efl.h", "browser/navigation_policy_handler_efl.cc", @@ -245,6 +241,8 @@ shared_library("chromium-ewk") { "devtools_delegate_efl.h", "devtools_manager_delegate_efl.cc", "devtools_manager_delegate_efl.h", + "download_manager_delegate_efl.cc", + "download_manager_delegate_efl.h", "efl_webprocess_main.cc", "efl_webprocess_main.h", "eweb_context.cc", @@ -260,6 +258,8 @@ shared_library("chromium-ewk") { "http_user_agent_settings_efl.h", "locale_efl.cc", "locale_efl.h", + "login_delegate_efl.cc", + "login_delegate_efl.h", "network_delegate_efl.cc", "network_delegate_efl.h", "notification_permission_popup.cc", @@ -578,6 +578,8 @@ shared_library("chromium-ewk") { "renderer/render_thread_observer_efl.h", "renderer/tizen_extensible.cc", "renderer/tizen_extensible.h", + "web_contents_observer_efl.cc", + "web_contents_observer_efl.h", "wrt/dynamicplugin.cc", "wrt/dynamicplugin.h", "wrt/v8widget.cc", diff --git a/tizen_src/ewk/efl_integration/autofill_popup_view_efl.cc b/tizen_src/ewk/efl_integration/browser/autofill_popup_view_efl.cc similarity index 100% rename from tizen_src/ewk/efl_integration/autofill_popup_view_efl.cc rename to tizen_src/ewk/efl_integration/browser/autofill_popup_view_efl.cc diff --git a/tizen_src/ewk/efl_integration/autofill_popup_view_efl.h b/tizen_src/ewk/efl_integration/browser/autofill_popup_view_efl.h similarity index 100% rename from tizen_src/ewk/efl_integration/autofill_popup_view_efl.h rename to tizen_src/ewk/efl_integration/browser/autofill_popup_view_efl.h diff --git a/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc b/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc index fedc587..f88b03c 100644 --- a/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/notification/notification_controller_efl.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" +#include "browser_context_efl.h" #include "common/web_contents_utils.h" #include "content/common/paths_efl.h" #include "content/public/browser/browser_thread.h" diff --git a/tizen_src/ewk/efl_integration/browser/policy_response_delegate_efl.cc b/tizen_src/ewk/efl_integration/browser/policy_response_delegate_efl.cc index 0378c0d..bf8ea0f 100644 --- a/tizen_src/ewk/efl_integration/browser/policy_response_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/browser/policy_response_delegate_efl.cc @@ -10,6 +10,7 @@ #include "browser/mime_override_manager_efl.h" #include "browser/network_service/browser_url_loader_throttle_efl.h" #include "browser/policy_response_params.h" +#include "browser_context_efl.h" #include "common/web_contents_utils.h" #include "content/public/browser/render_frame_host.h" #include "eweb_view.h" @@ -17,7 +18,7 @@ #include "private/ewk_policy_decision_private.h" #include "services/network/public/cpp/data_element.h" #include "services/network/public/cpp/features.h" -#include "services/network/public/mojom/url_response_head.mojom-forward.h" +#include "services/network/public/mojom/url_response_head.mojom.h" using web_contents_utils::WebViewFromWebContents; 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 3dc018f..7850c2e 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 @@ -14,6 +14,7 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" +#include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "eweb_view.h" #include "ipc_message_start_ewk.h" diff --git a/tizen_src/ewk/efl_integration/browser_context_efl.h b/tizen_src/ewk/efl_integration/browser_context_efl.h index 1f88ac0..bef9a1e 100644 --- a/tizen_src/ewk/efl_integration/browser_context_efl.h +++ b/tizen_src/ewk/efl_integration/browser_context_efl.h @@ -9,7 +9,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/synchronization/lock.h" -#include "browser/download_manager_delegate_efl.h" #include "browser/geolocation/geolocation_permission_context_efl.h" #include "browser/ssl_host_state_delegate_efl.h" #include "components/visitedlink/browser/visitedlink_delegate.h" @@ -17,6 +16,7 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/storage_partition.h" +#include "download_manager_delegate_efl.h" #include "url_request_context_getter_efl.h" class CookieManager; 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 23882ee..837b144 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.cc +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.cc @@ -14,6 +14,7 @@ #include "browser/quota_permission_context_efl.h" #include "browser/render_message_filter_efl.h" #include "browser/web_view_browser_message_filter.h" +#include "browser_context_efl.h" #include "browser_main_parts_efl.h" #include "command_line_efl.h" #include "common/content_switches_efl.h" @@ -23,6 +24,8 @@ #include "components/error_page/common/localized_error.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_iterator.h" #include "content/public/browser/web_contents.h" @@ -76,43 +79,8 @@ void PlatformLanguageChanged(keynode_t* keynode, void* data) { } #endif // BUILDFLAG(IS_TIZEN) -} // namespace - -ContentBrowserClientEfl::ContentBrowserClientEfl() - : browser_main_parts_efl_(nullptr), - notification_controller_(new NotificationControllerEfl), - accept_langs_(kDefaultAcceptLanguages) { -#if BUILDFLAG(IS_TIZEN) - PlatformLanguageChanged(nullptr, this); - vconf_notify_key_changed(VCONFKEY_LANGSET, PlatformLanguageChanged, this); -#endif -} - -ContentBrowserClientEfl::~ContentBrowserClientEfl() { -#if BUILDFLAG(IS_TIZEN) - vconf_ignore_key_changed(VCONFKEY_LANGSET, PlatformLanguageChanged); -#endif -} - -void ContentBrowserClientEfl::SetBrowserContext(BrowserContext* context) { - browser_context_.reset(context); -} - -void ContentBrowserClientEfl::CleanUpBrowserContext() { - browser_context_.reset(nullptr); - shutting_down_ = true; -} - -std::unique_ptr -ContentBrowserClientEfl::CreateBrowserMainParts(bool is_integration_test) { - auto browser_main_parts = std::make_unique(); - browser_main_parts_efl_ = browser_main_parts.get(); - return browser_main_parts; -} - -void ContentBrowserClientEfl::AppendExtraCommandLineSwitchesInternal( - base::CommandLine* command_line, - int child_process_id) { +void AppendExtraCommandLineSwitchesInternal(base::CommandLine* command_line, + int child_process_id) { if (!command_line->HasSwitch(switches::kProcessType)) return; @@ -159,6 +127,129 @@ void ContentBrowserClientEfl::AppendExtraCommandLineSwitchesInternal( widget_encoded_bundle); } +void DispatchPopupBlockedOnUIThread(int render_process_id, + const GURL& target_url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + std::unique_ptr widgets( + RenderWidgetHost::GetRenderWidgetHosts()); + RenderWidgetHost* widget = NULL; + + while ((widget = widgets->GetNextHost())) + if (widget->GetProcess()->GetID() == render_process_id) + break; + + // It may happen that this message will be handled on ui thread after view + // was closed. In such case ignore do nothing. + if (!widget) + return; + RenderViewHost* vh = RenderViewHost::From(widget); + if (!vh) + return; + + WebContents* content = WebContents::FromRenderViewHost(vh); + if (!content) + return; + + EWebView* wv = WebViewFromWebContents(content); + wv->SmartCallback().call( + target_url.spec().c_str()); +} + +} // namespace + +AcceptLanguagesHelper::AcceptLanguagesHelper() + : accept_langs_(kDefaultAcceptLanguages) {} + +AcceptLanguagesHelper::~AcceptLanguagesHelper() {} + +std::string AcceptLanguagesHelper::GetAcceptLangs() { + if (!preferred_langs_.empty()) + return preferred_langs_; + + return accept_langs_; +} + +void AcceptLanguagesHelper::SetAcceptLangs(const std::string& accept_langs) { + if (accept_langs.empty() || accept_langs_ == accept_langs) + return; + + accept_langs_ = accept_langs; + if (preferred_langs_.empty()) + NotifyAcceptLangsChanged(); +} + +void AcceptLanguagesHelper::SetPreferredLangs( + const std::string& preferred_langs) { + if (preferred_langs_ == preferred_langs) + return; + + preferred_langs_ = preferred_langs; + NotifyAcceptLangsChanged(); +} + +void AcceptLanguagesHelper::AddAcceptLangsChangedCallback( + AcceptLangsChangedCallback callback) { + if (callback) + accept_langs_changed_callbacks_.push_back(std::move(callback)); +} + +void AcceptLanguagesHelper::RemoveAcceptLangsChangedCallback( + AcceptLangsChangedCallback callback) { +#if !defined(EWK_BRINGUP) // FIXME: m94 bringup + for (size_t i = 0; i < accept_langs_changed_callbacks_.size(); ++i) { + if (accept_langs_changed_callbacks_[i] == callback) { + accept_langs_changed_callbacks_.erase( + accept_langs_changed_callbacks_.begin() + i); + return; + } + } +#endif +} + +void AcceptLanguagesHelper::NotifyAcceptLangsChanged() { + std::vector callbacks; + callbacks.swap(accept_langs_changed_callbacks_); + + for (auto& callback : callbacks) { + if (preferred_langs_.empty()) + std::move(callback).Run(accept_langs_); + else + std::move(callback).Run(preferred_langs_); + } +} + +ContentBrowserClientEfl::ContentBrowserClientEfl() + : notification_controller_(new NotificationControllerEfl), + accept_langs_helper_(new AcceptLanguagesHelper) { +#if BUILDFLAG(IS_TIZEN) + PlatformLanguageChanged(nullptr, this); + vconf_notify_key_changed(VCONFKEY_LANGSET, PlatformLanguageChanged, this); +#endif +} + +ContentBrowserClientEfl::~ContentBrowserClientEfl() { +#if BUILDFLAG(IS_TIZEN) + vconf_ignore_key_changed(VCONFKEY_LANGSET, PlatformLanguageChanged); +#endif +} + +void ContentBrowserClientEfl::SetBrowserContext(BrowserContext* context) { + browser_context_.reset(context); +} + +void ContentBrowserClientEfl::CleanUpBrowserContext() { + browser_context_.reset(nullptr); + shutting_down_ = true; +} + +std::unique_ptr +ContentBrowserClientEfl::CreateBrowserMainParts(bool is_integration_test) { + auto browser_main_parts = std::make_unique(); + browser_main_parts_efl_ = browser_main_parts.get(); + return browser_main_parts; +} + void ContentBrowserClientEfl::AppendExtraCommandLineSwitches( base::CommandLine* command_line, int child_process_id) { @@ -192,10 +283,9 @@ bool ContentBrowserClientEfl::CanCreateWindow( #if !defined(EWK_BRINGUP) // FIXME: m67 bringup if (!user_gesture) { *no_javascript_access = true; - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&ContentBrowserClientEfl::DispatchPopupBlockedOnUIThread, - render_process_id, target_url)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(&DispatchPopupBlockedOnUIThread, + render_process_id, target_url)); return false; } #endif @@ -218,36 +308,6 @@ bool ContentBrowserClientEfl::CanCreateWindow( return policy_decision->CanCreateWindow(); } -void ContentBrowserClientEfl::DispatchPopupBlockedOnUIThread( - int render_process_id, - const GURL& target_url) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - std::unique_ptr widgets( - RenderWidgetHost::GetRenderWidgetHosts()); - RenderWidgetHost* widget = NULL; - - while ((widget = widgets->GetNextHost())) - if (widget->GetProcess()->GetID() == render_process_id) - break; - - // It may happen that this message will be handled on ui thread after view - // was closed. In such case ignore do nothing. - if (!widget) - return; - RenderViewHost* vh = RenderViewHost::From(widget); - if (!vh) - return; - - WebContents* content = WebContents::FromRenderViewHost(vh); - if (!content) - return; - - EWebView* wv = WebViewFromWebContents(content); - wv->SmartCallback().call( - target_url.spec().c_str()); -} - bool ContentBrowserClientEfl::HasErrorPage(int http_status_code) { // Use an internal error page, if we have one for the status code. return error_page::LocalizedError::HasStrings( @@ -287,12 +347,6 @@ void ContentBrowserClientEfl::AllowCertificateError( #endif // !defined(EWK_BRINGUP) } -PlatformNotificationService* -ContentBrowserClientEfl::GetPlatformNotificationService( - BrowserContext* browser_context) { - return notification_controller_.get(); -} - NotificationControllerEfl* ContentBrowserClientEfl::GetNotificationController() const { return notification_controller_.get(); @@ -455,61 +509,26 @@ std::string ContentBrowserClientEfl::GetUserAgent() { } std::string ContentBrowserClientEfl::GetAcceptLangs(BrowserContext* context) { - if (!preferred_langs_.empty()) - return preferred_langs_; - - return accept_langs_; + return accept_langs_helper_->GetAcceptLangs(); } void ContentBrowserClientEfl::SetAcceptLangs(const std::string& accept_langs) { - if (accept_langs.empty() || accept_langs_ == accept_langs) - return; - - accept_langs_ = accept_langs; - - if (preferred_langs_.empty()) - NotifyAcceptLangsChanged(); + accept_langs_helper_->SetAcceptLangs(accept_langs); } void ContentBrowserClientEfl::SetPreferredLangs( const std::string& preferred_langs) { - if (preferred_langs_ == preferred_langs) - return; - - preferred_langs_ = preferred_langs; - - NotifyAcceptLangsChanged(); + accept_langs_helper_->SetPreferredLangs(preferred_langs); } void ContentBrowserClientEfl::AddAcceptLangsChangedCallback( - AcceptLangsChangedCallback callback) { - if (callback) - accept_langs_changed_callbacks_.push_back(std::move(callback)); + AcceptLanguagesHelper::AcceptLangsChangedCallback callback) { + accept_langs_helper_->AddAcceptLangsChangedCallback(std::move(callback)); } void ContentBrowserClientEfl::RemoveAcceptLangsChangedCallback( - AcceptLangsChangedCallback callback) { -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - for (size_t i = 0; i < accept_langs_changed_callbacks_.size(); ++i) { - if (accept_langs_changed_callbacks_[i] == callback) { - accept_langs_changed_callbacks_.erase( - accept_langs_changed_callbacks_.begin() + i); - return; - } - } -#endif -} - -void ContentBrowserClientEfl::NotifyAcceptLangsChanged() { - std::vector callbacks; - callbacks.swap(accept_langs_changed_callbacks_); - - for (auto& callback : callbacks) { - if (preferred_langs_.empty()) - std::move(callback).Run(accept_langs_); - else - std::move(callback).Run(preferred_langs_); - } + AcceptLanguagesHelper::AcceptLangsChangedCallback callback) { + accept_langs_helper_->RemoveAcceptLangsChangedCallback(std::move(callback)); } std::unique_ptr ContentBrowserClientEfl::CreateLoginDelegate( diff --git a/tizen_src/ewk/efl_integration/content_browser_client_efl.h b/tizen_src/ewk/efl_integration/content_browser_client_efl.h index 7b3f8f1..5ba1b1a 100644 --- a/tizen_src/ewk/efl_integration/content_browser_client_efl.h +++ b/tizen_src/ewk/efl_integration/content_browser_client_efl.h @@ -21,35 +21,47 @@ namespace content { class BrowserMainPartsEfl; class NotificationControllerEfl; class SharedURLLoaderFactoryEfl; - #if defined(TIZEN_WEB_SPEECH_RECOGNITION) class SpeechRecognitionManagerDelegate; #endif - class WebContents; class WebContentsView; -class ContentBrowserClientEfl : public ContentBrowserClient { +class AcceptLanguagesHelper { public: - typedef void (*Notification_Show_Callback)(Ewk_Notification*, void*); - typedef void (*Notification_Cancel_Callback)(uint64_t, void*); + using AcceptLangsChangedCallback = + base::OnceCallback; + AcceptLanguagesHelper(); + ~AcceptLanguagesHelper(); + + void SetAcceptLangs(const std::string& accept_langs); + void SetPreferredLangs(const std::string& preferred_langs); + std::string GetAcceptLangs(); + void AddAcceptLangsChangedCallback(AcceptLangsChangedCallback callback); + void RemoveAcceptLangsChangedCallback(AcceptLangsChangedCallback callback); + + private: + void NotifyAcceptLangsChanged(); + std::string accept_langs_; + std::string preferred_langs_; + std::vector accept_langs_changed_callbacks_; +}; + +class ContentBrowserClientEfl : public ContentBrowserClient { + public: ContentBrowserClientEfl(); ~ContentBrowserClientEfl() override; ContentBrowserClientEfl(const ContentBrowserClientEfl&) = delete; ContentBrowserClientEfl& operator=(const ContentBrowserClientEfl&) = delete; - typedef base::OnceCallback - AcceptLangsChangedCallback; + // ContentBrowserClient implementations. std::unique_ptr CreateBrowserMainParts( bool is_integration_test) override; - // Allows the embedder to pass extra command line flags. - // switches::kProcessType will already be set at this point. void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) override; - bool CanCreateWindow(RenderFrameHost* opener, const GURL& opener_url, const GURL& opener_top_level_frame_url, @@ -80,46 +92,29 @@ class ContentBrowserClientEfl : public ContentBrowserClient { bool is_main_frame_request, bool strict_enforcement, base::OnceCallback callback) override; - - PlatformNotificationService* GetPlatformNotificationService( - BrowserContext* browser_context); - - NotificationControllerEfl* GetNotificationController() const; - bool AllowGetCookie(const GURL& url, const GURL& first_party, const net::CookieList& cookie_list, ResourceContext* context, int render_process_id, int render_frame_id); - bool AllowSetCookie(const GURL& url, const GURL& first_party, const net::CanonicalCookie& cookie, ResourceContext* context, int render_process_id, int render_frame_id); - void OverrideWebkitPrefs(WebContents* web_contents, blink::web_pref::WebPreferences* prefs); - void RenderProcessWillLaunch(RenderProcessHost* host) override; - void SetCertificatePem(const net::SSLInfo& ssl_info, int render_process_id, int render_view_id); - DevToolsManagerDelegate* GetDevToolsManagerDelegate(); - std::string GetApplicationLocale() override; - std::unique_ptr GetWebContentsViewDelegate( WebContents* web_contents) override; - - void SetBrowserContext(BrowserContext* context); - void CleanUpBrowserContext(); - - virtual std::unique_ptr CreateLoginDelegate( + std::unique_ptr CreateLoginDelegate( const net::AuthChallengeInfo& auth_info, WebContents* web_contents, const GlobalRequestID& request_id, @@ -128,15 +123,17 @@ class ContentBrowserClientEfl : public ContentBrowserClient { scoped_refptr response_headers, bool first_auth_attempt, LoginAuthRequiredCallback auth_required_callback) override; - std::string GetProduct() override; std::string GetUserAgent() override; - - std::string GetAcceptLangs(BrowserContext* context) override; + NotificationControllerEfl* GetNotificationController() const; + void SetBrowserContext(BrowserContext* context); + void CleanUpBrowserContext(); void SetAcceptLangs(const std::string& accept_langs); void SetPreferredLangs(const std::string& preferred_langs); - void AddAcceptLangsChangedCallback(AcceptLangsChangedCallback callback); - void RemoveAcceptLangsChangedCallback(AcceptLangsChangedCallback callback); + void AddAcceptLangsChangedCallback( + AcceptLanguagesHelper::AcceptLangsChangedCallback callback); + void RemoveAcceptLangsChangedCallback( + AcceptLanguagesHelper::AcceptLangsChangedCallback callback); std::vector> CreateThrottlesForNavigation( NavigationHandle* handle) override; std::vector> @@ -146,6 +143,7 @@ class ContentBrowserClientEfl : public ContentBrowserClient { const base::RepeatingCallback& wc_getter, content::NavigationUIData* navigation_ui_data, int frame_tree_node_id) override; + std::string GetAcceptLangs(BrowserContext* context) override; private: bool WillCreateURLLoaderFactory( @@ -162,33 +160,21 @@ class ContentBrowserClientEfl : public ContentBrowserClient { bool* bypass_redirect_checks, bool* disable_secure_dns, network::mojom::URLLoaderFactoryOverridePtr* factory_override) override; - scoped_refptr GetSystemSharedURLLoaderFactory() override; - static void SetCertificatePemOnUIThread(int render_process_id, int render_view_id, std::string certificate); - static void DispatchPopupBlockedOnUIThread(int render_process_id, - const GURL& target_url); - - void NotifyAcceptLangsChanged(); - void AppendExtraCommandLineSwitchesInternal(base::CommandLine* command_line, - int child_process_id); - - BrowserMainPartsEfl* browser_main_parts_efl_; - - std::unique_ptr notification_controller_; + BrowserMainPartsEfl* browser_main_parts_efl_ = nullptr; std::unique_ptr browser_context_; + std::unique_ptr notification_controller_; // URLLoaderFactory backed by the NetworkContext returned by GetContext(), so // consumers don't all need to create their own factory. scoped_refptr shared_url_loader_factory_; - std::string accept_langs_; - std::string preferred_langs_; - std::vector accept_langs_changed_callbacks_; + std::unique_ptr accept_langs_helper_; bool shutting_down_ = false; }; } // namespace content diff --git a/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc b/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc index ede9214..d44cd99 100644 --- a/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc +++ b/tizen_src/ewk/efl_integration/context_menu_controller_efl.cc @@ -10,17 +10,20 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" +#include "browser_context_efl.h" #include "common/web_contents_utils.h" #include "content/browser/selection/selection_controller_efl.h" #include "content/common/paths_efl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/render_process_host.h" #include "context_menu_controller_efl.h" #include "eweb_view.h" #include "net/base/filename_util.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "private/ewk_context_menu_private.h" +#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard_helper_efl.h" diff --git a/tizen_src/ewk/efl_integration/browser/download_manager_delegate_efl.cc b/tizen_src/ewk/efl_integration/download_manager_delegate_efl.cc similarity index 98% rename from tizen_src/ewk/efl_integration/browser/download_manager_delegate_efl.cc rename to tizen_src/ewk/efl_integration/download_manager_delegate_efl.cc index 0d81672..c7dfc6e 100644 --- a/tizen_src/ewk/efl_integration/browser/download_manager_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/download_manager_delegate_efl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "browser/download_manager_delegate_efl.h" +#include "download_manager_delegate_efl.h" #include "base/files/file_path.h" #include "base/path_service.h" diff --git a/tizen_src/ewk/efl_integration/browser/download_manager_delegate_efl.h b/tizen_src/ewk/efl_integration/download_manager_delegate_efl.h similarity index 100% rename from tizen_src/ewk/efl_integration/browser/download_manager_delegate_efl.h rename to tizen_src/ewk/efl_integration/download_manager_delegate_efl.h diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 449ac1b..ead962c 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/pickle.h" #include "base/strings/utf_string_conversions.h" +#include "browser/javascript_dialog_manager_efl.h" #include "browser/javascript_interface/gin_native_bridge_dispatcher_host.h" #include "browser/navigation_policy_handler_efl.h" #include "browser/quota_permission_context_efl.h" @@ -21,6 +22,7 @@ #include "browser/selectpicker/popup_menu_item_private.h" #include "browser/web_view_browser_message_filter.h" #include "browser/web_view_evas_handler.h" +#include "browser_context_efl.h" #include "common/content_client_efl.h" #include "common/render_messages_ewk.h" #include "common/version_info.h" diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index bb7357b..3fd06db 100755 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -659,7 +659,7 @@ class EWebView { std::map hit_test_callback_; - content::ContentBrowserClientEfl::AcceptLangsChangedCallback + content::AcceptLanguagesHelper::AcceptLangsChangedCallback accept_langs_changed_callback_; std::unique_ptr host_; diff --git a/tizen_src/ewk/efl_integration/browser/login_delegate_efl.cc b/tizen_src/ewk/efl_integration/login_delegate_efl.cc similarity index 100% rename from tizen_src/ewk/efl_integration/browser/login_delegate_efl.cc rename to tizen_src/ewk/efl_integration/login_delegate_efl.cc diff --git a/tizen_src/ewk/efl_integration/browser/login_delegate_efl.h b/tizen_src/ewk/efl_integration/login_delegate_efl.h similarity index 100% rename from tizen_src/ewk/efl_integration/browser/login_delegate_efl.h rename to tizen_src/ewk/efl_integration/login_delegate_efl.h diff --git a/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h b/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h index ded617d..c5765e5 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h +++ b/tizen_src/ewk/efl_integration/private/ewk_auth_challenge_private.h @@ -7,7 +7,7 @@ #include "url/gurl.h" #include "net/base/auth.h" -#include "browser/login_delegate_efl.h" +#include "login_delegate_efl.h" /** * @brief Structure used to send credential for authentication challenge. * diff --git a/tizen_src/ewk/efl_integration/private/ewk_context_form_autofill_profile_private.cc b/tizen_src/ewk/efl_integration/private/ewk_context_form_autofill_profile_private.cc index d68fe02..182d00a 100644 --- a/tizen_src/ewk/efl_integration/private/ewk_context_form_autofill_profile_private.cc +++ b/tizen_src/ewk/efl_integration/private/ewk_context_form_autofill_profile_private.cc @@ -14,6 +14,7 @@ #include "base/guid.h" #include "base/strings/stringprintf.h" #include "browser/autofill/personal_data_manager_factory.h" +#include "browser_context_efl.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "eweb_view.h" #include "ewk_autofill_profile_private.h" 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 67a2e18..c1d6e59 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc @@ -6,28 +6,27 @@ #include "base/strings/utf_string_conversions.h" #include "base/trace_event/ttrace.h" -#include "browser/favicon/favicon_database.h" #include "browser/input_picker/color_chooser_efl.h" #include "browser/javascript_dialog_manager_efl.h" #include "browser/policy_response_delegate_efl.h" +#include "browser_context_efl.h" #include "common/render_messages_ewk.h" -#include "components/favicon/core/favicon_url.h" -#include "components/favicon_base/favicon_types.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" #include "content/browser/manifest/manifest_manager_host.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/content_switches_internal.h" #include "content/common/render_messages_efl.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/favicon_status.h" +#include "content/public/browser/file_select_listener.h" #include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_view_host.h" #include "eweb_view.h" #include "eweb_view_callbacks.h" #include "net/base/load_states.h" #include "net/http/http_response_headers.h" -#include "printing/metafile_skia.h" #include "private/ewk_certificate_private.h" #include "private/ewk_console_message_private.h" #include "private/ewk_custom_handlers_private.h" @@ -38,6 +37,7 @@ #include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/common/manifest/manifest_util.h" #include "url/gurl.h" +#include "web_contents_observer_efl.h" #if BUILDFLAG(IS_TIZEN) #include @@ -68,23 +68,6 @@ using namespace ui; namespace content { -void WritePdfDataToFile(printing::MetafileSkia* metafile, - const base::FilePath& filename) { -#if !defined(EWK_BRINGUP) // FIXME: m67 bringup - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); -#endif - DCHECK(metafile); - base::File file(filename, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - metafile->SaveTo(&file); - file.Close(); - delete metafile; -} - -static bool IsMainFrame(RenderFrameHost* render_frame_host) { - return !render_frame_host->GetParent(); -} - #if BUILDFLAG(IS_TIZEN) && defined(TIZEN_MULTIMEDIA_SUPPORT) static const MediaStreamDevice* GetRequestedVideoDevice( const std::string& device_id) { @@ -99,15 +82,9 @@ static const MediaStreamDevice* GetRequestedVideoDevice( #endif WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* view) - : WebContentsObserver(&view->web_contents()), - web_view_(view), - is_fullscreen_(false), + : web_view_(view), web_contents_(view->web_contents()), - did_render_frame_(false), - did_first_visually_non_empty_paint_(false), - document_created_(false), - dialog_manager_(NULL), - weak_ptr_factory_(this) { + contents_observer_(std::make_unique(view, this)) { #if defined(TIZEN_AUTOFILL_SUPPORT) AutofillClientEfl::CreateForWebContents(&web_contents_); AutofillClientEfl* autofill_client = @@ -198,11 +175,6 @@ void WebContentsDelegateEfl::LoadingStateChanged(WebContents* source, web_view_->SmartCallback().call(); } -void WebContentsDelegateEfl::LoadProgressChanged(double progress) { - web_view_->SetProgressValue(progress); - web_view_->SmartCallback().call(&progress); -} - void WebContentsDelegateEfl::AddNewContents( WebContents* source, std::unique_ptr new_contents, @@ -362,107 +334,6 @@ void WebContentsDelegateEfl::OnAuthRequired(const std::string& realm, web_view_->InvokeAuthCallback(login_delegate, url, realm); } -void WebContentsDelegateEfl::DidStartNavigation( - NavigationHandle* navigation_handle) { - if (!navigation_handle->IsInMainFrame()) - return; - web_view_->SmartCallback().call(); -} - -void WebContentsDelegateEfl::DidRedirectNavigation( - NavigationHandle* navigation_handle) { - if (!navigation_handle->IsInMainFrame()) - return; - web_view_->SmartCallback().call(); -} - -void WebContentsDelegateEfl::DidFinishNavigation( - NavigationHandle* navigation_handle) { - if (!navigation_handle->HasCommitted()) - return; - - if (navigation_handle->IsInMainFrame()) { - web_view_->SmartCallback().call(); - - if (!navigation_handle->IsSameDocument() && - !navigation_handle->IsErrorPage()) - web_view_->SmartCallback().call(); - } else if (!navigation_handle->HasSubframeNavigationEntryCommitted()) { - return; - } - - if (navigation_handle->ShouldUpdateHistory()) - static_cast(web_contents_.GetBrowserContext()) - ->AddVisitedURLs(navigation_handle->GetRedirectChain()); -} - -void WebContentsDelegateEfl::DidFinishLoad(RenderFrameHost* render_frame_host, - const GURL& validated_url) { - if (!IsMainFrame(render_frame_host)) - return; - web_view_->SmartCallback().call(); - - web_contents_.Focus(); -} - -void WebContentsDelegateEfl::DidFailLoad(RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code) { - if (!IsMainFrame(render_frame_host)) - return; - - web_view_->InvokeLoadError(validated_url, error_code, - error_code == net::ERR_ABORTED); -} - -void WebContentsDelegateEfl::DidUpdateFaviconURL( - RenderFrameHost* render_frame_host, - const std::vector& candidates) { - // select and set proper favicon - for (const auto& favicon : candidates) { - if (!favicon->icon_url.is_valid()) - continue; - - if (favicon->icon_type == blink::mojom::FaviconIconType::kFavicon) { - NavigationEntry* entry = web_contents_.GetController().GetVisibleEntry(); - if (!entry) - return; - entry->GetFavicon().url = favicon->icon_url; - entry->GetFavicon().valid = true; - - // check/update the url and favicon url in favicon database - FaviconDatabase::Instance()->SetFaviconURLForPageURL(favicon->icon_url, - entry->GetURL()); - - // download favicon if there is no such in database - if (!FaviconDatabase::Instance()->ExistsForFaviconURL( - favicon->icon_url)) { - LOG(INFO) << "No favicon in database for URL: " - << favicon->icon_url.spec(); - favicon_downloader_.reset(new FaviconDownloader( - &web_contents_, favicon->icon_url, - base::BindOnce(&WebContentsDelegateEfl::DidDownloadFavicon, - weak_ptr_factory_.GetWeakPtr()))); - favicon_downloader_->Start(); - } else { - web_view_->SmartCallback().call(); - } - return; - } - } -} - -void WebContentsDelegateEfl::DidDownloadFavicon(bool success, - const GURL& icon_url, - const SkBitmap& bitmap) { - favicon_downloader_.reset(); - if (success) { - FaviconDatabase::Instance()->SetBitmapForFaviconURL(bitmap, icon_url); - // emit "icon,received" - web_view_->SmartCallback().call(); - } -} - void WebContentsDelegateEfl::RequestCertificateConfirm( WebContents* /*web_contents*/, int cert_error, @@ -536,16 +407,7 @@ void WebContentsDelegateEfl::ActivateContents(WebContents* contents) { void WebContentsDelegateEfl::SetContentSecurityPolicy( const std::string& policy, Ewk_CSP_Header_Type header_type) { - if (document_created_) { -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - RenderViewHost* rvh = web_contents_.GetRenderViewHost(); - rvh->Send(new EwkViewMsg_SetCSP(rvh->GetRoutingID(), policy, header_type)); -#endif - } else { - DCHECK(!pending_content_security_policy_.get()); - pending_content_security_policy_.reset( - new ContentSecurityPolicy(policy, header_type)); - } + contents_observer_->SetContentSecurityPolicy(policy, header_type); } void WebContentsDelegateEfl::FindReply(WebContents* web_contents, @@ -596,59 +458,6 @@ void WebContentsDelegateEfl::OnUpdateSettings(const Ewk_Settings* settings) { #endif } -bool WebContentsDelegateEfl::OnMessageReceived( - const IPC::Message& message, - RenderFrameHost* render_frame_host) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WebContentsDelegateEfl, message) - IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_GetContentSecurityPolicy, - OnGetContentSecurityPolicy) - IPC_MESSAGE_HANDLER(EwkHostMsg_DidPrintPagesToPdf, - OnPrintedMetafileReceived) - IPC_MESSAGE_HANDLER(EwkHostMsg_WrtMessage, OnWrtPluginMessage) - IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_WrtSyncMessage, - OnWrtPluginSyncMessage) - IPC_MESSAGE_HANDLER(EwkHostMsg_DidChangeContentsSize, - OnDidChangeContentsSize) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled; -} - -bool WebContentsDelegateEfl::Send(IPC::Message* message) { - if (!web_contents_.GetRenderViewHost()) { - delete message; - return false; - } -#if !defined(EWK_BRINGUP) // FIXME: m94 bringup - return web_contents_.GetRenderViewHost()->Send(message); -#else - return false; -#endif -} - -void WebContentsDelegateEfl::OnWrtPluginMessage( - const Ewk_Wrt_Message_Data& data) { - std::unique_ptr p(new Ewk_Wrt_Message_Data); - p->type = data.type; - p->value = data.value; - p->id = data.id; - p->reference_id = data.reference_id; - - web_view_->SmartCallback().call( - p.get()); -} - -void WebContentsDelegateEfl::OnWrtPluginSyncMessage( - const Ewk_Wrt_Message_Data& data, - IPC::Message* reply) { - Ewk_Wrt_Message_Data tmp = data; - web_view_->SmartCallback().call(&tmp); - EwkHostMsg_WrtSyncMessage::WriteReplyParams(reply, tmp.value); - Send(reply); -} - void WebContentsDelegateEfl::DidFirstVisuallyNonEmptyPaint() { did_first_visually_non_empty_paint_ = true; web_view_->SmartCallback() @@ -659,62 +468,6 @@ void WebContentsDelegateEfl::DidStartLoading() { did_render_frame_ = false; } -void WebContentsDelegateEfl::OnGetContentSecurityPolicy( - IPC::Message* reply_msg) { - document_created_ = true; - if (!pending_content_security_policy_.get()) { - EwkHostMsg_GetContentSecurityPolicy::WriteReplyParams( - reply_msg, std::string(), EWK_DEFAULT_POLICY); - } else { - EwkHostMsg_GetContentSecurityPolicy::WriteReplyParams( - reply_msg, pending_content_security_policy_->policy, - pending_content_security_policy_->header_type); - pending_content_security_policy_.reset(); - } - Send(reply_msg); -} - -void WebContentsDelegateEfl::OnPrintedMetafileReceived( - const DidPrintPagesParams& params) { -#if !defined(EWK_BRINGUP) // FIXME: m85 bringup - base::SharedMemory shared_buf(params.metafile_data_handle, true); - if (!shared_buf.Map(params.data_size)) { - NOTREACHED() << "couldn't map"; - return; - } - - std::unique_ptr metafile( - new printing::MetafileSkia()); - if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { - NOTREACHED() << "Invalid metafile header"; - return; - } - - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::BindOnce(&WritePdfDataToFile, metafile.release(), params.filename)); -#endif -} - -void WebContentsDelegateEfl::NavigationEntryCommitted( - const LoadCommittedDetails& load_details) { - web_view_->InvokeBackForwardListChangedCallback(); -} - -void WebContentsDelegateEfl::RenderViewCreated( - RenderViewHost* render_view_host) { - web_view_->RenderViewCreated(render_view_host); -} - -void WebContentsDelegateEfl::RenderProcessGone(base::TerminationStatus status) { - // See RenderWidgetHostViewEfl::RenderProcessGone. - if (status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || - status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED || - status == base::TERMINATION_STATUS_PROCESS_CRASHED) { - web_view_->HandleRendererProcessCrash(); - } -} - bool WebContentsDelegateEfl::DidAddMessageToConsole( WebContents* source, blink::mojom::ConsoleMessageLevel level, @@ -780,11 +533,6 @@ bool WebContentsDelegateEfl::PreHandleGestureEvent( return false; } -void WebContentsDelegateEfl::TitleWasSet(NavigationEntry* entry) { - if (entry) - web_view_->GetBackForwardList()->UpdateItemWithEntry(entry); -} - void WebContentsDelegateEfl::RequestManifestInfo( Ewk_View_Request_Manifest_Callback callback, void* user_data) { @@ -814,12 +562,4 @@ void WebContentsDelegateEfl::OnDidGetManifest( } } -void WebContentsDelegateEfl::OnPageScaleFactorChanged(float page_scale_factor) { - web_view_->DidChangePageScaleFactor(page_scale_factor); -} - -void WebContentsDelegateEfl::OnDidChangeContentsSize(int width, int height) { - web_view_->DidChangeContentsSize(width, height); -} - } // 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 ba107b6..add0161 100644 --- a/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h +++ b/tizen_src/ewk/efl_integration/web_contents_delegate_efl.h @@ -2,39 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEB_CONTENTS_DELEGATE_EFL -#define WEB_CONTENTS_DELEGATE_EFL - -#include - -#include "browser/favicon/favicon_downloader.h" -#include "browser/javascript_dialog_manager_efl.h" -#include "browser_context_efl.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" +#ifndef WEB_CONTENTS_DELEGATE_EFL_H_ +#define WEB_CONTENTS_DELEGATE_EFL_H_ + #include "content/public/browser/web_contents_delegate.h" -#include "content/public/browser/web_contents_observer.h" #include "eweb_view.h" #include "private/ewk_manifest_private.h" #include "public/ewk_view_internal.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom.h" #include "ui/base/ime/text_input_type.h" -#include "url/gurl.h" -class DidPrintPagesParams; -class Ewk_Wrt_Message_Data; class JavaScriptDialogManagerEfl; namespace content { -class WebContentsDelegateEfl : public WebContentsDelegate, - public WebContentsObserver, - public IPC::Sender { +class WebContentsObserverEfl; + +class WebContentsDelegateEfl : public WebContentsDelegate { public: WebContentsDelegateEfl(EWebView*); - ~WebContentsDelegateEfl() override; + ~WebContentsDelegateEfl(); WebContentsDelegateEfl(const WebContentsDelegateEfl&) = delete; WebContentsDelegateEfl& operator=(const WebContentsDelegateEfl&) = delete; @@ -71,22 +58,6 @@ class WebContentsDelegateEfl : public WebContentsDelegate, void ExitFullscreenModeForTab(WebContents* web_contents) override; bool IsFullscreenForTabOrPending(const WebContents* web_contents) override; -#if defined(TIZEN_MULTIMEDIA_SUPPORT) - virtual bool CheckMediaAccessPermission(WebContents* web_contents, - const GURL& security_origin, - MediaStreamType type) override; - - virtual void RequestMediaAccessPermission( - WebContents* web_contents, - const MediaStreamRequest& request, - MediaResponseCallback callback) override; - - void RequestMediaAccessAllow(const MediaStreamRequest& request, - MediaResponseCallback callback); - - void RequestMediaAccessDeny(const MediaStreamRequest& request, - MediaResponseCallback callback); -#endif void RegisterProtocolHandler(RenderFrameHost* host, const std::string& protocol, const GURL& url, @@ -101,9 +72,7 @@ class WebContentsDelegateEfl : public WebContentsDelegate, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) override; - void DidRenderFrame() override; - void RequestCertificateConfirm( WebContents* web_contents, int cert_error, @@ -115,23 +84,14 @@ class WebContentsDelegateEfl : public WebContentsDelegate, JavaScriptDialogManager* GetJavaScriptDialogManager( WebContents* source) override; - void ActivateContents(WebContents* contents) override; - void OnUpdateSettings(const Ewk_Settings* settings); void SetContentSecurityPolicy(const std::string& policy, Ewk_CSP_Header_Type header_type); - void DidFirstVisuallyNonEmptyPaint() override; - void DidStartLoading() override; + void DidFirstVisuallyNonEmptyPaint(); + void DidStartLoading(); - bool OnMessageReceived(const IPC::Message& message, - RenderFrameHost* render_frame_host) override; - void OnPrintedMetafileReceived(const DidPrintPagesParams& params); - void NavigationEntryCommitted( - const LoadCommittedDetails& load_details) override; - void RenderViewCreated(RenderViewHost* render_view_host); - void RenderProcessGone(base::TerminationStatus status); bool DidAddMessageToConsole(WebContents* source, blink::mojom::ConsoleMessageLevel level, const std::u16string& message, @@ -143,8 +103,7 @@ class WebContentsDelegateEfl : public WebContentsDelegate, std::unique_ptr OpenColorChooser( WebContents* web_contents, SkColor color, - const std::vector& suggestions) - override; + const std::vector& suggestions); #if !defined(EWK_BRINGUP) // FIXME: m76 bringup void OpenDateTimeDialog(ui::TextInputType dialog_type, double dialog_value, @@ -155,53 +114,31 @@ class WebContentsDelegateEfl : public WebContentsDelegate, #endif bool PreHandleGestureEvent(WebContents* source, const blink::WebGestureEvent& event) override; + EWebView* web_view() const { return web_view_; } + WebContents& web_contents() const { return web_contents_; } - // WebContentsObserver--------------------------------------------------- - void DidStartNavigation(NavigationHandle* navigation_handle) override; - - void DidRedirectNavigation(NavigationHandle* navigation_handle) override; - - void DidFinishNavigation(NavigationHandle* navigation_handle) override; - - void LoadProgressChanged(double progress) override; - void DidFinishLoad(RenderFrameHost* render_frame_host, - const GURL& validated_url) override; - void OnPageScaleFactorChanged(float page_scale_factor) override; - - void DidFailLoad(RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code) override; - - void DidUpdateFaviconURL( - RenderFrameHost* render_frame_host, - const std::vector& candidates) override; - - void TitleWasSet(content::NavigationEntry* entry) override; - + void RequestManifestInfo(Ewk_View_Request_Manifest_Callback callback, + void* user_data); void OnAuthRequired(const std::string& realm, const GURL& url, LoginDelegateEfl* login_delegate); - // IPC::Sender----------------------------------------------------------- - bool Send(IPC::Message* message) override; - - void DidDownloadFavicon(bool success, - const GURL& icon_url, - const SkBitmap& bitmap); - - EWebView* web_view() const { return web_view_; } - WebContents& web_contents() const { return web_contents_; } +#if defined(TIZEN_MULTIMEDIA_SUPPORT) + virtual bool CheckMediaAccessPermission(WebContents* web_contents, + const GURL& security_origin, + MediaStreamType type) override; - void RequestManifestInfo(Ewk_View_Request_Manifest_Callback callback, - void* user_data); + virtual void RequestMediaAccessPermission( + WebContents* web_contents, + const MediaStreamRequest& request, + MediaResponseCallback callback) override; + void RequestMediaAccessAllow(const MediaStreamRequest& request, + MediaResponseCallback callback); + void RequestMediaAccessDeny(const MediaStreamRequest& request, + MediaResponseCallback callback); +#endif private: - void OnGetContentSecurityPolicy(IPC::Message* reply_msg); - void OnWrtPluginMessage(const Ewk_Wrt_Message_Data& data); - void OnWrtPluginSyncMessage(const Ewk_Wrt_Message_Data& data, - IPC::Message* reply); - void OnDidChangeContentsSize(int width, int height); - void OnDidGetManifest(Ewk_View_Request_Manifest_Callback callback, void* user_data, const GURL& manifest_url, @@ -211,26 +148,18 @@ class WebContentsDelegateEfl : public WebContentsDelegate, bool is_fullscreen_; WebContents& web_contents_; - bool did_render_frame_; - bool did_first_visually_non_empty_paint_; - - struct ContentSecurityPolicy { - ContentSecurityPolicy(const std::string& p, Ewk_CSP_Header_Type type) - : policy(p), header_type(type) {} - std::string policy; - Ewk_CSP_Header_Type header_type; - }; + bool did_render_frame_ = false; + bool did_first_visually_non_empty_paint_ = false; + std::unique_ptr contents_observer_; + void* ime_window_ = nullptr; GURL last_visible_url_; - std::unique_ptr pending_content_security_policy_; - bool document_created_; JavaScriptDialogManagerEfl* dialog_manager_ = nullptr; - std::unique_ptr favicon_downloader_; - base::WeakPtrFactory weak_ptr_factory_; + int rotation_ = -1; std::unique_ptr<_Ewk_Certificate_Policy_Decision> certificate_policy_decision_; }; } -#endif +#endif // WEB_CONTENTS_DELEGATE_EFL_H_ diff --git a/tizen_src/ewk/efl_integration/web_contents_observer_efl.cc b/tizen_src/ewk/efl_integration/web_contents_observer_efl.cc new file mode 100644 index 0000000..537b761 --- /dev/null +++ b/tizen_src/ewk/efl_integration/web_contents_observer_efl.cc @@ -0,0 +1,318 @@ +// 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 "web_contents_observer_efl.h" + +#include "base/task/bind_post_task.h" +#include "browser/favicon/favicon_database.h" +#include "browser/favicon/favicon_downloader.h" +#include "browser_context_efl.h" +#include "common/print_pages_params.h" +#include "common/render_messages_ewk.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/favicon_status.h" +#include "content/public/browser/file_select_listener.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "eweb_view_callbacks.h" +#include "ipc/ipc_message_macros.h" +#include "printing/metafile_skia.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" +#include "url/gurl.h" + +#if defined(OS_TIZEN_TV_PRODUCT) +#if !defined(EWK_BRINGUP) +#include "devtools_port_manager.h" +#endif +#include "private/ewk_context_private.h" +#endif + +#if defined(TIZEN_AUTOFILL_SUPPORT) +#include "browser/autofill/autofill_client_efl.h" +using autofill::AutofillClientEfl; +#endif + +namespace content { + +static bool IsMainFrame(RenderFrameHost* render_frame_host) { + return !render_frame_host->GetParent(); +} + +WebContentsObserverEfl::WebContentsObserverEfl(EWebView* view, + WebContentsDelegateEfl* delegate) + : WebContentsObserver(&view->web_contents()), + web_view_(view), + web_contents_(view->web_contents()), + web_contents_delegate_(delegate), + weak_ptr_factory_(this) {} + +WebContentsObserverEfl::~WebContentsObserverEfl() = default; + +void WebContentsObserverEfl::SetContentSecurityPolicy( + const std::string& policy, + Ewk_CSP_Header_Type header_type) { + if (document_created_) { +#if !defined(EWK_BRINGUP) // FIXME: m94 bringup + RenderViewHost* rvh = web_contents_.GetRenderViewHost(); + rvh->Send(new EwkViewMsg_SetCSP(rvh->GetRoutingID(), policy, header_type)); +#endif + } else { + DCHECK(!pending_content_security_policy_.get()); + pending_content_security_policy_.reset( + new ContentSecurityPolicy(policy, header_type)); + } +} + +void WebContentsObserverEfl::DidStartNavigation( + NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame()) + return; + web_view_->SmartCallback().call(); +} + +void WebContentsObserverEfl::DidRedirectNavigation( + NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame()) + return; + web_view_->SmartCallback().call(); +} + +void WebContentsObserverEfl::DidFinishNavigation( + NavigationHandle* navigation_handle) { + if (!navigation_handle->HasCommitted()) + return; + + if (navigation_handle->IsInMainFrame()) { + web_view_->SmartCallback().call(); + + if (!navigation_handle->IsSameDocument() && + !navigation_handle->IsErrorPage()) + web_view_->SmartCallback().call(); + } else if (!navigation_handle->HasSubframeNavigationEntryCommitted()) { + return; + } + + if (navigation_handle->ShouldUpdateHistory()) + static_cast(web_contents_.GetBrowserContext()) + ->AddVisitedURLs(navigation_handle->GetRedirectChain()); +} + +void WebContentsObserverEfl::LoadProgressChanged(double progress) { + web_view_->SetProgressValue(progress); + web_view_->SmartCallback().call(&progress); +} + +void WebContentsObserverEfl::DidFinishLoad(RenderFrameHost* render_frame_host, + const GURL& validated_url) { + if (!IsMainFrame(render_frame_host)) + return; + web_view_->SmartCallback().call(); + + web_contents_.Focus(); +} + +void WebContentsObserverEfl::DidFailLoad(RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code) { + if (!IsMainFrame(render_frame_host)) + return; + + web_view_->InvokeLoadError(validated_url, error_code, + error_code == net::ERR_ABORTED); +} + +void WebContentsObserverEfl::TitleWasSet(NavigationEntry* entry) { + if (entry) + web_view_->GetBackForwardList()->UpdateItemWithEntry(entry); +} + +void WebContentsObserverEfl::OnPageScaleFactorChanged(float page_scale_factor) { + web_view_->DidChangePageScaleFactor(page_scale_factor); +} + +void WebContentsObserverEfl::DidFirstVisuallyNonEmptyPaint() { + web_contents_delegate_->DidFirstVisuallyNonEmptyPaint(); +} + +void WebContentsObserverEfl::DidStartLoading() { + web_contents_delegate_->DidStartLoading(); +} + +void WebContentsObserverEfl::NavigationEntryCommitted( + const LoadCommittedDetails& load_details) { + web_view_->InvokeBackForwardListChangedCallback(); +} + +void WebContentsObserverEfl::PrimaryMainFrameRenderProcessGone( + base::TerminationStatus status) { + if (status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || + status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED || + status == base::TERMINATION_STATUS_PROCESS_CRASHED) { + web_view_->HandleRendererProcessCrash(); + } +} + +void WebContentsObserverEfl::RenderViewCreated( + RenderViewHost* render_view_host) { + web_view_->RenderViewCreated(render_view_host); +} + +void WebContentsObserverEfl::DidUpdateFaviconURL( + RenderFrameHost* render_frame_host, + const std::vector& candidates) { + // select and set proper favicon + for (const auto& favicon : candidates) { + if (!favicon->icon_url.is_valid()) + continue; + + if (favicon->icon_type == blink::mojom::FaviconIconType::kFavicon) { + NavigationEntry* entry = web_contents_.GetController().GetVisibleEntry(); + if (!entry) + return; + entry->GetFavicon().url = favicon->icon_url; + entry->GetFavicon().valid = true; + + // check/update the url and favicon url in favicon database + FaviconDatabase::Instance()->SetFaviconURLForPageURL(favicon->icon_url, + entry->GetURL()); + + // download favicon if there is no such in database + if (!FaviconDatabase::Instance()->ExistsForFaviconURL( + favicon->icon_url)) { + LOG(INFO) << "No favicon in database for URL: " + << favicon->icon_url.spec(); + favicon_downloader_.reset(new FaviconDownloader( + &web_contents_, favicon->icon_url, + base::BindOnce(&WebContentsObserverEfl::DidDownloadFavicon, + weak_ptr_factory_.GetWeakPtr()))); + favicon_downloader_->Start(); + } else { + web_view_->SmartCallback().call(); + } + return; + } + } +} + +bool WebContentsObserverEfl::OnMessageReceived( + const IPC::Message& message, + RenderFrameHost* render_frame_host) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WebContentsObserverEfl, message) + IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_GetContentSecurityPolicy, + OnGetContentSecurityPolicy) + IPC_MESSAGE_HANDLER(EwkHostMsg_DidPrintPagesToPdf, + OnPrintedMetafileReceived) + IPC_MESSAGE_HANDLER(EwkHostMsg_WrtMessage, OnWrtPluginMessage) + IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_WrtSyncMessage, + OnWrtPluginSyncMessage) + IPC_MESSAGE_HANDLER(EwkHostMsg_DidChangeContentsSize, + OnDidChangeContentsSize) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; +} + +bool WebContentsObserverEfl::Send(IPC::Message* message) { + if (!web_contents_.GetRenderViewHost()) { + delete message; + return false; + } +#if !defined(EWK_BRINGUP) // FIXME: m94 bringup + return web_contents_.GetRenderViewHost()->Send(message); +#else + return false; +#endif +} + +void WebContentsObserverEfl::OnGetContentSecurityPolicy( + IPC::Message* reply_msg) { + document_created_ = true; + if (!pending_content_security_policy_.get()) { + EwkHostMsg_GetContentSecurityPolicy::WriteReplyParams( + reply_msg, std::string(), EWK_DEFAULT_POLICY); + } else { + EwkHostMsg_GetContentSecurityPolicy::WriteReplyParams( + reply_msg, pending_content_security_policy_->policy, + pending_content_security_policy_->header_type); + pending_content_security_policy_.reset(); + } + Send(reply_msg); +} + +void WebContentsObserverEfl::OnPrintedMetafileReceived( + const DidPrintPagesParams& params) { +#if !defined(EWK_BRINGUP) // FIXME: m85 bringup + base::SharedMemory shared_buf(params.metafile_data_handle, true); + if (!shared_buf.Map(params.data_size)) { + NOTREACHED() << "couldn't map"; + return; + } + + std::unique_ptr metafile( + new printing::MetafileSkia()); + if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { + NOTREACHED() << "Invalid metafile header"; + return; + } + + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::BindOnce(&WritePdfDataToFile, metafile.release(), params.filename)); +#endif +} + +void WebContentsObserverEfl::OnWrtPluginMessage( + const Ewk_Wrt_Message_Data& data) { + std::unique_ptr p(new Ewk_Wrt_Message_Data); + p->type = data.type; + p->value = data.value; + p->id = data.id; + p->reference_id = data.reference_id; + + web_view_->SmartCallback().call( + p.get()); +} + +void WebContentsObserverEfl::OnWrtPluginSyncMessage( + const Ewk_Wrt_Message_Data& data, + IPC::Message* reply) { + Ewk_Wrt_Message_Data tmp = data; + web_view_->SmartCallback().call(&tmp); + EwkHostMsg_WrtSyncMessage::WriteReplyParams(reply, tmp.value); + Send(reply); +} + +void WebContentsObserverEfl::OnDidChangeContentsSize(int width, int height) { + web_view_->DidChangeContentsSize(width, height); +} + +void WebContentsObserverEfl::OnDidChangeFocusedNodeBounds( + const gfx::RectF& focused_node_bounds) { +#if defined(TIZEN_AUTOFILL_SUPPORT) + if (AutofillClientEfl* autofill_client = + AutofillClientEfl::FromWebContents(&web_contents_)) { + autofill_client->DidChangeFocusedNodeBounds(focused_node_bounds); + } +#endif +} + +void WebContentsObserverEfl::DidDownloadFavicon(bool success, + const GURL& icon_url, + const SkBitmap& bitmap) { + favicon_downloader_.reset(); + if (success) { + FaviconDatabase::Instance()->SetBitmapForFaviconURL(bitmap, icon_url); + // emit "icon,received" + web_view_->SmartCallback().call(); + } +} + +} // namespace content diff --git a/tizen_src/ewk/efl_integration/web_contents_observer_efl.h b/tizen_src/ewk/efl_integration/web_contents_observer_efl.h new file mode 100644 index 0000000..b870fa6 --- /dev/null +++ b/tizen_src/ewk/efl_integration/web_contents_observer_efl.h @@ -0,0 +1,99 @@ +// 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. + +#ifndef WEB_CONTENTS_OBSERVER_EFL_H_ +#define WEB_CONTENTS_OBSERVER_EFL_H_ + +#include + +#include "base/memory/weak_ptr.h" +#include "content/public/browser/web_contents_observer.h" +#include "eweb_view.h" + +class DidPrintPagesParams; +class Ewk_Wrt_Message_Data; +class FaviconDownloader; +class GURL; +class SkBitmap; + +namespace gfx { +class Rect; +} + +namespace content { + +class WebContentsDelegateEfl; + +class WebContentsObserverEfl : public WebContentsObserver, public IPC::Sender { + public: + explicit WebContentsObserverEfl(EWebView* view, + WebContentsDelegateEfl* delegate); + WebContentsObserverEfl(const WebContentsObserverEfl&) = delete; + WebContentsObserverEfl& operator=(const WebContentsObserverEfl&) = delete; + ~WebContentsObserverEfl() override; + + void SetContentSecurityPolicy(const std::string& policy, + Ewk_CSP_Header_Type header_type); + + // IPC::Sender----------------------------------------------------------- + bool Send(IPC::Message* message) override; + + private: + // WebContentsObserver overrides: + void DidStartNavigation(NavigationHandle* navigation_handle) override; + void DidRedirectNavigation(NavigationHandle* navigation_handle) override; + void DidFinishNavigation(NavigationHandle* navigation_handle) override; + void LoadProgressChanged(double progress) override; + void DidFinishLoad(RenderFrameHost* render_frame_host, + const GURL& validated_url) override; + void DidFailLoad(RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code) override; + void TitleWasSet(NavigationEntry* entry) override; + void OnPageScaleFactorChanged(float page_scale_factor) override; + void DidFirstVisuallyNonEmptyPaint() override; + void DidStartLoading() override; + void NavigationEntryCommitted( + const LoadCommittedDetails& load_details) override; + void PrimaryMainFrameRenderProcessGone( + base::TerminationStatus status) override; + void RenderViewCreated(RenderViewHost* render_view_host); + void DidUpdateFaviconURL( + RenderFrameHost* render_frame_host, + const std::vector& candidates) override; + bool OnMessageReceived(const IPC::Message& message, + RenderFrameHost* render_frame_host) override; + + // IPC message handlers: + void OnGetContentSecurityPolicy(IPC::Message* reply_msg); + void OnPrintedMetafileReceived(const DidPrintPagesParams& params); + void OnWrtPluginMessage(const Ewk_Wrt_Message_Data& data); + void OnWrtPluginSyncMessage(const Ewk_Wrt_Message_Data& data, + IPC::Message* reply); + void OnDidChangeContentsSize(int width, int height); + void OnDidChangeFocusedNodeBounds(const gfx::RectF& focused_node_bounds); + + void DidDownloadFavicon(bool success, + const GURL& icon_url, + const SkBitmap& bitmap); + + struct ContentSecurityPolicy { + ContentSecurityPolicy(const std::string& p, Ewk_CSP_Header_Type type) + : policy(p), header_type(type) {} + std::string policy; + Ewk_CSP_Header_Type header_type; + }; + + bool document_created_ = false; + EWebView* web_view_; + WebContents& web_contents_; + std::unique_ptr pending_content_security_policy_; + std::unique_ptr favicon_downloader_; + WebContentsDelegateEfl* web_contents_delegate_ = nullptr; + base::WeakPtrFactory weak_ptr_factory_; +}; + +} // namespace content + +#endif // WEB_CONTENTS_OBSERVER_EFL_H_ -- 2.7.4 From 36283f083ca4b9a8a6f4391e3bc67cca1c8ffdc5 Mon Sep 17 00:00:00 2001 From: "ayush.k123" Date: Fri, 27 Jan 2023 10:46:44 +0530 Subject: [PATCH 15/16] [M108 Migration][NativeControl] Refactor Permission Popup. This patch includes below changes: - Refactor Permission_popup. - Fix SetPopupTitle() hardcoding. - Permission popup is closed, When request is cancelled. - NULL checking while DeletePermissionRequest. Reference: https://review.tizen.org/gerrit/c/277643/ Change-Id: I87080ac0061bb9bdf42c8db6a09db6a51b2a6596 Signed-off-by: Ayush Kumar --- tizen_src/ewk/efl_integration/eweb_view.cc | 3 +- tizen_src/ewk/efl_integration/permission_popup.h | 9 +- .../efl_integration/permission_popup_manager.cc | 306 ++++++++------------- .../ewk/efl_integration/permission_popup_manager.h | 59 ++-- 4 files changed, 160 insertions(+), 217 deletions(-) mode change 100755 => 100644 tizen_src/ewk/efl_integration/permission_popup_manager.cc diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index ead962c..e28f0fe 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -1,4 +1,4 @@ -// Copyright 2014 Samsung Electronics. All rights reserved. +// Copyright 2014-2020 Samsung Electronics. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -289,7 +289,6 @@ EWebView::~EWebView() { old_context_ = nullptr; } - GetPermissionPopupManager()->DeleteAllPermissionRequest(); permission_popup_manager_.reset(); if (context_->GetImpl()->browser_context()->IsOffTheRecord()) diff --git a/tizen_src/ewk/efl_integration/permission_popup.h b/tizen_src/ewk/efl_integration/permission_popup.h index 32f07a0..a1b000b 100644 --- a/tizen_src/ewk/efl_integration/permission_popup.h +++ b/tizen_src/ewk/efl_integration/permission_popup.h @@ -1,4 +1,4 @@ -// Copyright 2015 Samsung Electronics. All rights reserved. +// Copyright 2015-2020 Samsung Electronics. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -19,12 +19,13 @@ class PermissionPopup { popup_message_ = message; } + PermissionPopup(const PermissionPopup&) = delete; + PermissionPopup& operator=(const PermissionPopup&) = delete; + virtual ~PermissionPopup() { } std::string GetMessage() const { return popup_message_; } - std::string GetOriginHost() const { - return std::string(ewk_security_origin_host_get(origin_)); - } + std::string GetOrigin() const { return origin_->GetURL().spec(); } virtual void SendDecidedPermission(Evas_Object*, bool decide) = 0; private: diff --git a/tizen_src/ewk/efl_integration/permission_popup_manager.cc b/tizen_src/ewk/efl_integration/permission_popup_manager.cc old mode 100755 new mode 100644 index 190f40b..2535b57 --- a/tizen_src/ewk/efl_integration/permission_popup_manager.cc +++ b/tizen_src/ewk/efl_integration/permission_popup_manager.cc @@ -1,254 +1,188 @@ -// Copyright 2015 Samsung Electronics. All rights reserved. +// Copyright 2015-2020 Samsung Electronics. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "permission_popup_manager.h" + #if BUILDFLAG(IS_TIZEN) #include #endif -#include -#include #include "base/strings/utf_string_conversions.h" -#include "eweb_view.h" #include "permission_popup.h" -#include "permission_popup_manager.h" -PermissionPopupManager::PermissionPopupManager(Evas_Object* eweb_view) - : is_decided_(false) - , permission_popups_(0) - , eweb_view_(eweb_view) - , popup_(0) - , widget_win_(0) - , top_widget_(0) { -} +PermissionPopupManager::PermissionPopupManager(Evas_Object* evas_object) + : evas_object_(evas_object) {} PermissionPopupManager::~PermissionPopupManager() { - ClosePopup(); - DeleteAllPermissionRequest(); + CancelPermissionRequest(); } -void PermissionPopupManager::AddPermissionRequest(PermissionPopup* popup) { - permission_popups_ = eina_list_append(permission_popups_, popup); +void PermissionPopupManager::AddPermissionRequest( + PermissionPopup* permission_popup) { + permission_popups_ = eina_list_append(permission_popups_, permission_popup); ShowPermissionPopup(static_cast( eina_list_data_get(permission_popups_))); } -void PermissionPopupManager::DeletePermissionRequest(PermissionPopup* popup) { - permission_popups_ = eina_list_remove(permission_popups_, popup); - delete popup; +void PermissionPopupManager::CancelPermissionRequest() { + DeletePopup(); + DeleteAllPermissionRequests(); +} - if (eina_list_count(permission_popups_) == 0) +void PermissionPopupManager::DeleteAllPermissionRequests() { + if (!permission_popups_) return; - ShowPermissionPopup(static_cast( - eina_list_data_get(permission_popups_))); + void* data; + EINA_LIST_FREE(permission_popups_, data) { + auto permission_popup = static_cast(data); + permission_popup->SendDecidedPermission(evas_object_, false); + delete permission_popup; + } } -void PermissionPopupManager::DeleteAllPermissionRequest() { - void* data; - EINA_LIST_FREE(permission_popups_, data) - delete static_cast(data); +void PermissionPopupManager::DeletePermissionRequest( + PermissionPopup* permission_popup) { + permission_popups_ = eina_list_remove(permission_popups_, permission_popup); + delete permission_popup; } -Evas_Object* PermissionPopupManager::CreatePopup() { - top_widget_ = elm_object_top_widget_get(elm_object_parent_widget_get(eweb_view_)); - if (!top_widget_) - return 0; +void PermissionPopupManager::ShowPermissionPopup( + PermissionPopup* permission_popup) { + if (popup_ || !CreatePopup()) + return; + if (!SetupPopup(permission_popup)) { + DeletePopup(); + return; + } - widget_win_ = elm_win_add(top_widget_, "WebKit Permission Popup", ELM_WIN_BASIC); - if (!widget_win_) - return 0; + evas_object_show(popup_); +} - elm_win_alpha_set(widget_win_, EINA_TRUE); -#if !defined(WAYLAND_BRINGUP) - ecore_x_icccm_name_class_set(elm_win_xwindow_get(widget_win_), - "APP_POPUP", "APP_POPUP"); -#endif +void PermissionPopupManager::Decide(bool decision) { + DeletePopup(); - if (elm_win_wm_rotation_supported_get(top_widget_)) { - int preferredRotation = - elm_win_wm_rotation_preferred_rotation_get(top_widget_); - if (preferredRotation == -1) { - int rots[4] = {0, 90, 180, 270}; - elm_win_wm_rotation_available_rotations_set(widget_win_, rots, 4); - } - else { - elm_win_wm_rotation_available_rotations_set(widget_win_, - &preferredRotation, 1); - } - } + auto permission_popup = + static_cast(eina_list_data_get(permission_popups_)); + permission_popup->SendDecidedPermission(evas_object_, decision); + DeletePermissionRequest(permission_popup); + permission_popup = + static_cast(eina_list_data_get(permission_popups_)); + if (permission_popup) + ShowPermissionPopup(permission_popup); +} - Eina_Rectangle windowRect; - Ecore_Evas* ee = ecore_evas_ecore_evas_get( - evas_object_evas_get(eweb_view_)); - ecore_evas_geometry_get(ee, &windowRect.x, &windowRect.y, - &windowRect.w, &windowRect.h); - evas_object_resize(widget_win_, windowRect.w, windowRect.h); +void PermissionPopupManager::PermissionOkCallback(void* data, + Evas_Object* obj, + void* event_info) { + PermissionPopupManager* manager = static_cast(data); + manager->Decide(true); +} + +void PermissionPopupManager::PermissionCancelCallback(void* data, + Evas_Object* obj, + void* event_info) { + PermissionPopupManager* manager = static_cast(data); + manager->Decide(false); +} - Evas_Object* conformant = elm_conformant_add(widget_win_); +bool PermissionPopupManager::CreatePopup() { + top_widget_ = + elm_object_top_widget_get(elm_object_parent_widget_get(evas_object_)); + if (!top_widget_) + return false; + + Evas_Object* conformant = elm_conformant_add(top_widget_); if (!conformant) - return 0; + return false; - evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_win_resize_object_add(widget_win_, conformant); + evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(top_widget_, conformant); evas_object_show(conformant); Evas_Object* layout = elm_layout_add(conformant); if (!layout) - return 0; + return false; elm_layout_theme_set(layout, "layout", "application", "default"); evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_show(layout); elm_object_content_set(conformant, layout); - elm_win_conformant_set(widget_win_, EINA_TRUE); - - evas_object_show(widget_win_); - - Evas_Object* popup = elm_popup_add(layout); - elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0); - - return popup; -} - -static void permissionPopupFocusInCallback( - void* data, Evas_Object* obj, void* event_info) { - evas_object_smart_callback_del(obj, "focus,in", permissionPopupFocusInCallback); - - PermissionPopupManager* manager = static_cast(data); - if (!manager) - return; - manager->ClosePopup(); - - PermissionPopup* popup = manager->GetPermissionPopup(); - if (!popup) - return; - popup->SendDecidedPermission(manager->GetEwebView(), manager->IsDecided()); - manager->DeletePermissionRequest(popup); + popup_ = elm_popup_add(layout); + return !!popup_; } -static void permissionOkCallback(void* data, Evas_Object* obj, void* event_info) { - PermissionPopupManager* manager = static_cast(data); - if (!manager) +void PermissionPopupManager::DeletePopup() { + if (!popup_) return; - - evas_object_smart_callback_add(manager->GetTopWidget(), - "focus,in", permissionPopupFocusInCallback, data); - manager->HidePopup(); - manager->Decide(true); + evas_object_del(popup_); + popup_ = nullptr; } -static void permissionCancelCallback( - void* data, Evas_Object* obj, void* event_info) { - PermissionPopupManager* manager = static_cast(data); - if (!manager) - return; +bool PermissionPopupManager::SetupPopup(PermissionPopup* permission_popup) { + elm_popup_align_set(popup_, ELM_NOTIFY_ALIGN_FILL, 1.0); - evas_object_smart_callback_add(manager->GetTopWidget(), "focus,in", - permissionPopupFocusInCallback, data); - manager->HidePopup(); - manager->Decide(false); -} + if (!SetPopupText(permission_popup->GetMessage()) || + !SetPopupTitle(permission_popup->GetOrigin())) { + return false; + } #if BUILDFLAG(IS_TIZEN) -static void permissionHwBackKeyCallback( - void* data, Evas_Object* obj, void* event_info) { - PermissionPopupManager* manager = static_cast(data); - if (!manager) - return; - - evas_object_smart_callback_add(manager->GetTopWidget(), - "focus,in", permissionPopupFocusInCallback, data); - manager->HidePopup(); -} + eext_object_event_callback_add( + popup_, EEXT_CALLBACK_BACK, + &PermissionPopupManager::PermissionCancelCallback, this); #endif -void PermissionPopupManager::ShowPermissionPopup(PermissionPopup* popup) { - if (popup_) - return; - - popup_ = CreatePopup(); - - if (!popup_) - return; - - if (!SetLabelText(popup->GetMessage())) - return; + AddButtonToPopup("button1", "IDS_WEBVIEW_BUTTON_CANCEL_ABB4", + &PermissionPopupManager::PermissionCancelCallback, false); + AddButtonToPopup("button2", "IDS_WEBVIEW_BUTTON_OK_ABB4", + &PermissionPopupManager::PermissionOkCallback, true); -#if BUILDFLAG(IS_TIZEN) - eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, - permissionHwBackKeyCallback, this); -#endif - - Evas_Object* cancelButton = elm_button_add(popup_); - elm_object_style_set(cancelButton, "popup"); - elm_object_domain_translatable_part_text_set( - cancelButton, NULL, "WebKit", "Cancel"); - elm_object_part_content_set(popup_, "button1", cancelButton); - evas_object_smart_callback_add(cancelButton, "clicked", - permissionCancelCallback, this); - - Evas_Object* okButton = elm_button_add(popup_); - elm_object_style_set(okButton, "popup"); - elm_object_domain_translatable_part_text_set(okButton, NULL, "WebKit", "OK"); - elm_object_part_content_set(popup_, "button2", okButton); - evas_object_focus_set(okButton, true); - evas_object_smart_callback_add(okButton, "clicked", permissionOkCallback, this); - - elm_object_part_text_set(popup_, "title,text", GetTitle(popup).c_str()); - evas_object_show(popup_); + return true; } -std::string PermissionPopupManager::GetTitle(PermissionPopup* popup) { - std::string url = std::string(ewk_view_url_get(eweb_view_)); - - if (url.empty()) - url = std::string(ewk_view_title_get(eweb_view_)); +bool PermissionPopupManager::SetPopupTitle(const std::string& origin) { + // Empty origin is improper one. + if (origin.empty()) + return false; + std::string title = + dgettext("WebKit", "IDS_WEBVIEW_HEADER_MESSAGE_FROM_PS_M_WEBSITE"); - std::string popupTitle = std::string(dgettext( - "WebKit","IDS_WEBVIEW_HEADER_MESSAGE_FROM_PS_M_WEBSITE")); - std::string replaceStr = std::string("%s"); - size_t pos = popupTitle.find(replaceStr.c_str()); + const std::string replaceStr("%s"); + size_t pos = title.find(replaceStr); if (pos != std::string::npos) - popupTitle.replace(pos, replaceStr.length(), url.c_str()); - - return popupTitle; + title.replace(pos, replaceStr.length(), origin); + else + LOG(ERROR) << "Translation issue. " << title << " not found"; + elm_object_part_text_set(popup_, "title,text", title.c_str()); + return true; } -bool PermissionPopupManager::SetLabelText(const std::string& message) { +bool PermissionPopupManager::SetPopupText(const std::string& message) { if (message.empty()) return false; - - std::string labal_text = message; + std::string text = message; std::string replaceStr = std::string("\n"); - size_t pos = labal_text.find(replaceStr.c_str()); + size_t pos = text.find(replaceStr.c_str()); if (pos != std::string::npos) - labal_text.replace(pos, replaceStr.length(), "
"); - - elm_object_text_set(popup_, labal_text.c_str()); - + text.replace(pos, replaceStr.length(), "
"); + elm_object_text_set(popup_, text.c_str()); return true; } -void PermissionPopupManager::ClosePopup() { - if (!widget_win_) - return; - - evas_object_del(widget_win_); - popup_ = 0; - widget_win_ = 0; -} - -void PermissionPopupManager::HidePopup() { - if (popup_) - evas_object_hide(popup_); - - if (widget_win_) - evas_object_hide(widget_win_); -} - -PermissionPopup* PermissionPopupManager::GetPermissionPopup() { - return static_cast(eina_list_data_get(permission_popups_)); +void PermissionPopupManager::AddButtonToPopup(const char* name, + const char* text, + Evas_Smart_Cb callback, + bool focus) { + Evas_Object* button = elm_button_add(popup_); + elm_object_style_set(button, "popup"); + elm_object_domain_translatable_part_text_set(button, NULL, "WebKit", text); + elm_object_part_content_set(popup_, name, button); + evas_object_smart_callback_add(button, "clicked", callback, this); + if (focus) + evas_object_focus_set(button, true); } diff --git a/tizen_src/ewk/efl_integration/permission_popup_manager.h b/tizen_src/ewk/efl_integration/permission_popup_manager.h index 09fc2f5..83f9398 100644 --- a/tizen_src/ewk/efl_integration/permission_popup_manager.h +++ b/tizen_src/ewk/efl_integration/permission_popup_manager.h @@ -1,4 +1,4 @@ -// Copyright 2015 Samsung Electronics. All rights reserved. +// Copyright 2015-2020 Samsung Electronics. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,38 +6,47 @@ #define PermissionPopupManager_h #include -#include +#include -#include "permission_popup.h" +class PermissionPopup; class PermissionPopupManager { public: - PermissionPopupManager(Evas_Object* ); + PermissionPopupManager(Evas_Object* evas_object); ~PermissionPopupManager(); - bool IsDecided() const { return is_decided_; } - Evas_Object* GetEwebView() const { return eweb_view_; } - Evas_Object* GetTopWidget() const { return top_widget_; } - PermissionPopup* GetPermissionPopup(); - void AddPermissionRequest(PermissionPopup*); - void ClosePopup(); - void DeletePermissionRequest(PermissionPopup*); - void DeleteAllPermissionRequest(); - void HidePopup(); - void Decide(bool decided) { is_decided_ = decided; } + PermissionPopupManager(const PermissionPopupManager&) = delete; + PermissionPopupManager& operator=(const PermissionPopupManager&) = delete; + + void AddPermissionRequest(PermissionPopup* permission_popup); + void CancelPermissionRequest(); private: - bool SetLabelText(const std::string& message); - Evas_Object* CreatePopup(); - std::string GetTitle(PermissionPopup* popup); - void ShowPermissionPopup(PermissionPopup*); - - bool is_decided_; - Eina_List* permission_popups_; - Evas_Object* eweb_view_; - Evas_Object* popup_; - Evas_Object* widget_win_; - Evas_Object* top_widget_; + bool CreatePopup(); + bool SetupPopup(PermissionPopup* permission_popup); + void DeletePopup(); + bool SetPopupText(const std::string& message); + bool SetPopupTitle(const std::string& host); + void AddButtonToPopup(const char* name, + const char* text, + Evas_Smart_Cb callback, + bool focus); + void DeleteAllPermissionRequests(); + void DeletePermissionRequest(PermissionPopup* permission_popup); + void ShowPermissionPopup(PermissionPopup* permission_popup); + void Decide(bool decision); + + static void PermissionOkCallback(void* data, + Evas_Object* obj, + void* event_info); + static void PermissionCancelCallback(void* data, + Evas_Object* obj, + void* event_info); + + Eina_List* permission_popups_ = nullptr; + Evas_Object* popup_ = nullptr; + Evas_Object* top_widget_ = nullptr; + Evas_Object* evas_object_; }; #endif // PermissionPopupManager_h -- 2.7.4 From 9bbddf098cc162676d73b63c8394de57a3059d8b Mon Sep 17 00:00:00 2001 From: v-saha Date: Mon, 30 Jan 2023 17:25:51 +0530 Subject: [PATCH 16/16] [M108 Migration] Toggle screencast off in Web inspector by default When web inspector is launched & screencast is enabled by default, it occupies a large amount of space & is tangential to the earlier layouts we show to the user Reference: https://review.tizen.org/gerrit/278284 Change-Id: Iae31c76d277ca1015ba335ce57c79cf9d86b20fc Signed-off-by: v-saha --- .../devtools-frontend/src/front_end/panels/screencast/ScreencastApp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/devtools-frontend/src/front_end/panels/screencast/ScreencastApp.ts b/third_party/devtools-frontend/src/front_end/panels/screencast/ScreencastApp.ts index 0c7eba2..6ef70c4 100644 --- a/third_party/devtools-frontend/src/front_end/panels/screencast/ScreencastApp.ts +++ b/third_party/devtools-frontend/src/front_end/panels/screencast/ScreencastApp.ts @@ -27,7 +27,7 @@ export class ScreencastApp implements Common.App.App, private screenCaptureModel?: SDK.ScreenCaptureModel.ScreenCaptureModel; private screencastView?: ScreencastView; constructor() { - this.enabledSetting = Common.Settings.Settings.instance().createSetting('screencastEnabled', true); + this.enabledSetting = Common.Settings.Settings.instance().createSetting('screencastEnabled', false); this.toggleButton = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.toggleScreencast), 'largeicon-phone'); this.toggleButton.setToggled(this.enabledSetting.get()); this.toggleButton.setEnabled(false); -- 2.7.4