Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1132)

Unified Diff: content/browser/download/mhtml_generation_manager.cc

Issue 1417323006: OOPIFs: Deduplicating MHTML parts across frames. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mhtml-serialization-per-frame
Patch Set: Rebasing... Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/download/mhtml_generation_manager.cc
diff --git a/content/browser/download/mhtml_generation_manager.cc b/content/browser/download/mhtml_generation_manager.cc
index e011f42dae39635230366e9daa7947ffb863d6d8..9d112ffb716b1a29caf5bb17a657b4f0d8d94a2c 100644
--- a/content/browser/download/mhtml_generation_manager.cc
+++ b/content/browser/download/mhtml_generation_manager.cc
@@ -20,6 +20,8 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/web_contents.h"
+#include "crypto/sha2.h"
+#include "url/gurl.h"
namespace content {
@@ -34,15 +36,18 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
GenerateMHTMLCallback callback() const { return callback_; }
- // Sends IPC to the renderer, asking for MHTML generation of the next frame.
- //
- // Returns true if the message was sent successfully; false otherwise.
- //
- // See FrameMsg_SerializeAsMHTML IPC message for description of
- // |mhtml_boundary_marker| parameter.
- bool SendToNextRenderFrame(const std::string& mhtml_boundary_marker);
+ // Sends IPC to the renderer of the first frame, asking it to start
+ // MHTML serialization.
+ // Returns |true| upon success; |false| otherwise.
+ bool SendToFirstFrame();
- // Indicates if more calls to SendToNextRenderFrame are needed.
+ // Handler for ViewHostMsg_SavedPageAsMHTML (a notification from the renderer
+ // that the MHTML generation for previous frame has finished).
+ // Returns |true| upon success; |false| otherwise.
+ bool OnSavedPageAsMHTML(std::string mhtml_boundary_marker,
+ const std::set<GURL>& uris_of_generated_mhtml_parts);
+
+ // Indicates if the job has completed.
bool GotMoreFramesToProcess() {
return !pending_frame_tree_node_ids_.empty();
}
@@ -66,6 +71,14 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
std::map<int, std::string> CreateFrameRoutingIdToContentId(
SiteInstance* site_instance);
+ // Sends IPC to the renderer, asking for MHTML generation of the next frame.
+ //
+ // Returns true if the message was sent successfully; false otherwise.
+ //
+ // See FrameMsg_SerializeAsMHTML IPC message for description of
+ // |mhtml_boundary_marker| parameter.
+ bool SendToNextRenderFrame(const std::string& mhtml_boundary_marker);
+
// Id used to map renderer responses to jobs.
// See also MHTMLGenerationManager::id_to_job_ map.
int job_id_;
@@ -80,6 +93,9 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
// for more details about what "content ids" are and how they are used).
std::map<int, std::string> frame_tree_node_to_content_id_;
+ // URIs of already generated MHTML parts.
+ std::set<GURL> already_serialized_uris_;
+
// The callback to call once generation is complete.
GenerateMHTMLCallback callback_;
@@ -138,9 +154,13 @@ bool MHTMLGenerationManager::Job::SendToNextRenderFrame(
DCHECK(browser_file_.IsValid());
DCHECK_LT(0u, pending_frame_tree_node_ids_.size());
+ FrameMsg_SerializeAsMHTML_Params ipc_params;
+ ipc_params.job_id = job_id_;
+ ipc_params.mhtml_boundary_marker = mhtml_boundary_marker;
+
int frame_tree_node_id = pending_frame_tree_node_ids_.front();
pending_frame_tree_node_ids_.pop();
- bool is_last_frame = pending_frame_tree_node_ids_.empty();
+ ipc_params.is_last_frame = pending_frame_tree_node_ids_.empty();
FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
if (!ftn) // The contents went away.
@@ -151,12 +171,20 @@ bool MHTMLGenerationManager::Job::SendToNextRenderFrame(
observed_renderer_process_host_.RemoveAll();
observed_renderer_process_host_.Add(rfh->GetProcess());
- IPC::PlatformFileForTransit renderer_file = IPC::GetFileHandleForProcess(
+ // Tell the renderer to skip (= deduplicate) already covered MHTML parts.
+ std::set<std::string> digests_of_uris_to_skip;
ncarter (slow) 2015/12/04 21:52:39 This is unused.
Łukasz Anforowicz 2015/12/04 22:55:43 Thanks for catching this. I must have missed this
+ ipc_params.salt = base::GenerateGUID();
+ for (const GURL& uri : already_serialized_uris_) {
+ std::string digest = crypto::SHA256HashString(ipc_params.salt + uri.spec());
+ ipc_params.digests_of_uris_to_skip.insert(digest);
+ }
+
+ ipc_params.destination_file = IPC::GetFileHandleForProcess(
browser_file_.GetPlatformFile(), rfh->GetProcess()->GetHandle(),
false); // |close_source_handle|.
- rfh->Send(new FrameMsg_SerializeAsMHTML(
- rfh->GetRoutingID(), job_id_, renderer_file, mhtml_boundary_marker,
- CreateFrameRoutingIdToContentId(rfh->GetSiteInstance()), is_last_frame));
+ ipc_params.frame_routing_id_to_content_id =
+ CreateFrameRoutingIdToContentId(rfh->GetSiteInstance());
+ rfh->Send(new FrameMsg_SerializeAsMHTML(rfh->GetRoutingID(), ipc_params));
return true;
}
@@ -202,6 +230,27 @@ void MHTMLGenerationManager::Job::CloseFile(
callback);
}
+bool MHTMLGenerationManager::Job::SendToFirstFrame() {
+ // We don't yet have an mhtml boundary marker when serializing the 1st frame.
+ std::string initial_mhtml_boundary_marker = "";
+
+ return SendToNextRenderFrame(initial_mhtml_boundary_marker);
+}
+
+bool MHTMLGenerationManager::Job::OnSavedPageAsMHTML(
+ std::string mhtml_boundary_marker,
+ const std::set<GURL>& uris_of_generated_mhtml_parts) {
+ bool success = true;
+
+ already_serialized_uris_.insert(uris_of_generated_mhtml_parts.begin(),
+ uris_of_generated_mhtml_parts.end());
+
+ if (GotMoreFramesToProcess())
+ success = SendToNextRenderFrame(mhtml_boundary_marker);
+
+ return success;
+}
+
// static
int64 MHTMLGenerationManager::Job::CloseFileOnFileThread(base::File file) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
@@ -239,7 +288,8 @@ void MHTMLGenerationManager::SaveMHTML(WebContents* web_contents,
void MHTMLGenerationManager::OnSavedPageAsMHTML(
int job_id,
bool mhtml_generation_in_renderer_succeeded,
- const std::string& mhtml_boundary_marker) {
+ const std::string& mhtml_boundary_marker,
+ const std::set<GURL>& uris_of_generated_mhtml_parts) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!mhtml_generation_in_renderer_succeeded) {
@@ -251,14 +301,15 @@ void MHTMLGenerationManager::OnSavedPageAsMHTML(
if (!job)
return;
- if (job->GotMoreFramesToProcess()) {
- if (!job->SendToNextRenderFrame(mhtml_boundary_marker)) {
- JobFinished(job_id, JobStatus::FAILURE);
- }
+ if (!job->GotMoreFramesToProcess()) {
+ JobFinished(job_id, JobStatus::SUCCESS);
return;
}
- JobFinished(job_id, JobStatus::SUCCESS);
+ if (!job->OnSavedPageAsMHTML(mhtml_boundary_marker,
+ uris_of_generated_mhtml_parts)) {
+ JobFinished(job_id, JobStatus::FAILURE);
+ }
}
// static
@@ -297,9 +348,7 @@ void MHTMLGenerationManager::OnFileAvailable(int job_id,
job->set_browser_file(browser_file.Pass());
- // We don't yet have an mhtml boundary marker when serializing the 1st frame.
- std::string initial_mhtml_boundary_marker = "";
- if (!job->SendToNextRenderFrame(initial_mhtml_boundary_marker)) {
+ if (!job->SendToFirstFrame()) {
JobFinished(job_id, JobStatus::FAILURE);
}
}

Powered by Google App Engine
This is Rietveld 408576698