From 2608ec7cb3d5d6270d87606bb2a5c38d2a0ec7e9 Mon Sep 17 00:00:00 2001 From: Bakka Uday Kiran Date: Wed, 8 Feb 2023 12:34:47 +0530 Subject: [PATCH] [M108 Migration][API] Add ewk_view_save_page_as_mhtml as new internal API This patch adds ewk_view_save_page_as_mhtml by MPR. It would be used to save current page as MHTML format for offline usage. Reference: https://review.tizen.org/gerrit/c/279838 Change-Id: Iff36f5ca44053116e4b1d5109fb08ad57e2ed8fa Signed-off-by: Bakka Uday Kiran --- tizen_src/ewk/efl_integration/eweb_view.cc | 90 ++++++++++++++++++++++++ tizen_src/ewk/efl_integration/eweb_view.h | 15 ++++ tizen_src/ewk/efl_integration/public/ewk_view.cc | 6 +- 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/tizen_src/ewk/efl_integration/eweb_view.cc b/tizen_src/ewk/efl_integration/eweb_view.cc index 9238206..89770db 100644 --- a/tizen_src/ewk/efl_integration/eweb_view.cc +++ b/tizen_src/ewk/efl_integration/eweb_view.cc @@ -11,10 +11,12 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/json/json_string_value_serializer.h" #include "base/logging.h" #include "base/pickle.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/task_runner_util.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" @@ -46,7 +48,9 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" +#include "content/public/common/mhtml_generation_params.h" #include "content/public/common/user_agent.h" +#include "net/base/filename_util.h" #include "permission_popup_manager.cc" #include "private/ewk_back_forward_list_private.h" #include "private/ewk_context_private.h" @@ -83,6 +87,15 @@ using web_contents_utils::WebViewFromWebContents; namespace { +const int kTitleLengthMax = 80; +const base::FilePath::CharType kMHTMLFileNameExtension[] = + FILE_PATH_LITERAL(".mhtml"); +const base::FilePath::CharType kMHTMLExtension[] = FILE_PATH_LITERAL("mhtml"); +const base::FilePath::CharType kDefaultFileName[] = + FILE_PATH_LITERAL("saved_page"); +const char kReplaceChars[] = " "; +const char kReplaceWith[] = "_"; + static const char* kRendererCrashedHTMLMessage = "

Renderer process has crashed!

