summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_process.h3
-rw-r--r--chrome/browser/browser_process_impl.cc8
-rw-r--r--chrome/browser/browser_process_impl.h4
-rw-r--r--chrome/browser/download/mhtml_generation_browsertest.cc66
-rw-r--r--chrome/browser/download/mhtml_generation_manager.cc136
-rw-r--r--chrome/browser/download/mhtml_generation_manager.h81
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.cc13
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.h1
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_renderer.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/render_messages.h11
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc2
-rw-r--r--chrome/renderer/mhtml_generator.cc65
-rw-r--r--chrome/renderer/mhtml_generator.h32
-rw-r--r--chrome/test/testing_browser_process.cc4
-rw-r--r--chrome/test/testing_browser_process.h2
17 files changed, 431 insertions, 2 deletions
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index 3351d0b..82e7970 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -30,6 +30,7 @@ class IconManager;
class IntranetRedirectDetector;
class IOThread;
class MetricsService;
+class MHTMLGenerationManager;
class NotificationUIManager;
class PrefService;
class ProfileManager;
@@ -239,6 +240,8 @@ class BrowserProcess {
plugin_data_remover_mime_type_ = mime_type;
}
+ virtual MHTMLGenerationManager* mhtml_generation_manager() = 0;
+
private:
// User-data-dir based profiles.
std::vector<std::wstring> user_data_dir_profiles_;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 771f67e..41c846c 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/debugger/devtools_protocol_handler.h"
#include "chrome/browser/download/download_file_manager.h"
+#include "chrome/browser/download/mhtml_generation_manager.h"
#include "chrome/browser/download/save_file_manager.h"
#include "chrome/browser/extensions/extension_event_router_forwarder.h"
#include "chrome/browser/extensions/extension_tab_id_map.h"
@@ -691,6 +692,13 @@ prerender::PrerenderTracker* BrowserProcessImpl::prerender_tracker() {
return prerender_tracker_.get();
}
+MHTMLGenerationManager* BrowserProcessImpl::mhtml_generation_manager() {
+ if (!mhtml_generation_manager_.get())
+ mhtml_generation_manager_ = new MHTMLGenerationManager();
+
+ return mhtml_generation_manager_.get();
+}
+
void BrowserProcessImpl::ClearLocalState(const FilePath& profile_path) {
webkit_database::DatabaseTracker::ClearLocalState(profile_path);
BrowsingDataRemover::ClearGearsData(profile_path);
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 0d32964..adb5a1f 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -116,6 +116,8 @@ class BrowserProcessImpl : public BrowserProcess,
virtual void SetIPCLoggingEnabled(bool enable);
#endif
+ virtual MHTMLGenerationManager* mhtml_generation_manager();
+
private:
void ClearLocalState(const FilePath& profile_path);
bool ShouldClearLocalState(FilePath* profile_path);
@@ -292,6 +294,8 @@ class BrowserProcessImpl : public BrowserProcess,
NotificationRegistrar notification_registrar_;
scoped_refptr<PluginDataRemover> plugin_data_remover_;
+ scoped_refptr<MHTMLGenerationManager> mhtml_generation_manager_;
+
// Monitors the state of the 'DisablePluginFinder' policy.
BooleanPrefMember plugin_finder_disabled_pref_;
diff --git a/chrome/browser/download/mhtml_generation_browsertest.cc b/chrome/browser/download/mhtml_generation_browsertest.cc
new file mode 100644
index 0000000..6077b02
--- /dev/null
+++ b/chrome/browser/download/mhtml_generation_browsertest.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_path.h"
+#include "base/scoped_temp_dir.h"
+#include "chrome/browser/download/mhtml_generation_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/testing_browser_process.h"
+#include "chrome/test/ui_test_utils.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "net/test/test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MHTMLGenerationTest : public InProcessBrowserTest {
+ public:
+ MHTMLGenerationTest() {}
+
+ protected:
+ virtual void SetUp() {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ InProcessBrowserTest::SetUp();
+ }
+
+ ScopedTempDir temp_dir_;
+};
+
+// Tests that generating a MHTML does create contents.
+// Note that the actual content of the file is not tested, the purpose of this
+// test is to ensure we were successfull in creating the MHTML data from the
+// renderer.
+IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) {
+ ASSERT_TRUE(test_server()->Start());
+
+ FilePath path(temp_dir_.path());
+ path = path.Append(FILE_PATH_LITERAL("test.mht"));
+
+ ui_test_utils::NavigateToURL(browser(),
+ test_server()->GetURL("files/google/google.html"));
+
+ TabContents* tab = browser()->GetSelectedTabContentsWrapper()->tab_contents();
+ MHTMLGenerationManager* mhtml_generation_manager =
+ g_browser_process->mhtml_generation_manager();
+
+ Source<RenderViewHost> source(tab->render_view_host());
+ ui_test_utils::WindowedNotificationObserverWithDetails<
+ MHTMLGenerationManager::NotificationDetails> signal(
+ NotificationType::MHTML_GENERATED, source);
+ mhtml_generation_manager->GenerateMHTML(tab, path);
+ signal.Wait();
+
+ MHTMLGenerationManager::NotificationDetails details;
+ ASSERT_TRUE(signal.GetDetailsFor(source.map_key(), &details));
+ ASSERT_TRUE(details.success);
+
+ // Make sure the generated file has some contents.
+ int64 file_size;
+ ASSERT_TRUE(file_util::GetFileSize(path, &file_size));
+ EXPECT_GT(file_size, 100);
+}
+
+} // namespace
diff --git a/chrome/browser/download/mhtml_generation_manager.cc b/chrome/browser/download/mhtml_generation_manager.cc
new file mode 100644
index 0000000..ea98155
--- /dev/null
+++ b/chrome/browser/download/mhtml_generation_manager.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/download/mhtml_generation_manager.h"
+
+#include "base/platform_file.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/common/render_messages.h"
+#include "content/browser/renderer_host/render_process_host.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/common/notification_service.h"
+#include "content/common/page_transition_types.h"
+
+MHTMLGenerationManager::Job::Job()
+ : browser_file(base::kInvalidPlatformFileValue),
+ renderer_file(IPC::InvalidPlatformFileForTransit()),
+ process_id(-1),
+ routing_id(-1) {
+}
+
+MHTMLGenerationManager::MHTMLGenerationManager() {
+}
+
+MHTMLGenerationManager::~MHTMLGenerationManager() {
+}
+
+void MHTMLGenerationManager::GenerateMHTML(TabContents* tab_contents,
+ const FilePath& file) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ static int id_counter = 0;
+
+ int job_id = id_counter++;
+ Job job;
+ job.file_path = file;
+ job.process_id = tab_contents->GetRenderProcessHost()->id();
+ job.routing_id = tab_contents->render_view_host()->routing_id();
+ id_to_job_[job_id] = job;
+
+ base::ProcessHandle renderer_process =
+ tab_contents->GetRenderProcessHost()->GetHandle();
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &MHTMLGenerationManager::CreateFile,
+ job_id, file, renderer_process));
+}
+
+void MHTMLGenerationManager::MHTMLGenerated(int job_id, bool success) {
+ JobFinished(job_id, success);
+}
+
+void MHTMLGenerationManager::CreateFile(int job_id, const FilePath& file_path,
+ base::ProcessHandle renderer_process) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ base::PlatformFile browser_file = base::CreatePlatformFile(file_path,
+ base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
+ NULL, NULL);
+ if (browser_file == base::kInvalidPlatformFileValue) {
+ LOG(ERROR) << "Failed to create file to save MHTML at: " <<
+ file_path.value();
+ }
+
+ IPC::PlatformFileForTransit renderer_file =
+ IPC::GetFileHandleForProcess(browser_file, renderer_process, false);
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &MHTMLGenerationManager::FileCreated,
+ job_id, browser_file, renderer_file));
+}
+
+void MHTMLGenerationManager::FileCreated(int job_id,
+ base::PlatformFile browser_file,
+ IPC::PlatformFileForTransit renderer_file) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (browser_file == base::kInvalidPlatformFileValue) {
+ LOG(ERROR) << "Failed to create file";
+ JobFinished(job_id, false);
+ return;
+ }
+
+ IDToJobMap::iterator iter = id_to_job_.find(job_id);
+ if (iter == id_to_job_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ Job& job = iter->second;
+ job.browser_file = browser_file;
+ job.renderer_file = renderer_file;
+
+ TabContents* tab_contents =
+ tab_util::GetTabContentsByID(job.process_id, job.routing_id);
+ if (!tab_contents) {
+ // The tab went away.
+ JobFinished(job_id, false);
+ return;
+ }
+
+ RenderViewHost* host = tab_contents->render_view_host();
+ host->Send(new ViewMsg_SavePageAsMHTML(host->routing_id(), job_id,
+ renderer_file));
+}
+
+void MHTMLGenerationManager::JobFinished(int job_id, bool success) {
+ IDToJobMap::iterator iter = id_to_job_.find(job_id);
+ if (iter == id_to_job_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ Job& job = iter->second;
+
+ TabContents* tab_contents =
+ tab_util::GetTabContentsByID(job.process_id, job.routing_id);
+ if (tab_contents) {
+ NotificationDetails details;
+ details.file_path = job.file_path;
+ details.success = success;
+
+ NotificationService::current()->Notify(
+ NotificationType::MHTML_GENERATED,
+ Source<RenderViewHost>(tab_contents->render_view_host()),
+ Details<NotificationDetails>(&details));
+ }
+
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &MHTMLGenerationManager::CloseFile,
+ job.browser_file));
+
+ id_to_job_.erase(job_id);
+}
+
+void MHTMLGenerationManager::CloseFile(base::PlatformFile file) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ base::ClosePlatformFile(file);
+}
diff --git a/chrome/browser/download/mhtml_generation_manager.h b/chrome/browser/download/mhtml_generation_manager.h
new file mode 100644
index 0000000..8e8557f
--- /dev/null
+++ b/chrome/browser/download/mhtml_generation_manager.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOWNLOAD_MHTML_GENERATION_MANAGER_H_
+#define CHROME_BROWSER_DOWNLOAD_MHTML_GENERATION_MANAGER_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "base/platform_file.h"
+#include "base/process.h"
+#include "content/browser/browser_thread.h"
+#include "ipc/ipc_platform_file.h"
+
+class FilePath;
+class TabContents;
+
+class MHTMLGenerationManager
+ : public base::RefCountedThreadSafe<MHTMLGenerationManager,
+ BrowserThread::DeleteOnUIThread> {
+ public:
+ MHTMLGenerationManager();
+ ~MHTMLGenerationManager();
+
+ // Instructs the render view to generate a MHTML representation of the current
+ // page for |tab_contents|.
+ void GenerateMHTML(TabContents* tab_contents, const FilePath& file);
+
+ // Notification from the renderer that the MHTML generation succeeded/failed.
+ void MHTMLGenerated(int job_id, bool success);
+
+ // The details sent along with the MHTML_GENERATED notification.
+ struct NotificationDetails {
+ FilePath file_path;
+ bool success;
+ };
+
+ private:
+ struct Job{
+ Job();
+
+ FilePath file_path;
+
+ // The handles to file the MHTML is saved to, for the browser and renderer
+ // processes.
+ base::PlatformFile browser_file;
+ IPC::PlatformFileForTransit renderer_file;
+
+ // The IDs mapping to a specific tab.
+ int process_id;
+ int routing_id;
+ };
+
+ // Called on the file thread to create |file|.
+ void CreateFile(int job_id,
+ const FilePath& file,
+ base::ProcessHandle renderer_process);
+
+ // Called on the UI thread when the file that should hold the MHTML data has
+ // been created. This returns a handle to that file for the browser process
+ // and one for the renderer process. These handles are
+ // kInvalidPlatformFileValue if the file could not be opened.
+ void FileCreated(int job_id,
+ base::PlatformFile browser_file,
+ IPC::PlatformFileForTransit renderer_file);
+
+ // Called on the file thread to close the file the MHTML was saved to.
+ void CloseFile(base::PlatformFile file);
+
+ // Called on the UI thread when a job has been processed (successfully or
+ // not). Closes the file and removes the job from the job map.
+ void JobFinished(int job_id, bool success);
+
+ typedef std::map<int, Job> IDToJobMap;
+ IDToJobMap id_to_job_;
+
+ DISALLOW_COPY_AND_ASSIGN(MHTMLGenerationManager);
+};
+
+#endif // CHROME_BROWSER_DOWNLOAD_MHTML_GENERATION_MANAGER_H_
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index d7393aa..15852e2 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
+#include "chrome/browser/download/mhtml_generation_manager.h"
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_message_service.h"
@@ -98,6 +99,7 @@ bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER(ViewHostMsg_CanTriggerClipboardWrite,
OnCanTriggerClipboardWrite)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClearPredictorCache, OnClearPredictorCache)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -137,10 +139,10 @@ void ChromeRenderMessageFilter::OverrideThreadForMessage(
case ExtensionHostMsg_AddListener::ID:
case ExtensionHostMsg_RemoveListener::ID:
case ExtensionHostMsg_CloseChannel::ID:
- *thread = BrowserThread::UI;
- break;
case ViewHostMsg_UpdatedCacheStats::ID:
+ case ViewHostMsg_SavedPageAsMHTML::ID:
*thread = BrowserThread::UI;
+ break;
default:
break;
}
@@ -500,3 +502,10 @@ void ChromeRenderMessageFilter::OnSetCookie(const IPC::Message& message,
AutomationResourceMessageFilter::SetCookiesForUrl(
render_process_id_, message.routing_id(), url, cookie);
}
+
+
+void ChromeRenderMessageFilter::OnSavedPageAsMHTML(int job_id, bool success) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ g_browser_process->mhtml_generation_manager()->
+ MHTMLGenerated(job_id, success);
+}
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h
index 867b824..55590d2 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.h
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.h
@@ -124,6 +124,7 @@ class ChromeRenderMessageFilter : public BrowserMessageFilter {
const GURL& url,
const GURL& first_party_for_cookies,
const std::string& cookie);
+ void OnSavedPageAsMHTML(int job_id, bool success);
int render_process_id_;
ProfileId profile_id_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 93f036e..c9ad4f0 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -857,6 +857,8 @@
'browser/download/drag_download_file.h',
'browser/download/drag_download_util.cc',
'browser/download/drag_download_util.h',
+ 'browser/download/mhtml_generation_manager.cc',
+ 'browser/download/mhtml_generation_manager.h',
'browser/download/save_file.cc',
'browser/download/save_file.h',
'browser/download/save_file_manager.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 85eefc5..8f17d6b 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -120,6 +120,8 @@
'renderer/external_extension.h',
'renderer/localized_error.cc',
'renderer/localized_error.h',
+ 'renderer/mhtml_generator.cc',
+ 'renderer/mhtml_generator.h',
'renderer/page_click_listener.h',
'renderer/page_click_tracker.cc',
'renderer/page_click_tracker.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index c239a79..bfaf920 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2360,6 +2360,7 @@
'browser/content_settings/content_settings_browsertest.cc',
'browser/crash_recovery_browsertest.cc',
'browser/download/download_browsertest.cc',
+ 'browser/download/mhtml_generation_browsertest.cc',
'browser/download/save_page_browsertest.cc',
'browser/extensions/alert_apitest.cc',
'browser/extensions/all_urls_apitest.cc',
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 6b6fe9f..65f07433 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -26,6 +26,7 @@
#include "chrome/common/translate_errors.h"
#include "content/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_platform_file.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h"
#include "ui/gfx/rect.h"
@@ -269,6 +270,11 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetAllowDisplayingInsecureContent,
IPC_MESSAGE_ROUTED1(ViewMsg_SetAllowRunningInsecureContent,
bool /* allowed */)
+// Instructs the renderer to save the current page to MHTML.
+IPC_MESSAGE_ROUTED2(ViewMsg_SavePageAsMHTML,
+ int /* job_id */,
+ IPC::PlatformFileForTransit /* file handle */)
+
//-----------------------------------------------------------------------------
// TabContents messages
// These are messages sent from the renderer to the browser process.
@@ -497,6 +503,11 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_DidBlockDisplayingInsecureContent)
// a secure origin by a security policy. The page may appear incomplete.
IPC_MESSAGE_ROUTED0(ViewHostMsg_DidBlockRunningInsecureContent)
+// Notifies the browser that the page was or was not saved as MHTML.
+IPC_MESSAGE_ROUTED2(ViewHostMsg_SavedPageAsMHTML,
+ int /* job_id*/,
+ bool /* success */)
+
// Suggest results -----------------------------------------------------------
IPC_MESSAGE_ROUTED3(ViewHostMsg_SetSuggestions,
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 78148d3..bd71656 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -44,6 +44,7 @@
#include "chrome/renderer/external_extension.h"
#include "chrome/renderer/loadtimes_extension_bindings.h"
#include "chrome/renderer/localized_error.h"
+#include "chrome/renderer/mhtml_generator.h"
#include "chrome/renderer/net/renderer_net_predictor.h"
#include "chrome/renderer/page_click_tracker.h"
#include "chrome/renderer/page_load_histograms.h"
@@ -197,6 +198,7 @@ void ChromeContentRendererClient::RenderViewCreated(RenderView* render_view) {
new ContentSettingsObserver(render_view);
new DevToolsAgent(render_view);
new ExtensionHelper(render_view, extension_dispatcher_.get());
+ new MHTMLGenerator(render_view);
new PageLoadHistograms(render_view, histogram_snapshots_.get());
new PrintWebViewHelper(render_view);
new SearchBox(render_view);
diff --git a/chrome/renderer/mhtml_generator.cc b/chrome/renderer/mhtml_generator.cc
new file mode 100644
index 0000000..8dfe79a3
--- /dev/null
+++ b/chrome/renderer/mhtml_generator.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/mhtml_generator.h"
+
+#include "base/platform_file.h"
+#include "chrome/common/render_messages.h"
+#include "content/renderer/render_view.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializer.h"
+
+MHTMLGenerator::MHTMLGenerator(RenderView* render_view)
+ : RenderViewObserver(render_view),
+ file_(base::kInvalidPlatformFileValue) {
+}
+
+MHTMLGenerator::~MHTMLGenerator() {
+}
+
+// RenderViewObserver implementation:
+bool MHTMLGenerator::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MHTMLGenerator, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_SavePageAsMHTML, OnSavePageAsMHTML)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void MHTMLGenerator::OnSavePageAsMHTML(
+ int job_id, IPC::PlatformFileForTransit file_for_transit) {
+ base::PlatformFile file =
+ IPC::PlatformFileForTransitToPlatformFile(file_for_transit);
+ file_ = file;
+ bool success = GenerateMHTML();
+ NotifyBrowser(job_id, success);
+}
+
+void MHTMLGenerator::NotifyBrowser(int job_id, bool success) {
+ render_view()->Send(new ViewHostMsg_SavedPageAsMHTML(
+ render_view()->routing_id(), job_id, success));
+ file_ = base::kInvalidPlatformFileValue;
+}
+
+// TODO(jcivelli): write the chunks in deferred tasks to give a chance to the
+// message loop to process other events.
+bool MHTMLGenerator::GenerateMHTML() {
+ WebKit::WebCString mhtml =
+ WebKit::WebPageSerializer::serializeToMHTML(render_view()->webview());
+ const size_t chunk_size = 1024;
+ const char* data = mhtml.data();
+ size_t total_bytes_written = 0;
+ while (total_bytes_written < mhtml.length()) {
+ size_t copy_size =
+ std::min(mhtml.length() - total_bytes_written, chunk_size);
+ int bytes_written = base::WritePlatformFile(file_, total_bytes_written,
+ data + total_bytes_written,
+ copy_size);
+ if (bytes_written == -1)
+ return false;
+ total_bytes_written += bytes_written;
+ }
+ return true;
+}
diff --git a/chrome/renderer/mhtml_generator.h b/chrome/renderer/mhtml_generator.h
new file mode 100644
index 0000000..3520657
--- /dev/null
+++ b/chrome/renderer/mhtml_generator.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_MHTML_GENERATOR_H_
+#define CHROME_RENDERER_MHTML_GENERATOR_H_
+
+#include "content/renderer/render_view_observer.h"
+
+#include "ipc/ipc_platform_file.h"
+
+class MHTMLGenerator : public RenderViewObserver {
+ public:
+ explicit MHTMLGenerator(RenderView* render_view);
+ virtual ~MHTMLGenerator();
+
+ private:
+ // RenderViewObserver implementation:
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ void OnSavePageAsMHTML(int job_id,
+ IPC::PlatformFileForTransit file_for_transit);
+
+ void NotifyBrowser(int job_id, bool success);
+ bool GenerateMHTML();
+
+ base::PlatformFile file_;
+
+ DISALLOW_COPY_AND_ASSIGN(MHTMLGenerator);
+};
+
+#endif // CHROME_RENDERER_MHTML_GENERATOR_H_
diff --git a/chrome/test/testing_browser_process.cc b/chrome/test/testing_browser_process.cc
index 386ffa0..86332ae 100644
--- a/chrome/test/testing_browser_process.cc
+++ b/chrome/test/testing_browser_process.cc
@@ -230,6 +230,10 @@ prerender::PrerenderTracker* TestingBrowserProcess::prerender_tracker() {
return prerender_tracker_.get();
}
+MHTMLGenerationManager* TestingBrowserProcess::mhtml_generation_manager() {
+ return NULL;
+}
+
void TestingBrowserProcess::SetLocalState(PrefService* local_state) {
if (!local_state && notification_ui_manager_.get())
notification_ui_manager_.reset(); // Used local_state_.
diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h
index f2ea1ee..030fea4 100644
--- a/chrome/test/testing_browser_process.h
+++ b/chrome/test/testing_browser_process.h
@@ -21,6 +21,7 @@
class BackgroundModeManager;
class IOThread;
class GoogleURLTracker;
+class MHTMLGenerationManager;
class NotificationUIManager;
class PrefService;
class WatchDogThread;
@@ -113,6 +114,7 @@ class TestingBrowserProcess : public BrowserProcess {
#if defined(IPC_MESSAGE_LOG_ENABLED)
virtual void SetIPCLoggingEnabled(bool enable) {}
#endif
+ virtual MHTMLGenerationManager* mhtml_generation_manager();
// Set the local state for tests. Consumer is responsible for cleaning it up
// afterwards (using ScopedTestingLocalState, for example).