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

Side by Side Diff: content/browser/download/mhtml_generation_manager.cc

Issue 2163073002: Avoid crashing if MHTMLGenerationManager::JobFinished is called twice. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698