Revert 285173 "Removed InProcessBrowserTest::CleanUpOnMainThread()"
[chromium-blink-merge.git] / chrome / browser / extensions / api / page_capture / page_capture_api.cc
blobb342c2488ce8a314dac7ac7e9fc02e93d6f3a3ad
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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/page_capture/page_capture_api.h"
7 #include <limits>
9 #include "base/bind.h"
10 #include "base/file_util.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/extensions/extension_tab_util.h"
13 #include "content/public/browser/child_process_security_policy.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_source.h"
16 #include "content/public/browser/notification_types.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "extensions/common/extension_messages.h"
22 using content::BrowserThread;
23 using content::ChildProcessSecurityPolicy;
24 using content::WebContents;
25 using extensions::PageCaptureSaveAsMHTMLFunction;
26 using webkit_blob::ShareableFileReference;
28 namespace SaveAsMHTML = extensions::api::page_capture::SaveAsMHTML;
30 namespace {
32 const char kFileTooBigError[] = "The MHTML file generated is too big.";
33 const char kMHTMLGenerationFailedError[] = "Failed to generate MHTML.";
34 const char kTemporaryFileError[] = "Failed to create a temporary file.";
35 const char kTabClosedError[] = "Cannot find the tab for this request.";
37 } // namespace
39 static PageCaptureSaveAsMHTMLFunction::TestDelegate* test_delegate_ = NULL;
41 PageCaptureSaveAsMHTMLFunction::PageCaptureSaveAsMHTMLFunction() {
44 PageCaptureSaveAsMHTMLFunction::~PageCaptureSaveAsMHTMLFunction() {
45 if (mhtml_file_.get()) {
46 webkit_blob::ShareableFileReference* to_release = mhtml_file_.get();
47 to_release->AddRef();
48 mhtml_file_ = NULL;
49 BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, to_release);
53 void PageCaptureSaveAsMHTMLFunction::SetTestDelegate(TestDelegate* delegate) {
54 test_delegate_ = delegate;
57 bool PageCaptureSaveAsMHTMLFunction::RunAsync() {
58 params_ = SaveAsMHTML::Params::Create(*args_);
59 EXTENSION_FUNCTION_VALIDATE(params_.get());
61 AddRef(); // Balanced in ReturnFailure/ReturnSuccess()
63 BrowserThread::PostTask(
64 BrowserThread::FILE, FROM_HERE,
65 base::Bind(&PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile, this));
66 return true;
69 bool PageCaptureSaveAsMHTMLFunction::OnMessageReceived(
70 const IPC::Message& message) {
71 if (message.type() != ExtensionHostMsg_ResponseAck::ID)
72 return false;
74 int message_request_id;
75 PickleIterator iter(message);
76 if (!message.ReadInt(&iter, &message_request_id)) {
77 NOTREACHED() << "malformed extension message";
78 return true;
81 if (message_request_id != request_id())
82 return false;
84 // The extension process has processed the response and has created a
85 // reference to the blob, it is safe for us to go away.
86 Release(); // Balanced in Run()
88 return true;
91 void PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile() {
92 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
93 bool success = base::CreateTemporaryFile(&mhtml_path_);
94 BrowserThread::PostTask(
95 BrowserThread::IO, FROM_HERE,
96 base::Bind(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated, this,
97 success));
100 void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated(bool success) {
101 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
102 if (success) {
103 // Setup a ShareableFileReference so the temporary file gets deleted
104 // once it is no longer used.
105 mhtml_file_ = ShareableFileReference::GetOrCreate(
106 mhtml_path_,
107 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
108 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
109 .get());
111 BrowserThread::PostTask(
112 BrowserThread::UI, FROM_HERE,
113 base::Bind(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated, this,
114 success));
115 return;
118 DCHECK_CURRENTLY_ON(BrowserThread::UI);
119 if (!success) {
120 ReturnFailure(kTemporaryFileError);
121 return;
124 if (test_delegate_)
125 test_delegate_->OnTemporaryFileCreated(mhtml_path_);
127 WebContents* web_contents = GetWebContents();
128 if (!web_contents) {
129 ReturnFailure(kTabClosedError);
130 return;
133 web_contents->GenerateMHTML(
134 mhtml_path_,
135 base::Bind(&PageCaptureSaveAsMHTMLFunction::MHTMLGenerated, this));
138 void PageCaptureSaveAsMHTMLFunction::MHTMLGenerated(
139 int64 mhtml_file_size) {
140 if (mhtml_file_size <= 0) {
141 ReturnFailure(kMHTMLGenerationFailedError);
142 return;
145 if (mhtml_file_size > std::numeric_limits<int>::max()) {
146 ReturnFailure(kFileTooBigError);
147 return;
150 ReturnSuccess(mhtml_file_size);
153 void PageCaptureSaveAsMHTMLFunction::ReturnFailure(const std::string& error) {
154 DCHECK_CURRENTLY_ON(BrowserThread::UI);
156 error_ = error;
158 SendResponse(false);
160 Release(); // Balanced in Run()
163 void PageCaptureSaveAsMHTMLFunction::ReturnSuccess(int64 file_size) {
164 DCHECK_CURRENTLY_ON(BrowserThread::UI);
166 WebContents* web_contents = GetWebContents();
167 if (!web_contents || !render_view_host()) {
168 ReturnFailure(kTabClosedError);
169 return;
172 int child_id = render_view_host()->GetProcess()->GetID();
173 ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
174 child_id, mhtml_path_);
176 base::DictionaryValue* dict = new base::DictionaryValue();
177 SetResult(dict);
178 dict->SetString("mhtmlFilePath", mhtml_path_.value());
179 dict->SetInteger("mhtmlFileLength", file_size);
181 SendResponse(true);
183 // Note that we'll wait for a response ack message received in
184 // OnMessageReceived before we call Release() (to prevent the blob file from
185 // being deleted).
188 WebContents* PageCaptureSaveAsMHTMLFunction::GetWebContents() {
189 Browser* browser = NULL;
190 content::WebContents* web_contents = NULL;
192 if (!ExtensionTabUtil::GetTabById(params_->details.tab_id,
193 GetProfile(),
194 include_incognito(),
195 &browser,
196 NULL,
197 &web_contents,
198 NULL)) {
199 return NULL;
201 return web_contents;