[M108 Migration][API] Add ewk_view_save_page_as_mhtml as new internal API 54/287954/4
authorBakka Uday Kiran <b.kiran@samsung.com>
Wed, 8 Feb 2023 07:04:47 +0000 (12:34 +0530)
committerBot Blink <blinkbot@samsung.com>
Fri, 10 Feb 2023 13:13:22 +0000 (13:13 +0000)
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 <b.kiran@samsung.com>
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/public/ewk_view.cc

index 9238206..89770db 100644 (file)
 #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 =
     "<html><body><h1>Renderer process has crashed!</h1></body></html>";
 
@@ -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());
index 318f4e3..79abbc3 100755 (executable)
@@ -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*);
 
index 009709b..d779344 100644 (file)
@@ -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)