blob: 351c92ca75a9658c56ba5081418113e91887b415 [file] [log] [blame]
[email protected]3a605e82011-09-26 17:26:161// Copyright (c) 2011 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.
4
[email protected]9e4430f2011-11-28 07:43:295#include "chrome/browser/extensions/extension_page_capture_api.h"
[email protected]3a605e82011-09-26 17:26:166
[email protected]7477b2712011-11-23 07:53:037#include "base/bind.h"
[email protected]3a605e82011-09-26 17:26:168#include "base/file_util.h"
9#include "chrome/browser/browser_process.h"
[email protected]ac84431b2011-09-27 17:26:1110#include "chrome/browser/extensions/extension_tab_util.h"
[email protected]3a605e82011-09-26 17:26:1611#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
[email protected]0f7daaa2011-11-22 18:34:5612#include "chrome/common/extensions/extension_messages.h"
[email protected]3a605e82011-09-26 17:26:1613#include "content/browser/child_process_security_policy.h"
14#include "content/browser/renderer_host/render_view_host.h"
15#include "content/browser/tab_contents/tab_contents.h"
16#include "content/browser/download/mhtml_generation_manager.h"
[email protected]ad50def52011-10-19 23:17:0717#include "content/public/browser/notification_details.h"
18#include "content/public/browser/notification_source.h"
[email protected]0d6e9bd2011-10-18 04:29:1619#include "content/public/browser/notification_types.h"
[email protected]3a605e82011-09-26 17:26:1620
[email protected]631bb742011-11-02 11:29:3921using content::BrowserThread;
22
[email protected]3a605e82011-09-26 17:26:1623// Error messages.
24const char* const kFileTooBigError = "The MHTML file generated is too big.";
25const char* const kMHTMLGenerationFailedError = "Failed to generate MHTML.";
26const char* const kSizeRetrievalError =
27 "Failed to retrieve size of generated MHTML.";
28const char* const kTemporaryFileError = "Failed to create a temporary file.";
29const char* const kTabClosedError = "Cannot find the tab for thie request.";
30
[email protected]9e4430f2011-11-28 07:43:2931static PageCaptureSaveAsMHTMLFunction::TestDelegate* test_delegate_ = NULL;
[email protected]0f7daaa2011-11-22 18:34:5632
[email protected]9e4430f2011-11-28 07:43:2933PageCaptureSaveAsMHTMLFunction::PageCaptureSaveAsMHTMLFunction() : tab_id_(0) {
[email protected]3a605e82011-09-26 17:26:1634}
35
[email protected]9e4430f2011-11-28 07:43:2936PageCaptureSaveAsMHTMLFunction::~PageCaptureSaveAsMHTMLFunction() {
[email protected]3a605e82011-09-26 17:26:1637}
38
[email protected]9e4430f2011-11-28 07:43:2939void PageCaptureSaveAsMHTMLFunction::SetTestDelegate(TestDelegate* delegate) {
[email protected]0f7daaa2011-11-22 18:34:5640 test_delegate_ = delegate;
41}
42
[email protected]9e4430f2011-11-28 07:43:2943bool PageCaptureSaveAsMHTMLFunction::RunImpl() {
[email protected]8077c952011-11-22 23:27:1444 DictionaryValue* args;
45 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &args));
46
47 if (!args->HasKey("tabId"))
48 return false;
49
50 EXTENSION_FUNCTION_VALIDATE(args->GetInteger("tabId", &tab_id_));
[email protected]3a605e82011-09-26 17:26:1651
52 AddRef(); // Balanced in ReturnFailure/ReturnSuccess()
53
54 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
[email protected]9e4430f2011-11-28 07:43:2955 NewRunnableMethod(this,
56 &PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile));
[email protected]3a605e82011-09-26 17:26:1657 return true;
58}
59
[email protected]9e4430f2011-11-28 07:43:2960bool PageCaptureSaveAsMHTMLFunction::OnMessageReceivedFromRenderView(
[email protected]0f7daaa2011-11-22 18:34:5661 const IPC::Message& message) {
62 if (message.type() != ExtensionHostMsg_ResponseAck::ID)
63 return false;
64
65 int message_request_id;
66 void* iter = NULL;
67 if (!message.ReadInt(&iter, &message_request_id)) {
68 NOTREACHED() << "malformed extension message";
69 return true;
70 }
71
72 if (message_request_id != request_id())
73 return false;
74
75 // The extension process has processed the response and has created a
76 // reference to the blob, it is safe for us to go away.
77 Release(); // Balanced in Run()
78
79 return true;
80}
81
[email protected]9e4430f2011-11-28 07:43:2982void PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile() {
[email protected]3a605e82011-09-26 17:26:1683 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]3a605e82011-09-26 17:26:1684 bool success = file_util::CreateTemporaryFile(&mhtml_path_);
85 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
[email protected]9e4430f2011-11-28 07:43:2986 NewRunnableMethod(this,
87 &PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated,
[email protected]3a605e82011-09-26 17:26:1688 success));
89}
90
[email protected]9e4430f2011-11-28 07:43:2991void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated(bool success) {
[email protected]3a605e82011-09-26 17:26:1692 if (!success) {
93 ReturnFailure(kTemporaryFileError);
94 return;
95 }
96
[email protected]0f7daaa2011-11-22 18:34:5697 if (test_delegate_)
98 test_delegate_->OnTemporaryFileCreated(mhtml_path_);
[email protected]3a605e82011-09-26 17:26:1699
[email protected]0f7daaa2011-11-22 18:34:56100 // Sets a DeletableFileReference so the temporary file gets deleted once it is
101 // no longer used.
102 mhtml_file_ = webkit_blob::DeletableFileReference::GetOrCreate(mhtml_path_,
103 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
104
105 TabContents* tab_contents = GetTabContents();
106 if (!tab_contents) {
[email protected]3a605e82011-09-26 17:26:16107 ReturnFailure(kTabClosedError);
108 return;
109 }
110
[email protected]7477b2712011-11-23 07:53:03111 MHTMLGenerationManager::GenerateMHTMLCallback callback =
[email protected]9e4430f2011-11-28 07:43:29112 base::Bind(&PageCaptureSaveAsMHTMLFunction::MHTMLGenerated, this);
[email protected]7477b2712011-11-23 07:53:03113
[email protected]3a605e82011-09-26 17:26:16114 g_browser_process->mhtml_generation_manager()->GenerateMHTML(
[email protected]7477b2712011-11-23 07:53:03115 tab_contents, mhtml_path_, callback);
[email protected]3a605e82011-09-26 17:26:16116}
117
[email protected]9e4430f2011-11-28 07:43:29118void PageCaptureSaveAsMHTMLFunction::MHTMLGenerated(const FilePath& file_path,
119 int64 mhtml_file_size) {
[email protected]7477b2712011-11-23 07:53:03120 DCHECK(mhtml_path_ == file_path);
121 if (mhtml_file_size <= 0) {
[email protected]3a605e82011-09-26 17:26:16122 ReturnFailure(kMHTMLGenerationFailedError);
123 return;
124 }
125
[email protected]7477b2712011-11-23 07:53:03126 if (mhtml_file_size > std::numeric_limits<int>::max()) {
[email protected]3a605e82011-09-26 17:26:16127 ReturnFailure(kFileTooBigError);
128 return;
129 }
130
[email protected]7477b2712011-11-23 07:53:03131 ReturnSuccess(mhtml_file_size);
[email protected]3a605e82011-09-26 17:26:16132}
133
[email protected]9e4430f2011-11-28 07:43:29134void PageCaptureSaveAsMHTMLFunction::ReturnFailure(const std::string& error) {
[email protected]3a605e82011-09-26 17:26:16135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
136
137 error_ = error;
138
139 SendResponse(false);
140
141 Release(); // Balanced in Run()
142}
143
[email protected]9e4430f2011-11-28 07:43:29144void PageCaptureSaveAsMHTMLFunction::ReturnSuccess(int64 file_size) {
[email protected]3a605e82011-09-26 17:26:16145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146
[email protected]0f7daaa2011-11-22 18:34:56147 TabContents* tab_contents = GetTabContents();
148 if (!tab_contents || !render_view_host()) {
149 ReturnFailure(kTabClosedError);
150 return;
151 }
152
[email protected]f3b1a082011-11-18 00:34:30153 int child_id = render_view_host()->process()->GetID();
[email protected]3a605e82011-09-26 17:26:16154 ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
155 child_id, mhtml_path_);
156
157 DictionaryValue* dict = new DictionaryValue();
158 result_.reset(dict);
159 dict->SetString("mhtmlFilePath", mhtml_path_.value());
160 dict->SetInteger("mhtmlFileLength", file_size);
161
162 SendResponse(true);
163
[email protected]0f7daaa2011-11-22 18:34:56164 // Note that we'll wait for a response ack message received in
165 // OnMessageReceivedFromRenderView before we call Release() (to prevent the
166 // blob file from being deleted).
167}
168
[email protected]9e4430f2011-11-28 07:43:29169TabContents* PageCaptureSaveAsMHTMLFunction::GetTabContents() {
[email protected]0f7daaa2011-11-22 18:34:56170 Browser* browser = NULL;
171 TabContentsWrapper* tab_contents_wrapper = NULL;
172
173 if (!ExtensionTabUtil::GetTabById(tab_id_, profile(), include_incognito(),
174 &browser, NULL, &tab_contents_wrapper, NULL)) {
175 return NULL;
176 }
177 return tab_contents_wrapper->tab_contents();
[email protected]3a605e82011-09-26 17:26:16178}