From 373c1069852a133d823ddb417f18beaa840664e8 Mon Sep 17 00:00:00 2001 From: "jam@chromium.org" Date: Thu, 9 Jun 2011 21:11:51 +0000 Subject: Move UtilityProcessHost to content and move the message sending/dispatching to the clients. This allows the content layer to use the class. BUG=76697 Review URL: http://codereview.chromium.org/6995095 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88586 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/utility/chrome_content_utility_client.cc | 349 +++++++++++++++++++++ chrome/utility/chrome_content_utility_client.h | 67 ++++ chrome/utility/utility_main.cc | 64 ---- chrome/utility/utility_thread.cc | 388 ------------------------ chrome/utility/utility_thread.h | 117 ------- 5 files changed, 416 insertions(+), 569 deletions(-) create mode 100644 chrome/utility/chrome_content_utility_client.cc create mode 100644 chrome/utility/chrome_content_utility_client.h delete mode 100644 chrome/utility/utility_main.cc delete mode 100644 chrome/utility/utility_thread.cc delete mode 100644 chrome/utility/utility_thread.h (limited to 'chrome/utility') diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc new file mode 100644 index 0000000..10c577d --- /dev/null +++ b/chrome/utility/chrome_content_utility_client.cc @@ -0,0 +1,349 @@ +// 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/utility/chrome_content_utility_client.h" + +#include "base/base64.h" +#include "base/command_line.h" +#include "base/json/json_reader.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_utility_messages.h" +#include "chrome/common/extensions/extension_l10n_util.h" +#include "chrome/common/extensions/extension_unpacker.h" +#include "chrome/common/extensions/update_manifest.h" +#include "chrome/common/web_resource/web_resource_unpacker.h" +#include "content/utility/utility_thread.h" +#include "printing/backend/print_backend.h" +#include "printing/page_range.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/ui_base_switches.h" +#include "ui/gfx/rect.h" +#include "webkit/glue/image_decoder.h" + +#if defined(OS_WIN) +#include "app/win/iat_patch_function.h" +#include "base/file_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/path_service.h" +#include "base/win/scoped_handle.h" +#include "content/common/content_switches.h" +#include "content/common/sandbox_init_wrapper.h" +#include "printing/emf_win.h" +#endif // defined(OS_WIN) + +namespace chrome { + +ChromeContentUtilityClient::ChromeContentUtilityClient() { +} + +ChromeContentUtilityClient::~ChromeContentUtilityClient() { +} + +void ChromeContentUtilityClient::UtilityThreadStarted() { +#if defined(OS_WIN) + // Load the pdf plugin before the sandbox is turned on. This is for Windows + // only because we need this DLL only on Windows. + FilePath pdf; + if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && + file_util::PathExists(pdf)) { + bool rv = !!LoadLibrary(pdf.value().c_str()); + DCHECK(rv) << "Couldn't load PDF plugin"; + } +#endif + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + std::string lang = command_line->GetSwitchValueASCII(switches::kLang); + if (!lang.empty()) + extension_l10n_util::SetProcessLocale(lang); +} + +bool ChromeContentUtilityClient::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient, message) + IPC_MESSAGE_HANDLER(UtilityMsg_UnpackExtension, OnUnpackExtension) + IPC_MESSAGE_HANDLER(UtilityMsg_UnpackWebResource, OnUnpackWebResource) + IPC_MESSAGE_HANDLER(UtilityMsg_ParseUpdateManifest, OnParseUpdateManifest) + IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImage, OnDecodeImage) + IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImageBase64, OnDecodeImageBase64) + IPC_MESSAGE_HANDLER(UtilityMsg_RenderPDFPagesToMetafile, + OnRenderPDFPagesToMetafile) + IPC_MESSAGE_HANDLER(UtilityMsg_ParseJSON, OnParseJSON) + IPC_MESSAGE_HANDLER(UtilityMsg_GetPrinterCapsAndDefaults, + OnGetPrinterCapsAndDefaults) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +bool ChromeContentUtilityClient::Send(IPC::Message* message) { + return UtilityThread::current()->Send(message); +} + +void ChromeContentUtilityClient::OnUnpackExtension( + const FilePath& extension_path) { + ExtensionUnpacker unpacker(extension_path); + if (unpacker.Run() && unpacker.DumpImagesToFile() && + unpacker.DumpMessageCatalogsToFile()) { + Send(new UtilityHostMsg_UnpackExtension_Succeeded( + *unpacker.parsed_manifest())); + } else { + Send(new UtilityHostMsg_UnpackExtension_Failed(unpacker.error_message())); + } + + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +void ChromeContentUtilityClient::OnUnpackWebResource( + const std::string& resource_data) { + // Parse json data. + // TODO(mrc): Add the possibility of a template that controls parsing, and + // the ability to download and verify images. + WebResourceUnpacker unpacker(resource_data); + if (unpacker.Run()) { + Send(new UtilityHostMsg_UnpackWebResource_Succeeded( + *unpacker.parsed_json())); + } else { + Send(new UtilityHostMsg_UnpackWebResource_Failed( + unpacker.error_message())); + } + + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +void ChromeContentUtilityClient::OnParseUpdateManifest(const std::string& xml) { + UpdateManifest manifest; + if (!manifest.Parse(xml)) { + Send(new UtilityHostMsg_ParseUpdateManifest_Failed(manifest.errors())); + } else { + Send(new UtilityHostMsg_ParseUpdateManifest_Succeeded(manifest.results())); + } + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +void ChromeContentUtilityClient::OnDecodeImage( + const std::vector& encoded_data) { + webkit_glue::ImageDecoder decoder; + const SkBitmap& decoded_image = decoder.Decode(&encoded_data[0], + encoded_data.size()); + if (decoded_image.empty()) { + Send(new UtilityHostMsg_DecodeImage_Failed()); + } else { + Send(new UtilityHostMsg_DecodeImage_Succeeded(decoded_image)); + } + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +void ChromeContentUtilityClient::OnDecodeImageBase64( + const std::string& encoded_string) { + std::string decoded_string; + + if (!base::Base64Decode(encoded_string, &decoded_string)) { + Send(new UtilityHostMsg_DecodeImage_Failed()); + return; + } + + std::vector decoded_vector(decoded_string.size()); + for (size_t i = 0; i < decoded_string.size(); ++i) { + decoded_vector[i] = static_cast(decoded_string[i]); + } + + OnDecodeImage(decoded_vector); +} + +void ChromeContentUtilityClient::OnRenderPDFPagesToMetafile( + base::PlatformFile pdf_file, + const FilePath& metafile_path, + const gfx::Rect& render_area, + int render_dpi, + const std::vector& page_ranges) { + bool succeeded = false; +#if defined(OS_WIN) + int highest_rendered_page_number = 0; + succeeded = RenderPDFToWinMetafile(pdf_file, + metafile_path, + render_area, + render_dpi, + page_ranges, + &highest_rendered_page_number); + if (succeeded) { + Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded( + highest_rendered_page_number)); + } +#endif // defined(OS_WIN) + if (!succeeded) { + Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Failed()); + } + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +#if defined(OS_WIN) +// Exported by pdf.dll +typedef bool (*RenderPDFPageToDCProc)( + const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc, + int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y, + int bounds_width, int bounds_height, bool fit_to_bounds, + bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds); + +typedef bool (*GetPDFDocInfoProc)(const unsigned char* pdf_buffer, + int buffer_size, int* page_count, + double* max_page_width); + +// The 2 below IAT patch functions are almost identical to the code in +// render_process_impl.cc. This is needed to work around specific Windows APIs +// used by the Chrome PDF plugin that will fail in the sandbox. +static app::win::IATPatchFunction g_iat_patch_createdca; +HDC WINAPI UtilityProcess_CreateDCAPatch(LPCSTR driver_name, + LPCSTR device_name, + LPCSTR output, + const DEVMODEA* init_data) { + if (driver_name && + (std::string("DISPLAY") == std::string(driver_name))) + // CreateDC fails behind the sandbox, but not CreateCompatibleDC. + return CreateCompatibleDC(NULL); + + NOTREACHED(); + return CreateDCA(driver_name, device_name, output, init_data); +} + +static app::win::IATPatchFunction g_iat_patch_get_font_data; +DWORD WINAPI UtilityProcess_GetFontDataPatch( + HDC hdc, DWORD table, DWORD offset, LPVOID buffer, DWORD length) { + int rv = GetFontData(hdc, table, offset, buffer, length); + if (rv == GDI_ERROR && hdc) { + HFONT font = static_cast(GetCurrentObject(hdc, OBJ_FONT)); + + LOGFONT logfont; + if (GetObject(font, sizeof(LOGFONT), &logfont)) { + std::vector font_data; + if (UtilityThread::current()->Send( + new UtilityHostMsg_PreCacheFont(logfont))) + rv = GetFontData(hdc, table, offset, buffer, length); + } + } + return rv; +} + +bool ChromeContentUtilityClient::RenderPDFToWinMetafile( + base::PlatformFile pdf_file, + const FilePath& metafile_path, + const gfx::Rect& render_area, + int render_dpi, + const std::vector& page_ranges, + int* highest_rendered_page_number) { + *highest_rendered_page_number = -1; + base::win::ScopedHandle file(pdf_file); + FilePath pdf_module_path; + PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path); + HMODULE pdf_module = GetModuleHandle(pdf_module_path.value().c_str()); + if (!pdf_module) + return false; + + RenderPDFPageToDCProc render_proc = + reinterpret_cast( + GetProcAddress(pdf_module, "RenderPDFPageToDC")); + if (!render_proc) + return false; + + GetPDFDocInfoProc get_info_proc = reinterpret_cast( + GetProcAddress(pdf_module, "GetPDFDocInfo")); + if (!get_info_proc) + return false; + + // Patch the IAT for handling specific APIs known to fail in the sandbox. + if (!g_iat_patch_createdca.is_patched()) + g_iat_patch_createdca.Patch(pdf_module_path.value().c_str(), + "gdi32.dll", "CreateDCA", + UtilityProcess_CreateDCAPatch); + + if (!g_iat_patch_get_font_data.is_patched()) + g_iat_patch_get_font_data.Patch(pdf_module_path.value().c_str(), + "gdi32.dll", "GetFontData", + UtilityProcess_GetFontDataPatch); + + // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle + // and a page range array. That way we don't need to read the entire PDF into + // memory. + DWORD length = ::GetFileSize(file, NULL); + if (length == INVALID_FILE_SIZE) + return false; + + std::vector buffer; + buffer.resize(length); + DWORD bytes_read = 0; + if (!ReadFile(pdf_file, &buffer.front(), length, &bytes_read, NULL) || + (bytes_read != length)) + return false; + + int total_page_count = 0; + if (!get_info_proc(&buffer.front(), buffer.size(), &total_page_count, NULL)) + return false; + + printing::Emf metafile; + metafile.InitToFile(metafile_path); + // Since we created the metafile using the screen DPI (but we actually want + // the PDF DLL to print using the passed in render_dpi, we apply the following + // transformation. + SetGraphicsMode(metafile.context(), GM_ADVANCED); + XFORM xform = {0}; + int screen_dpi = GetDeviceCaps(GetDC(NULL), LOGPIXELSX); + xform.eM11 = xform.eM22 = + static_cast(screen_dpi) / static_cast(render_dpi); + ModifyWorldTransform(metafile.context(), &xform, MWT_LEFTMULTIPLY); + + bool ret = false; + std::vector::const_iterator iter; + for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) { + for (int page_number = iter->from; page_number <= iter->to; ++page_number) { + if (page_number >= total_page_count) + break; + // The underlying metafile is of type Emf and ignores the arguments passed + // to StartPage. + metafile.StartPage(gfx::Size(), gfx::Rect(), 1); + if (render_proc(&buffer.front(), buffer.size(), page_number, + metafile.context(), render_dpi, render_dpi, + render_area.x(), render_area.y(), render_area.width(), + render_area.height(), true, false, true, true)) + if (*highest_rendered_page_number < page_number) + *highest_rendered_page_number = page_number; + ret = true; + metafile.FinishPage(); + } + } + metafile.FinishDocument(); + return ret; +} +#endif // defined(OS_WIN) + + +void ChromeContentUtilityClient::OnParseJSON(const std::string& json) { + int error_code; + std::string error; + Value* value = + base::JSONReader::ReadAndReturnError(json, false, &error_code, &error); + if (value) { + ListValue wrapper; + wrapper.Append(value); + Send(new UtilityHostMsg_ParseJSON_Succeeded(wrapper)); + } else { + Send(new UtilityHostMsg_ParseJSON_Failed(error)); + } + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +void ChromeContentUtilityClient::OnGetPrinterCapsAndDefaults( + const std::string& printer_name) { + scoped_refptr print_backend = + printing::PrintBackend::CreateInstance(NULL); + printing::PrinterCapsAndDefaults printer_info; + if (print_backend->GetPrinterCapsAndDefaults(printer_name, &printer_info)) { + Send(new UtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(printer_name, + printer_info)); + } else { + Send(new UtilityHostMsg_GetPrinterCapsAndDefaults_Failed(printer_name)); + } + UtilityThread::current()->ReleaseProcessIfNeeded(); +} + +} // namespace chrome diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h new file mode 100644 index 0000000..47d6158 --- /dev/null +++ b/chrome/utility/chrome_content_utility_client.h @@ -0,0 +1,67 @@ +// 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_UTILITY_CHROME_CONTENT_UTILITY_CLIENT_H_ +#define CHROME_UTILITY_CHROME_CONTENT_UTILITY_CLIENT_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "base/platform_file.h" +#include "content/utility/content_utility_client.h" + +class FilePath; + +namespace gfx { +class Rect; +} + +namespace printing { +struct PageRange; +} + +namespace chrome { + +class ChromeContentUtilityClient : public content::ContentUtilityClient { + public: + ChromeContentUtilityClient(); + ~ChromeContentUtilityClient(); + + virtual void UtilityThreadStarted() OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + private: + virtual bool Send(IPC::Message* message); + + // IPC message handlers. + void OnUnpackExtension(const FilePath& extension_path); + void OnUnpackWebResource(const std::string& resource_data); + void OnParseUpdateManifest(const std::string& xml); + void OnDecodeImage(const std::vector& encoded_data); + void OnDecodeImageBase64(const std::string& encoded_data); + void OnRenderPDFPagesToMetafile( + base::PlatformFile pdf_file, + const FilePath& metafile_path, + const gfx::Rect& render_area, + int render_dpi, + const std::vector& page_ranges); + void OnParseJSON(const std::string& json); + +#if defined(OS_WIN) + // Helper method for Windows. + // |highest_rendered_page_number| is set to -1 on failure to render any page. + bool RenderPDFToWinMetafile( + base::PlatformFile pdf_file, + const FilePath& metafile_path, + const gfx::Rect& render_area, + int render_dpi, + const std::vector& page_ranges, + int* highest_rendered_page_number); +#endif // defined(OS_WIN) + + void OnGetPrinterCapsAndDefaults(const std::string& printer_name); +}; + +} // namespace chrome + +#endif // CHROME_UTILITY_CHROME_CONTENT_UTILITY_CLIENT_H_ diff --git a/chrome/utility/utility_main.cc b/chrome/utility/utility_main.cc deleted file mode 100644 index d4647f0..0000000 --- a/chrome/utility/utility_main.cc +++ /dev/null @@ -1,64 +0,0 @@ -// 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/command_line.h" -#include "base/message_loop.h" -#include "base/system_monitor/system_monitor.h" -#include "base/threading/platform_thread.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/extensions/extension_l10n_util.h" -#include "chrome/utility/utility_thread.h" -#include "content/common/child_process.h" -#include "content/common/hi_res_timer_manager.h" -#include "content/common/main_function_params.h" -#include "ui/base/ui_base_switches.h" - -#if defined(OS_WIN) -#include "base/file_util.h" -#include "base/path_service.h" -#include "chrome/common/chrome_switches.h" -#include "content/common/sandbox_init_wrapper.h" -#include "sandbox/src/sandbox.h" -#endif // defined(OS_WIN) - -// Mainline routine for running as the utility process. -int UtilityMain(const MainFunctionParams& parameters) { - // The main message loop of the utility process. - MessageLoop main_message_loop; - base::PlatformThread::SetName("CrUtilityMain"); - - base::SystemMonitor system_monitor; - HighResolutionTimerManager hi_res_timer_manager; - - ChildProcess utility_process; - utility_process.set_main_thread(new UtilityThread()); -#if defined(OS_WIN) - // Load the pdf plugin before the sandbox is turned on. This is for Windows - // only because we need this DLL only on Windows. - FilePath pdf; - if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && - file_util::PathExists(pdf)) { - bool rv = !!LoadLibrary(pdf.value().c_str()); - DCHECK(rv) << "Couldn't load PDF plugin"; - } - - bool no_sandbox = parameters.command_line_.HasSwitch(switches::kNoSandbox); - if (!no_sandbox) { - sandbox::TargetServices* target_services = - parameters.sandbox_info_.TargetServices(); - if (!target_services) - return false; - target_services->LowerToken(); - } -#endif - - CommandLine* command_line = CommandLine::ForCurrentProcess(); - std::string lang = command_line->GetSwitchValueASCII(switches::kLang); - if (!lang.empty()) - extension_l10n_util::SetProcessLocale(lang); - - MessageLoop::current()->Run(); - - return 0; -} diff --git a/chrome/utility/utility_thread.cc b/chrome/utility/utility_thread.cc deleted file mode 100644 index 3f13950..0000000 --- a/chrome/utility/utility_thread.cc +++ /dev/null @@ -1,388 +0,0 @@ -// 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/utility/utility_thread.h" - -#include -#include - -#include "base/base64.h" -#include "base/file_path.h" -#include "base/json/json_reader.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/extensions/extension_unpacker.h" -#include "chrome/common/extensions/update_manifest.h" -#include "chrome/common/utility_messages.h" -#include "chrome/common/web_resource/web_resource_unpacker.h" -#include "content/common/child_process.h" -#include "content/common/indexed_db_key.h" -#include "content/common/serialized_script_value.h" -#include "ipc/ipc_message_macros.h" -#include "printing/backend/print_backend.h" -#include "printing/page_range.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h" -#include "ui/gfx/rect.h" -#include "webkit/glue/idb_bindings.h" -#include "webkit/glue/image_decoder.h" - -#if defined(OS_WIN) -#include "app/win/iat_patch_function.h" -#include "base/memory/scoped_ptr.h" -#include "base/path_service.h" -#include "base/win/scoped_handle.h" -#include "printing/emf_win.h" -#endif - -namespace { - -template -void ConvertVector(const SRC& src, DEST* dest) { - dest->reserve(src.size()); - for (typename SRC::const_iterator i = src.begin(); i != src.end(); ++i) - dest->push_back(typename DEST::value_type(*i)); -} - -} // namespace - - -UtilityThread::UtilityThread() - : batch_mode_(false) { - ChildProcess::current()->AddRefProcess(); -} - -UtilityThread::~UtilityThread() { -} - -bool UtilityThread::OnControlMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(UtilityThread, msg) - IPC_MESSAGE_HANDLER(UtilityMsg_UnpackExtension, OnUnpackExtension) - IPC_MESSAGE_HANDLER(UtilityMsg_UnpackWebResource, OnUnpackWebResource) - IPC_MESSAGE_HANDLER(UtilityMsg_ParseUpdateManifest, OnParseUpdateManifest) - IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImage, OnDecodeImage) - IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImageBase64, OnDecodeImageBase64) - IPC_MESSAGE_HANDLER(UtilityMsg_RenderPDFPagesToMetafile, - OnRenderPDFPagesToMetafile) - IPC_MESSAGE_HANDLER(UtilityMsg_IDBKeysFromValuesAndKeyPath, - OnIDBKeysFromValuesAndKeyPath) - IPC_MESSAGE_HANDLER(UtilityMsg_InjectIDBKey, - OnInjectIDBKey) - IPC_MESSAGE_HANDLER(UtilityMsg_ParseJSON, OnParseJSON) - IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Started, OnBatchModeStarted) - IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Finished, OnBatchModeFinished) - IPC_MESSAGE_HANDLER(UtilityMsg_GetPrinterCapsAndDefaults, - OnGetPrinterCapsAndDefaults) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void UtilityThread::OnUnpackExtension(const FilePath& extension_path) { - ExtensionUnpacker unpacker(extension_path); - if (unpacker.Run() && unpacker.DumpImagesToFile() && - unpacker.DumpMessageCatalogsToFile()) { - Send(new UtilityHostMsg_UnpackExtension_Succeeded( - *unpacker.parsed_manifest())); - } else { - Send(new UtilityHostMsg_UnpackExtension_Failed(unpacker.error_message())); - } - - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnUnpackWebResource(const std::string& resource_data) { - // Parse json data. - // TODO(mrc): Add the possibility of a template that controls parsing, and - // the ability to download and verify images. - WebResourceUnpacker unpacker(resource_data); - if (unpacker.Run()) { - Send(new UtilityHostMsg_UnpackWebResource_Succeeded( - *unpacker.parsed_json())); - } else { - Send(new UtilityHostMsg_UnpackWebResource_Failed( - unpacker.error_message())); - } - - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnParseUpdateManifest(const std::string& xml) { - UpdateManifest manifest; - if (!manifest.Parse(xml)) { - Send(new UtilityHostMsg_ParseUpdateManifest_Failed(manifest.errors())); - } else { - Send(new UtilityHostMsg_ParseUpdateManifest_Succeeded(manifest.results())); - } - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnDecodeImage( - const std::vector& encoded_data) { - webkit_glue::ImageDecoder decoder; - const SkBitmap& decoded_image = decoder.Decode(&encoded_data[0], - encoded_data.size()); - if (decoded_image.empty()) { - Send(new UtilityHostMsg_DecodeImage_Failed()); - } else { - Send(new UtilityHostMsg_DecodeImage_Succeeded(decoded_image)); - } - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnDecodeImageBase64( - const std::string& encoded_string) { - std::string decoded_string; - - if (!base::Base64Decode(encoded_string, &decoded_string)) { - Send(new UtilityHostMsg_DecodeImage_Failed()); - return; - } - - std::vector decoded_vector(decoded_string.size()); - for (size_t i = 0; i < decoded_string.size(); ++i) { - decoded_vector[i] = static_cast(decoded_string[i]); - } - - OnDecodeImage(decoded_vector); -} - -void UtilityThread::OnRenderPDFPagesToMetafile( - base::PlatformFile pdf_file, - const FilePath& metafile_path, - const gfx::Rect& render_area, - int render_dpi, - const std::vector& page_ranges) { - bool succeeded = false; -#if defined(OS_WIN) - int highest_rendered_page_number = 0; - succeeded = RenderPDFToWinMetafile(pdf_file, - metafile_path, - render_area, - render_dpi, - page_ranges, - &highest_rendered_page_number); - if (succeeded) { - Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded( - highest_rendered_page_number)); - } -#endif // defined(OS_WIN) - if (!succeeded) { - Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Failed()); - } - ReleaseProcessIfNeeded(); -} - -#if defined(OS_WIN) -// Exported by pdf.dll -typedef bool (*RenderPDFPageToDCProc)( - const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc, - int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y, - int bounds_width, int bounds_height, bool fit_to_bounds, - bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds); - -typedef bool (*GetPDFDocInfoProc)(const unsigned char* pdf_buffer, - int buffer_size, int* page_count, - double* max_page_width); - -// The 2 below IAT patch functions are almost identical to the code in -// render_process_impl.cc. This is needed to work around specific Windows APIs -// used by the Chrome PDF plugin that will fail in the sandbox. -static app::win::IATPatchFunction g_iat_patch_createdca; -HDC WINAPI UtilityProcess_CreateDCAPatch(LPCSTR driver_name, - LPCSTR device_name, - LPCSTR output, - const DEVMODEA* init_data) { - if (driver_name && - (std::string("DISPLAY") == std::string(driver_name))) - // CreateDC fails behind the sandbox, but not CreateCompatibleDC. - return CreateCompatibleDC(NULL); - - NOTREACHED(); - return CreateDCA(driver_name, device_name, output, init_data); -} - -static app::win::IATPatchFunction g_iat_patch_get_font_data; -DWORD WINAPI UtilityProcess_GetFontDataPatch( - HDC hdc, DWORD table, DWORD offset, LPVOID buffer, DWORD length) { - int rv = GetFontData(hdc, table, offset, buffer, length); - if (rv == GDI_ERROR && hdc) { - HFONT font = static_cast(GetCurrentObject(hdc, OBJ_FONT)); - - LOGFONT logfont; - if (GetObject(font, sizeof(LOGFONT), &logfont)) { - std::vector font_data; - if (UtilityThread::current()->Send( - new UtilityHostMsg_PreCacheFont(logfont))) - rv = GetFontData(hdc, table, offset, buffer, length); - } - } - return rv; -} - -bool UtilityThread::RenderPDFToWinMetafile( - base::PlatformFile pdf_file, - const FilePath& metafile_path, - const gfx::Rect& render_area, - int render_dpi, - const std::vector& page_ranges, - int* highest_rendered_page_number) { - *highest_rendered_page_number = -1; - base::win::ScopedHandle file(pdf_file); - FilePath pdf_module_path; - PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path); - HMODULE pdf_module = GetModuleHandle(pdf_module_path.value().c_str()); - if (!pdf_module) - return false; - - RenderPDFPageToDCProc render_proc = - reinterpret_cast( - GetProcAddress(pdf_module, "RenderPDFPageToDC")); - if (!render_proc) - return false; - - GetPDFDocInfoProc get_info_proc = reinterpret_cast( - GetProcAddress(pdf_module, "GetPDFDocInfo")); - if (!get_info_proc) - return false; - - // Patch the IAT for handling specific APIs known to fail in the sandbox. - if (!g_iat_patch_createdca.is_patched()) - g_iat_patch_createdca.Patch(pdf_module_path.value().c_str(), - "gdi32.dll", "CreateDCA", - UtilityProcess_CreateDCAPatch); - - if (!g_iat_patch_get_font_data.is_patched()) - g_iat_patch_get_font_data.Patch(pdf_module_path.value().c_str(), - "gdi32.dll", "GetFontData", - UtilityProcess_GetFontDataPatch); - - // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle - // and a page range array. That way we don't need to read the entire PDF into - // memory. - DWORD length = ::GetFileSize(file, NULL); - if (length == INVALID_FILE_SIZE) - return false; - - std::vector buffer; - buffer.resize(length); - DWORD bytes_read = 0; - if (!ReadFile(pdf_file, &buffer.front(), length, &bytes_read, NULL) || - (bytes_read != length)) - return false; - - int total_page_count = 0; - if (!get_info_proc(&buffer.front(), buffer.size(), &total_page_count, NULL)) - return false; - - printing::Emf metafile; - metafile.InitToFile(metafile_path); - // Since we created the metafile using the screen DPI (but we actually want - // the PDF DLL to print using the passed in render_dpi, we apply the following - // transformation. - SetGraphicsMode(metafile.context(), GM_ADVANCED); - XFORM xform = {0}; - int screen_dpi = GetDeviceCaps(GetDC(NULL), LOGPIXELSX); - xform.eM11 = xform.eM22 = - static_cast(screen_dpi) / static_cast(render_dpi); - ModifyWorldTransform(metafile.context(), &xform, MWT_LEFTMULTIPLY); - - bool ret = false; - std::vector::const_iterator iter; - for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) { - for (int page_number = iter->from; page_number <= iter->to; ++page_number) { - if (page_number >= total_page_count) - break; - // The underlying metafile is of type Emf and ignores the arguments passed - // to StartPage. - metafile.StartPage(gfx::Size(), gfx::Rect(), 1); - if (render_proc(&buffer.front(), buffer.size(), page_number, - metafile.context(), render_dpi, render_dpi, - render_area.x(), render_area.y(), render_area.width(), - render_area.height(), true, false, true, true)) - if (*highest_rendered_page_number < page_number) - *highest_rendered_page_number = page_number; - ret = true; - metafile.FinishPage(); - } - } - metafile.FinishDocument(); - return ret; -} -#endif // defined(OS_WIN) - -void UtilityThread::OnIDBKeysFromValuesAndKeyPath( - int id, - const std::vector& serialized_script_values, - const string16& idb_key_path) { - std::vector web_values; - ConvertVector(serialized_script_values, &web_values); - std::vector web_keys; - bool error = webkit_glue::IDBKeysFromValuesAndKeyPath( - web_values, idb_key_path, &web_keys); - if (error) { - Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed(id)); - return; - } - std::vector keys; - ConvertVector(web_keys, &keys); - Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded(id, keys)); - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnInjectIDBKey(const IndexedDBKey& key, - const SerializedScriptValue& value, - const string16& key_path) { - SerializedScriptValue new_value(webkit_glue::InjectIDBKey(key, value, - key_path)); - Send(new UtilityHostMsg_InjectIDBKey_Finished(new_value)); - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnParseJSON(const std::string& json) { - int error_code; - std::string error; - Value* value = - base::JSONReader::ReadAndReturnError(json, false, &error_code, &error); - if (value) { - ListValue wrapper; - wrapper.Append(value); - Send(new UtilityHostMsg_ParseJSON_Succeeded(wrapper)); - } else { - Send(new UtilityHostMsg_ParseJSON_Failed(error)); - } - ReleaseProcessIfNeeded(); -} - -void UtilityThread::OnBatchModeStarted() { - batch_mode_ = true; -} - -void UtilityThread::OnBatchModeFinished() { - ChildProcess::current()->ReleaseProcess(); -} - -void UtilityThread::OnGetPrinterCapsAndDefaults( - const std::string& printer_name) { - scoped_refptr print_backend = - printing::PrintBackend::CreateInstance(NULL); - printing::PrinterCapsAndDefaults printer_info; - if (print_backend->GetPrinterCapsAndDefaults(printer_name, &printer_info)) { - Send(new UtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(printer_name, - printer_info)); - } else { - Send(new UtilityHostMsg_GetPrinterCapsAndDefaults_Failed(printer_name)); - } - ReleaseProcessIfNeeded(); -} - -void UtilityThread::ReleaseProcessIfNeeded() { - if (!batch_mode_) - ChildProcess::current()->ReleaseProcess(); -} diff --git a/chrome/utility/utility_thread.h b/chrome/utility/utility_thread.h deleted file mode 100644 index ddafaaa..0000000 --- a/chrome/utility/utility_thread.h +++ /dev/null @@ -1,117 +0,0 @@ -// 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_UTILITY_UTILITY_THREAD_H_ -#define CHROME_UTILITY_UTILITY_THREAD_H_ -#pragma once - -#include -#include - -#include "base/basictypes.h" -#include "base/string16.h" -#include "base/platform_file.h" -#include "content/common/child_thread.h" - -class FilePath; -class IndexedDBKey; -class SerializedScriptValue; - -namespace gfx { -class Rect; -} - -namespace IPC { -class Message; -} - -namespace printing { -struct PageRange; -} - -// This class represents the background thread where the utility task runs. -class UtilityThread : public ChildThread { - public: - UtilityThread(); - virtual ~UtilityThread(); - - // Returns the one utility thread. - static UtilityThread* current() { - return static_cast(ChildThread::current()); - } - - private: - // IPC messages - virtual bool OnControlMessageReceived(const IPC::Message& msg); - void OnUnpackExtension(const FilePath& extension_path); - - // IPC messages for web resource service. - void OnUnpackWebResource(const std::string& resource_data); - - // IPC for parsing an extensions auto-update manifest xml file. - void OnParseUpdateManifest(const std::string& xml); - - // IPC for decoding an image. - void OnDecodeImage(const std::vector& encoded_data); - - // IPC for decoding an image which is base64 encoded. - void OnDecodeImageBase64(const std::string& encoded_data); - - // IPC to render a PDF into a platform metafile. - void OnRenderPDFPagesToMetafile( - base::PlatformFile pdf_file, - const FilePath& metafile_path, - const gfx::Rect& render_area, - int render_dpi, - const std::vector& page_ranges); - -#if defined(OS_WIN) - // Helper method for Windows. - // |highest_rendered_page_number| is set to -1 on failure to render any page. - bool RenderPDFToWinMetafile( - base::PlatformFile pdf_file, - const FilePath& metafile_path, - const gfx::Rect& render_area, - int render_dpi, - const std::vector& page_ranges, - int* highest_rendered_page_number); -#endif // defined(OS_WIN) - - // IPC for extracting IDBKeys from SerializedScriptValues, used by IndexedDB. - void OnIDBKeysFromValuesAndKeyPath( - int id, - const std::vector& serialized_script_values, - const string16& idb_key_path); - - // IPC for injecting an IndexedDB key into a SerializedScriptValue. - void OnInjectIDBKey(const IndexedDBKey& key, - const SerializedScriptValue& value, - const string16& key_path); - - // IPC for parsing a string of JSON into a Value. - void OnParseJSON(const std::string& json); - - // IPC to notify we'll be running in batch mode instead of quitting after - // any of the IPCs above, we'll only quit during OnBatchModeFinished(). - void OnBatchModeStarted(); - - // IPC to notify batch mode has finished and we should now quit. - void OnBatchModeFinished(); - - // IPC to get capabilities and defaults for the specified - // printer. Used on Windows to isolate the service process from printer driver - // crashes by executing this in a separate process. This does not run in a - // sandbox. - void OnGetPrinterCapsAndDefaults(const std::string& printer_name); - - // Releases the process if we are not (or no longer) in batch mode. - void ReleaseProcessIfNeeded(); - - // True when we're running in batch mode. - bool batch_mode_; - - DISALLOW_COPY_AND_ASSIGN(UtilityThread); -}; - -#endif // CHROME_UTILITY_UTILITY_THREAD_H_ -- cgit v1.1