diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-16 00:29:22 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-16 00:29:22 +0000 |
commit | fbea02332ae95f590c8a84019b582fa35e788a7c (patch) | |
tree | eeff857a083663f3d5556fcff304b5fd05e32eb2 /chrome | |
parent | 0018067c7afbdf516d1845b35a3a245d96910f66 (diff) | |
download | chromium_src-fbea02332ae95f590c8a84019b582fa35e788a7c.zip chromium_src-fbea02332ae95f590c8a84019b582fa35e788a7c.tar.gz chromium_src-fbea02332ae95f590c8a84019b582fa35e788a7c.tar.bz2 |
Linux: print page to file rather than using shared memory to send it to the browser.
BUG=9847
adapted from patch by <minyu.huang [at] gmail>
Review URL: http://codereview.chromium.org/203062
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26308 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.cc | 29 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter.h | 10 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_message_filter_gtk.cc | 63 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 10 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.cc | 48 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.h | 4 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_linux.cc | 96 |
7 files changed, 121 insertions, 139 deletions
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 095131f..4a5de3a 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -339,8 +339,10 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection) #endif #if defined(OS_LINUX) - IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateShareMemory, - OnAllocateShareMemory) + IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateTempFileForPrinting, + OnAllocateTempFileForPrinting) + IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten, + OnTempFileForPrintingWritten) #endif IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy) @@ -706,29 +708,6 @@ void ResourceMessageFilter::OnDuplicateSection( } #endif -#if defined(OS_LINUX) -void ResourceMessageFilter::OnAllocateShareMemory( - size_t buffer_size, - base::SharedMemoryHandle* browser_handle) { - // We don't want to allocate a super big chunk of memory. - // 32MB should be large enough for printing on Linux. - if (buffer_size > 32 * 1024 * 1024) { - *browser_handle = base::SharedMemory::NULLHandle(); - NOTREACHED() << "Buffer too large: " << buffer_size; - return; - } - base::SharedMemory shared_buf; - shared_buf.Create(L"", false, false, buffer_size); - if (shared_buf.Map(buffer_size)) { - shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle); - } else { - *browser_handle = base::SharedMemory::NULLHandle(); - NOTREACHED() << "Cannot map buffer"; - return; - } -} -#endif - void ResourceMessageFilter::OnResourceTypeStats( const WebCache::ResourceTypeStats& stats) { HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB", diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 897e373..dceaa3d 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -52,6 +52,9 @@ struct WebScreenInfo; } struct ViewHostMsg_ScriptedPrint_Params; +#if defined(OS_LINUX) +struct ViewHostMsg_DidPrintPage_Params; +#endif // This class filters out incoming IPC messages for network requests and // processes them on the IPC thread. As a result, network requests are not @@ -204,10 +207,11 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, #endif #if defined(OS_LINUX) - // Used to ask the browser allocate a block of shared memory for the renderer + // Used to ask the browser allocate a temporary file for the renderer // to fill in resulting PDF in renderer. - void OnAllocateShareMemory(size_t buffer_size, - base::SharedMemoryHandle* browser_handle); + void OnAllocateTempFileForPrinting(base::FileDescriptor* temp_file_fd, + int* fd_in_browser); + void OnTempFileForPrintingWritten(int fd_in_browser); #endif void OnResourceTypeStats(const WebKit::WebCache::ResourceTypeStats& stats); diff --git a/chrome/browser/renderer_host/resource_message_filter_gtk.cc b/chrome/browser/renderer_host/resource_message_filter_gtk.cc index 1dd964d..8533cac 100644 --- a/chrome/browser/renderer_host/resource_message_filter_gtk.cc +++ b/chrome/browser/renderer_host/resource_message_filter_gtk.cc @@ -4,11 +4,20 @@ #include "chrome/browser/renderer_host/resource_message_filter.h" +#include <fcntl.h> +#include <map> + +#include "app/l10n_util.h" #include "base/clipboard.h" +#include "base/file_util.h" #include "base/gfx/gtk_native_view_id_manager.h" +#include "base/path_service.h" +#include "base/singleton.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/render_messages.h" #include "chrome/common/x11_util.h" +#include "grit/generated_resources.h" #include "webkit/api/public/WebScreenInfo.h" #include "webkit/api/public/x11/WebScreenInfoFactory.h" @@ -16,6 +25,16 @@ using WebKit::WebScreenInfo; using WebKit::WebScreenInfoFactory; +namespace { + +typedef std::map<int, FilePath> FdMap; + +struct PrintingFileDescriptorMap { + FdMap map; +}; + +} // namespace + // We get null window_ids passed into the two functions below; please see // http://crbug.com/9060 for more details. @@ -210,3 +229,47 @@ void ResourceMessageFilter::OnClipboardReadHTML(Clipboard::Buffer buffer, this, &ResourceMessageFilter::DoOnClipboardReadHTML, buffer, reply_msg)); } + +// Called on the IO thread. +void ResourceMessageFilter::OnAllocateTempFileForPrinting( + base::FileDescriptor* temp_file_fd, int* fd_in_browser) { + temp_file_fd->fd = *fd_in_browser = -1; + + FilePath path; + if (!file_util::CreateTemporaryFile(&path)) + return; + + int fd = open(path.value().c_str(), O_WRONLY); + if (fd < 0) + return; + + // We need to remember the FilePath of the temporary file because we need + // it when we want to rename/move it, and more importantly, to print it + // when we print by using gtk_print_job_set_source_file(). + FdMap* map = &Singleton<PrintingFileDescriptorMap>::get()->map; + FdMap::iterator it = map->find(fd); + if (it != map->end()) { + NOTREACHED() << "The file descriptor is in use. fd=" << fd; + return; + } + + (*map)[fd] = path; + temp_file_fd->fd = *fd_in_browser = fd; + temp_file_fd->auto_close = true; +} + +// Called on the IO thread. +void ResourceMessageFilter::OnTempFileForPrintingWritten(int fd_in_browser) { + FdMap* map = &Singleton<PrintingFileDescriptorMap>::get()->map; + FdMap::iterator it = map->find(fd_in_browser); + if (it == map->end()) { + NOTREACHED() << "Got a file descriptor that we didn't pass to the " + "renderer: " << fd_in_browser; + return; + } + + // TODO(estade): print it. + + // Erase the entry in the map. + map->erase(it); +} diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 806c0e5..2916c17 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1396,11 +1396,13 @@ IPC_BEGIN_MESSAGES(ViewHost) #endif #if defined(OS_LINUX) - // Asks the browser create a block of shared memory for the renderer to fill + // Asks the browser create a temporary file for the renderer to fill // in resulting NativeMetafile in printing. - IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_AllocateShareMemory, - size_t /* buffer size */, - base::SharedMemoryHandle /* browser handle */) + IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_AllocateTempFileForPrinting, + base::FileDescriptor /* temp file fd */, + int /* fd in browser*/) + IPC_MESSAGE_CONTROL1(ViewHostMsg_TempFileForPrintingWritten, + int /* fd in browser */) #endif // Provide the browser process with information about the WebCore resource diff --git a/chrome/common/temp_scaffolding_stubs.cc b/chrome/common/temp_scaffolding_stubs.cc index 9b1ed6d..76d2d60 100644 --- a/chrome/common/temp_scaffolding_stubs.cc +++ b/chrome/common/temp_scaffolding_stubs.cc @@ -13,12 +13,8 @@ #include "chrome/browser/rlz/rlz.h" #if defined(OS_LINUX) -#include "base/path_service.h" #include "chrome/browser/dock_info.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/chrome_paths.h" #include "chrome/common/render_messages.h" -#include "printing/native_metafile.h" #endif #if defined(OS_MACOSX) @@ -326,47 +322,3 @@ void BookmarkManager::Show(Profile* profile) { #endif -//------------------------------------------------------------------------------ - -#if defined(OS_LINUX) -// TODO(myhuang): This is a quick hack for testing purpose. We should implement -// PrintViewManager and other related classes later on Linux. -namespace printing { - -void PrintViewManager::DidPrintPage( - const ViewHostMsg_DidPrintPage_Params& params) { - base::SharedMemory shared_buf(params.metafile_data_handle, true); - if (!shared_buf.Map(params.data_size)) { - NOTREACHED() << "couldn't map"; - owner_.Stop(); - return; - } - - // The only format we can use now is PDF since Cairo needs to create a - // temporary file for a PostScript surface. We do not allow disk I/O in the - // renderer. - scoped_ptr<NativeMetafile> metafile( - new NativeMetafile(printing::NativeMetafile::PDF)); - - if (!metafile->Init(shared_buf.memory(), params.data_size)) { - NOTREACHED() << "Invalid metafile header"; - shared_buf.Unmap(); - owner_.Stop(); - return; - } - - // Save the PDF file to default download location. - // NOTE: Existing file will be overwritten. - FilePath default_save_path; - if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &default_save_path)) { - NOTREACHED(); - } - FilePath save_filename = - default_save_path.Append(FilePath("chromium_printing_test.pdf")); - metafile->SaveTo(save_filename); - shared_buf.Unmap(); -} - -} // namespace printing - -#endif diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h index 7b01f31..6f186ff 100644 --- a/chrome/common/temp_scaffolding_stubs.h +++ b/chrome/common/temp_scaffolding_stubs.h @@ -67,13 +67,9 @@ class PrintViewManager : public RenderViewHostDelegate::Printing { NOTIMPLEMENTED(); } -#if defined(OS_LINUX) - virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params); -#else virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) { NOTIMPLEMENTED(); } -#endif private: TabContents& owner_; diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc index 211eb6f..b8e0ca2 100644 --- a/chrome/renderer/print_web_view_helper_linux.cc +++ b/chrome/renderer/print_web_view_helper_linux.cc @@ -4,6 +4,7 @@ #include "chrome/renderer/print_web_view_helper.h" +#include "base/file_descriptor_posix.h" #include "base/logging.h" #include "chrome/common/render_messages.h" #include "printing/native_metafile.h" @@ -53,64 +54,49 @@ void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params, // TODO(myhuang): Send ViewHostMsg_DidGetPrintedPagesCount. - if (page_count) { - // We only can use PDF in the renderer because Cairo needs to create a - // temporary file for a PostScript surface. - printing::NativeMetafile metafile(printing::NativeMetafile::PDF); - metafile.Init(); - - ViewMsg_PrintPage_Params print_page_params; - print_page_params.params = params.params; - const gfx::Size& canvas_size = prep_frame_view.GetPrintCanvasSize(); - if (params.pages.empty()) { - for (int i = 0; i < page_count; ++i) { - print_page_params.page_number = i; - PrintPage(print_page_params, canvas_size, frame, &metafile); - } - } else { - for (size_t i = 0; i < params.pages.size(); ++i) { - print_page_params.page_number = params.pages[i]; - PrintPage(print_page_params, canvas_size, frame, &metafile); - } - } + if (page_count == 0) + return; - metafile.Close(); - - // Get the size of the resulting metafile. - unsigned int buf_size = metafile.GetDataSize(); - DCHECK_GT(buf_size, 0u); - - ViewHostMsg_DidPrintPage_Params did_page_params; - - // Ask the browser create the shared memory for us. - if (Send(new ViewHostMsg_AllocateShareMemory( - routing_id(), - buf_size, - &did_page_params.metafile_data_handle))) { - if (did_page_params.metafile_data_handle.fd > -1) { - base::SharedMemory shared_buf(did_page_params.metafile_data_handle, - false); - if (shared_buf.Map(buf_size)) { - if (metafile.GetData(shared_buf.memory(), buf_size)) { - // FIXME(myhuang): This is for testing purpose at this moment. - // We use this message to pass the resulting PDF to the browser, - // and the browser will save this PDF on the disk. - did_page_params.data_size = buf_size; - Send(new ViewHostMsg_DidPrintPage(routing_id(), did_page_params)); - } else { - NOTREACHED() << "GetData() failed"; - } - shared_buf.Unmap(); - } else { - NOTREACHED() << "Buffer mapping failed"; - } - } else { - NOTREACHED() << "Buffer allocation failed"; - } - } else { - NOTREACHED() << "Buffer allocation failed"; + // We only can use PDF in the renderer because Cairo needs to create a + // temporary file for a PostScript surface. + printing::NativeMetafile metafile(printing::NativeMetafile::PDF); + metafile.Init(); + + ViewMsg_PrintPage_Params print_page_params; + print_page_params.params = params.params; + const gfx::Size& canvas_size = prep_frame_view.GetPrintCanvasSize(); + if (params.pages.empty()) { + for (int i = 0; i < page_count; ++i) { + print_page_params.page_number = i; + PrintPage(print_page_params, canvas_size, frame, &metafile); + } + } else { + for (size_t i = 0; i < params.pages.size(); ++i) { + print_page_params.page_number = params.pages[i]; + PrintPage(print_page_params, canvas_size, frame, &metafile); } } + + metafile.Close(); + + // Get the size of the resulting metafile. + unsigned int buf_size = metafile.GetDataSize(); + DCHECK_GT(buf_size, 0u); + + base::FileDescriptor fd; + int fd_in_browser = -1; + + // Ask the browser to open a file for us. + if (!Send(new ViewHostMsg_AllocateTempFileForPrinting(&fd, + &fd_in_browser))) { + return; + } + + if (!metafile.SaveTo(fd)) + return; + + // Tell the browser we've finished writing the file. + Send(new ViewHostMsg_TempFileForPrintingWritten(fd_in_browser)); } void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, |