diff options
author | jcivelli@chromium.org <jcivelli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-14 19:35:10 +0000 |
---|---|---|
committer | jcivelli@chromium.org <jcivelli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-14 19:35:10 +0000 |
commit | e7f009da9894df2b8e48aa21578aa4e5ecd7a765 (patch) | |
tree | 0ca8f38fa2a3531d6f6ef373faac0b1f84eb7369 /chrome/browser | |
parent | 286d5d1b43741c2a4b18d4dde38430e5d06097fa (diff) | |
download | chromium_src-e7f009da9894df2b8e48aa21578aa4e5ecd7a765.zip chromium_src-e7f009da9894df2b8e48aa21578aa4e5ecd7a765.tar.gz chromium_src-e7f009da9894df2b8e48aa21578aa4e5ecd7a765.tar.bz2 |
Hooking MHTML generation to the browser.
This CL adds a class that can be used to generate MHTML for the current
page of a tab.
It is not yet surfaced in the UI.
BUG=None
TEST=Run the browser tests.
Review URL: http://codereview.chromium.org/7044095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89047 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser_process.h | 3 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.cc | 8 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.h | 4 | ||||
-rw-r--r-- | chrome/browser/download/mhtml_generation_browsertest.cc | 66 | ||||
-rw-r--r-- | chrome/browser/download/mhtml_generation_manager.cc | 136 | ||||
-rw-r--r-- | chrome/browser/download/mhtml_generation_manager.h | 81 | ||||
-rw-r--r-- | chrome/browser/renderer_host/chrome_render_message_filter.cc | 13 | ||||
-rw-r--r-- | chrome/browser/renderer_host/chrome_render_message_filter.h | 1 |
8 files changed, 310 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_; |