15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/mhtml_generation_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/stl_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_process_host_observer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/view_messages.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Job();
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~Job();
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetWebContents(WebContents* web_contents);
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File browser_file() { return browser_file_.Pass(); }
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void set_browser_file(base::File file) { browser_file_ = file.Pass(); }
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int process_id() { return process_id_; }
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int routing_id() { return routing_id_; }
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateMHTMLCallback callback() { return callback_; }
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void set_callback(GenerateMHTMLCallback callback) { callback_ = callback; }
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // RenderProcessHostObserver:
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RenderProcessExited(RenderProcessHost* host,
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   base::ProcessHandle handle,
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   base::TerminationStatus status,
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   int exit_code) OVERRIDE;
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The handle to the file the MHTML is saved to for the browser process.
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File browser_file_;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The IDs mapping to a specific contents.
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int process_id_;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int routing_id_;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The callback to call once generation is complete.
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GenerateMHTMLCallback callback_;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The RenderProcessHost being observed, or NULL if none is.
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RenderProcessHost* host_;
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Job);
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MHTMLGenerationManager::Job::Job()
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : process_id_(-1),
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      routing_id_(-1),
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      host_(NULL) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MHTMLGenerationManager::Job::~Job() {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (host_)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    host_->RemoveObserver(this);
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MHTMLGenerationManager::Job::SetWebContents(WebContents* web_contents) {
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  process_id_ = web_contents->GetRenderProcessHost()->GetID();
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  routing_id_ = web_contents->GetRenderViewHost()->GetRoutingID();
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host_ = web_contents->GetRenderProcessHost();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host_->AddObserver(this);
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MHTMLGenerationManager::Job::RenderProcessExited(
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RenderProcessHost* host,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ProcessHandle handle,
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::TerminationStatus status,
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int exit_code) {
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MHTMLGenerationManager::GetInstance()->RenderProcessExited(this);
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MHTMLGenerationManager::Job::RenderProcessHostDestroyed(
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    RenderProcessHost* host) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  host_ = NULL;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MHTMLGenerationManager* MHTMLGenerationManager::GetInstance() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<MHTMLGenerationManager>::get();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MHTMLGenerationManager::MHTMLGenerationManager() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MHTMLGenerationManager::~MHTMLGenerationManager() {
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  STLDeleteValues(&id_to_job_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void MHTMLGenerationManager::SaveMHTML(WebContents* web_contents,
102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                       const base::FilePath& file,
103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                       const GenerateMHTMLCallback& callback) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int job_id = NewJob(web_contents, callback);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessHandle renderer_process =
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_contents->GetRenderProcessHost()->GetHandle();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MHTMLGenerationManager::CreateFile, base::Unretained(this),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 job_id, file, renderer_process));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void MHTMLGenerationManager::StreamMHTML(
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    WebContents* web_contents,
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::File browser_file,
118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const GenerateMHTMLCallback& callback) {
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int job_id = NewJob(web_contents, callback);
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::ProcessHandle renderer_process =
124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      web_contents->GetRenderProcessHost()->GetHandle();
125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  IPC::PlatformFileForTransit renderer_file =
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)     IPC::GetFileHandleForProcess(browser_file.GetPlatformFile(),
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  renderer_process, false);
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FileAvailable(job_id, browser_file.Pass(), renderer_file);
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MHTMLGenerationManager::MHTMLGenerated(int job_id, int64 mhtml_data_size) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JobFinished(job_id, mhtml_data_size);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MHTMLGenerationManager::CreateFile(
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int job_id, const base::FilePath& file_path,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle renderer_process) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File browser_file(
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!browser_file.IsValid()) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create file to save MHTML at: " <<
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_path.value();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::PlatformFileForTransit renderer_file =
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      IPC::GetFileHandleForProcess(browser_file.GetPlatformFile(),
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   renderer_process, false);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  BrowserThread::PostTask(
153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BrowserThread::UI,
154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      FROM_HERE,
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&MHTMLGenerationManager::FileAvailable,
156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 base::Unretained(this),
157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 job_id,
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 base::Passed(&browser_file),
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 renderer_file));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MHTMLGenerationManager::FileAvailable(
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int job_id,
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::File browser_file,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::PlatformFileForTransit renderer_file) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!browser_file.IsValid()) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create file";
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JobFinished(job_id, -1);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDToJobMap::iterator iter = id_to_job_.find(job_id);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == id_to_job_.end()) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Job* job = iter->second;
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  job->set_browser_file(browser_file.Pass());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RenderViewHost* rvh = RenderViewHost::FromID(
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      job->process_id(), job->routing_id());
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rvh) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The contents went away.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JobFinished(job_id, -1);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rvh->Send(new ViewMsg_SavePageAsMHTML(rvh->GetRoutingID(), job_id,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        renderer_file));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MHTMLGenerationManager::JobFinished(int job_id, int64 file_size) {
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IDToJobMap::iterator iter = id_to_job_.find(job_id);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == id_to_job_.end()) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Job* job = iter->second;
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  job->callback().Run(file_size);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MHTMLGenerationManager::CloseFile, base::Unretained(this),
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 base::Passed(job->browser_file())));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_to_job_.erase(job_id);
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  delete job;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MHTMLGenerationManager::CloseFile(base::File file) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  file.Close();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int MHTMLGenerationManager::NewJob(WebContents* web_contents,
219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   const GenerateMHTMLCallback& callback) {
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  static int id_counter = 0;
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int job_id = id_counter++;
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Job* job = new Job();
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  id_to_job_[job_id] = job;
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  job->SetWebContents(web_contents);
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  job->set_callback(callback);
226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return job_id;
227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MHTMLGenerationManager::RenderProcessExited(Job* job) {
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  for (IDToJobMap::iterator it = id_to_job_.begin(); it != id_to_job_.end();
2323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch       ++it) {
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (it->second == job) {
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      JobFinished(it->first, -1);
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
2393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
242