OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/download/mhtml_generation_manager.h" | 5 #include "content/browser/download/mhtml_generation_manager.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <queue> | 8 #include <queue> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 // Close the file on the file thread and respond back on the UI thread with | 68 // Close the file on the file thread and respond back on the UI thread with |
69 // file size. | 69 // file size. |
70 void CloseFile(base::Callback<void(int64_t file_size)> callback); | 70 void CloseFile(base::Callback<void(int64_t file_size)> callback); |
71 | 71 |
72 // RenderProcessHostObserver: | 72 // RenderProcessHostObserver: |
73 void RenderProcessExited(RenderProcessHost* host, | 73 void RenderProcessExited(RenderProcessHost* host, |
74 base::TerminationStatus status, | 74 base::TerminationStatus status, |
75 int exit_code) override; | 75 int exit_code) override; |
76 void RenderProcessHostDestroyed(RenderProcessHost* host) override; | 76 void RenderProcessHostDestroyed(RenderProcessHost* host) override; |
77 | 77 |
78 bool is_finished() const { return is_finished_; } | |
79 void MarkAsFinished() { is_finished_ = true; } | |
80 | |
78 private: | 81 private: |
79 static int64_t CloseFileOnFileThread(base::File file); | 82 static int64_t CloseFileOnFileThread(base::File file); |
80 void AddFrame(RenderFrameHost* render_frame_host); | 83 void AddFrame(RenderFrameHost* render_frame_host); |
81 | 84 |
82 // Creates a new map with values (content ids) the same as in | 85 // Creates a new map with values (content ids) the same as in |
83 // |frame_tree_node_to_content_id_| map, but with the keys translated from | 86 // |frame_tree_node_to_content_id_| map, but with the keys translated from |
84 // frame_tree_node_id into a |site_instance|-specific routing_id. | 87 // frame_tree_node_id into a |site_instance|-specific routing_id. |
85 std::map<int, std::string> CreateFrameRoutingIdToContentId( | 88 std::map<int, std::string> CreateFrameRoutingIdToContentId( |
86 SiteInstance* site_instance); | 89 SiteInstance* site_instance); |
87 | 90 |
(...skipping 24 matching lines...) Expand all Loading... | |
112 // MIME multipart boundary to use in the MHTML doc. | 115 // MIME multipart boundary to use in the MHTML doc. |
113 std::string mhtml_boundary_marker_; | 116 std::string mhtml_boundary_marker_; |
114 | 117 |
115 // Digests of URIs of already generated MHTML parts. | 118 // Digests of URIs of already generated MHTML parts. |
116 std::set<std::string> digests_of_already_serialized_uris_; | 119 std::set<std::string> digests_of_already_serialized_uris_; |
117 std::string salt_; | 120 std::string salt_; |
118 | 121 |
119 // The callback to call once generation is complete. | 122 // The callback to call once generation is complete. |
120 const GenerateMHTMLCallback callback_; | 123 const GenerateMHTMLCallback callback_; |
121 | 124 |
125 // Whether the job is finished (set to true only for the short duration of | |
126 // time between MHTMLGenerationManager::JobFinished is called and the job is | |
127 // destroyed by MHTMLGenerationManager::OnFileClosed). | |
128 bool is_finished_; | |
129 | |
122 // RAII helper for registering this Job as a RenderProcessHost observer. | 130 // RAII helper for registering this Job as a RenderProcessHost observer. |
123 ScopedObserver<RenderProcessHost, MHTMLGenerationManager::Job> | 131 ScopedObserver<RenderProcessHost, MHTMLGenerationManager::Job> |
124 observed_renderer_process_host_; | 132 observed_renderer_process_host_; |
125 | 133 |
126 DISALLOW_COPY_AND_ASSIGN(Job); | 134 DISALLOW_COPY_AND_ASSIGN(Job); |
127 }; | 135 }; |
128 | 136 |
129 MHTMLGenerationManager::Job::Job(int job_id, | 137 MHTMLGenerationManager::Job::Job(int job_id, |
130 WebContents* web_contents, | 138 WebContents* web_contents, |
131 const MHTMLGenerationParams& params, | 139 const MHTMLGenerationParams& params, |
132 const GenerateMHTMLCallback& callback) | 140 const GenerateMHTMLCallback& callback) |
133 : job_id_(job_id), | 141 : job_id_(job_id), |
134 params_(params), | 142 params_(params), |
135 frame_tree_node_id_of_busy_frame_(FrameTreeNode::kFrameTreeNodeInvalidId), | 143 frame_tree_node_id_of_busy_frame_(FrameTreeNode::kFrameTreeNodeInvalidId), |
136 mhtml_boundary_marker_(net::GenerateMimeMultipartBoundary()), | 144 mhtml_boundary_marker_(net::GenerateMimeMultipartBoundary()), |
137 salt_(base::GenerateGUID()), | 145 salt_(base::GenerateGUID()), |
138 callback_(callback), | 146 callback_(callback), |
147 is_finished_(false), | |
139 observed_renderer_process_host_(this) { | 148 observed_renderer_process_host_(this) { |
140 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 149 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
141 web_contents->ForEachFrame(base::Bind( | 150 web_contents->ForEachFrame(base::Bind( |
142 &MHTMLGenerationManager::Job::AddFrame, | 151 &MHTMLGenerationManager::Job::AddFrame, |
143 base::Unretained(this))); // Safe because ForEachFrame is synchronous. | 152 base::Unretained(this))); // Safe because ForEachFrame is synchronous. |
144 | 153 |
145 // Main frame needs to be processed first. | 154 // Main frame needs to be processed first. |
146 DCHECK(!pending_frame_tree_node_ids_.empty()); | 155 DCHECK(!pending_frame_tree_node_ids_.empty()); |
147 DCHECK(FrameTreeNode::GloballyFindByID(pending_frame_tree_node_ids_.front()) | 156 DCHECK(FrameTreeNode::GloballyFindByID(pending_frame_tree_node_ids_.front()) |
148 ->parent() == nullptr); | 157 ->parent() == nullptr); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 | 390 |
382 if (!job->SendToNextRenderFrame()) { | 391 if (!job->SendToNextRenderFrame()) { |
383 JobFinished(job, JobStatus::FAILURE); | 392 JobFinished(job, JobStatus::FAILURE); |
384 } | 393 } |
385 } | 394 } |
386 | 395 |
387 void MHTMLGenerationManager::JobFinished(Job* job, JobStatus job_status) { | 396 void MHTMLGenerationManager::JobFinished(Job* job, JobStatus job_status) { |
388 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 397 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
389 DCHECK(job); | 398 DCHECK(job); |
390 | 399 |
391 job->CloseFile( | 400 // Make sure we gracefully handle the case when JobFinished is called twice |
392 base::Bind(&MHTMLGenerationManager::OnFileClosed, | 401 // (i.e. once from OnSerializeAsMHTMLResponse and while the file is being |
393 base::Unretained(this), // Safe b/c |this| is a singleton. | 402 // closed also called a second time from RenderProcessExited). |
394 job->id(), job_status)); | 403 if (!job->is_finished()) { // Is this the first time JobFinished is called? |
404 job->MarkAsFinished(); | |
dewittj
2016/07/20 16:37:48
May want to clear |job|'s |observed_renderer_proce
Randy Smith (Not in Mondays)
2016/07/20 16:46:58
This is a good point, but wouldn't this solve this
Łukasz Anforowicz
2016/07/20 21:10:07
Done. Good point.
Randy Smith (Not in Mondays)
2016/07/20 22:47:49
Sure, that sounds good. Thanks for thinking the i
| |
405 job->CloseFile( | |
406 base::Bind(&MHTMLGenerationManager::OnFileClosed, | |
407 base::Unretained(this), // Safe b/c |this| is a singleton. | |
408 job->id(), job_status)); | |
409 } | |
395 } | 410 } |
396 | 411 |
397 void MHTMLGenerationManager::OnFileClosed(int job_id, | 412 void MHTMLGenerationManager::OnFileClosed(int job_id, |
398 JobStatus job_status, | 413 JobStatus job_status, |
399 int64_t file_size) { | 414 int64_t file_size) { |
400 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 415 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
401 | 416 |
402 Job* job = FindJob(job_id); | 417 Job* job = FindJob(job_id); |
403 job->callback().Run(job_status == JobStatus::SUCCESS ? file_size : -1); | 418 job->callback().Run(job_status == JobStatus::SUCCESS ? file_size : -1); |
404 id_to_job_.erase(job_id); | 419 id_to_job_.erase(job_id); |
(...skipping 21 matching lines...) Expand all Loading... | |
426 return iter->second; | 441 return iter->second; |
427 } | 442 } |
428 | 443 |
429 void MHTMLGenerationManager::RenderProcessExited(Job* job) { | 444 void MHTMLGenerationManager::RenderProcessExited(Job* job) { |
430 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 445 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
431 DCHECK(job); | 446 DCHECK(job); |
432 JobFinished(job, JobStatus::FAILURE); | 447 JobFinished(job, JobStatus::FAILURE); |
433 } | 448 } |
434 | 449 |
435 } // namespace content | 450 } // namespace content |
OLD | NEW |