"; @@ -105,6 +118,38 @@ static content::WebContents* NullCreateWebContents(void*) { return NULL; } +base::FilePath GenerateMHTMLFilePath(const GURL& url, + const std::string& title, + const std::string& base_path) { + base::FilePath file_path(base_path); + + if (base::DirectoryExists(file_path)) { + std::string title_part(title.substr(0, kTitleLengthMax)); + base::ReplaceChars(title_part, kReplaceChars, kReplaceWith, &title_part); + base::FilePath file_name = + net::GenerateFileName(url, std::string(), std::string(), title_part, + std::string(), kDefaultFileName); + DCHECK(!file_name.empty()); + file_path = file_path.Append(file_name); + } + + if (file_path.Extension().empty()) + file_path = file_path.AddExtension(kMHTMLExtension); + else if (!file_path.MatchesExtension(kMHTMLFileNameExtension)) + file_path = file_path.ReplaceExtension(kMHTMLExtension); + + if (!base::PathExists(file_path)) + return file_path; + + int uniquifier = base::GetUniquePathNumber(file_path); + if (uniquifier > 0) { + return file_path.InsertBeforeExtensionASCII( + base::StringPrintf(" (%d)", uniquifier)); + } + + return base::FilePath(); +} + } // namespace class WebViewAsyncRequestHitTestDataCallback { @@ -1998,6 +2043,51 @@ void EWebView::OnMHTMLContentGet(const std::string& mhtml_content, mhtml_callback_map_.Remove(callback_id); } +bool EWebView::SavePageAsMHTML(const std::string& path, + Ewk_View_Save_Page_Callback callback, + void* user_data) { + if (!web_contents_) + return false; + + GURL url(web_contents_->GetLastCommittedURL()); + std::u16string title(web_contents_->GetTitle()); + + // Post function that has file access to blocking task runner. + return base::PostTaskAndReplyWithResult( + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}) + .get(), + FROM_HERE, + base::BindOnce(&GenerateMHTMLFilePath, url, base::UTF16ToUTF8(title), + path), + base::BindOnce(&EWebView::GenerateMHTML, base::Unretained(this), callback, + user_data)); +} + +void EWebView::GenerateMHTML(Ewk_View_Save_Page_Callback callback, + void* user_data, + const base::FilePath& file_path) { + if (file_path.empty()) { + LOG(ERROR) << "Generating file path was failed"; + callback(evas_object_, nullptr, user_data); + return; + } + + MHTMLGenerationParams params(file_path); + web_contents_->GenerateMHTML( + params, base::BindOnce(&EWebView::MHTMLGenerated, base::Unretained(this), + callback, user_data, file_path)); +} + +void EWebView::MHTMLGenerated(Ewk_View_Save_Page_Callback callback, + void* user_data, + const base::FilePath& file_path, + int64_t file_size) { + callback(evas_object_, file_size > 0 ? file_path.value().c_str() : nullptr, + user_data); +} + bool EWebView::IsFullscreen() { return web_contents_delegate_->IsFullscreenForTabOrPending( web_contents_.get()); diff --git a/tizen_src/ewk/efl_integration/eweb_view.h b/tizen_src/ewk/efl_integration/eweb_view.h index 318f4e3..79abbc3 100755 --- a/tizen_src/ewk/efl_integration/eweb_view.h +++ b/tizen_src/ewk/efl_integration/eweb_view.h @@ -62,6 +62,10 @@ class WindowParentingClient; } // namespace client } // namespace aura +namespace base { +class FilePath; +} + namespace content { class RenderFrameHost; class RenderViewHost; @@ -442,6 +446,9 @@ class EWebView { bool GetMHTMLData(Ewk_View_MHTML_Data_Get_Callback callback, void* user_data); void OnMHTMLContentGet(const std::string& mhtml_content, int callback_id); + bool SavePageAsMHTML(const std::string& path, + Ewk_View_Save_Page_Callback callback, + void* user_data); bool IsFullscreen(); void ExitFullscreen(); double GetScale(); @@ -585,6 +592,14 @@ class EWebView { void ChangeScroll(int& x, int& y); + void GenerateMHTML(Ewk_View_Save_Page_Callback callback, + void* user_data, + const base::FilePath& file_path); + void MHTMLGenerated(Ewk_View_Save_Page_Callback callback, + void* user_data, + const base::FilePath& file_path, + int64_t file_size); + static void OnViewFocusIn(void* data, Evas*, Evas_Object*, void*); static void OnViewFocusOut(void* data, Evas*, Evas_Object*, void*); diff --git a/tizen_src/ewk/efl_integration/public/ewk_view.cc b/tizen_src/ewk/efl_integration/public/ewk_view.cc index 009709b..d779344 100644 --- a/tizen_src/ewk/efl_integration/public/ewk_view.cc +++ b/tizen_src/ewk/efl_integration/public/ewk_view.cc @@ -1184,8 +1184,10 @@ Eina_Bool ewk_view_did_change_theme_color_callback_set(Evas_Object* o, Ewk_View_ Eina_Bool ewk_view_save_page_as_mhtml(Evas_Object* o, const char* path, Ewk_View_Save_Page_Callback callback, void* user_data) { - LOG_EWK_API_MOCKUP(); - return false; + EWK_VIEW_IMPL_GET_OR_RETURN(o, impl, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(path, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE); + return impl->SavePageAsMHTML(path, callback, user_data); } void ewk_view_reader_mode_set(Evas_Object* ewk_view, Eina_Bool enable) -- 2.7.4