Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2262)

Side by Side Diff: content/utility/utility_thread.cc

Issue 6995095: Move UtilityProcessHost to content and move the message sending/dispatching to the clients. This... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/utility/utility_thread.h" 5 #include "content/utility/utility_thread.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <vector>
9 8
10 #include "base/base64.h"
11 #include "base/file_path.h"
12 #include "base/json/json_reader.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/values.h"
16 #include "build/build_config.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "chrome/common/extensions/extension_unpacker.h"
19 #include "chrome/common/extensions/update_manifest.h"
20 #include "chrome/common/utility_messages.h"
21 #include "chrome/common/web_resource/web_resource_unpacker.h"
22 #include "content/common/child_process.h" 9 #include "content/common/child_process.h"
23 #include "content/common/indexed_db_key.h" 10 #include "content/common/indexed_db_key.h"
24 #include "content/common/serialized_script_value.h" 11 #include "content/common/utility_messages.h"
25 #include "ipc/ipc_message_macros.h" 12 #include "content/utility/content_utility_client.h"
26 #include "printing/backend/print_backend.h"
27 #include "printing/page_range.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h" 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h"
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptVa lue.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptVa lue.h"
31 #include "ui/gfx/rect.h"
32 #include "webkit/glue/idb_bindings.h" 15 #include "webkit/glue/idb_bindings.h"
33 #include "webkit/glue/image_decoder.h"
34
35 #if defined(OS_WIN)
36 #include "app/win/iat_patch_function.h"
37 #include "base/memory/scoped_ptr.h"
38 #include "base/path_service.h"
39 #include "base/win/scoped_handle.h"
40 #include "printing/emf_win.h"
41 #endif
42 16
43 namespace { 17 namespace {
44 18
45 template<typename SRC, typename DEST> 19 template<typename SRC, typename DEST>
46 void ConvertVector(const SRC& src, DEST* dest) { 20 void ConvertVector(const SRC& src, DEST* dest) {
47 dest->reserve(src.size()); 21 dest->reserve(src.size());
48 for (typename SRC::const_iterator i = src.begin(); i != src.end(); ++i) 22 for (typename SRC::const_iterator i = src.begin(); i != src.end(); ++i)
49 dest->push_back(typename DEST::value_type(*i)); 23 dest->push_back(typename DEST::value_type(*i));
50 } 24 }
51 25
52 } // namespace 26 } // namespace
53 27
54 28
55 UtilityThread::UtilityThread() 29 UtilityThread::UtilityThread()
56 : batch_mode_(false) { 30 : batch_mode_(false) {
57 ChildProcess::current()->AddRefProcess(); 31 ChildProcess::current()->AddRefProcess();
32 content::GetContentClient()->utility()->UtilityThreadStarted();
58 } 33 }
59 34
60 UtilityThread::~UtilityThread() { 35 UtilityThread::~UtilityThread() {
61 } 36 }
62 37
63 bool UtilityThread::OnControlMessageReceived(const IPC::Message& msg) { 38 bool UtilityThread::OnControlMessageReceived(const IPC::Message& msg) {
39 if (content::GetContentClient()->utility()->OnMessageReceived(msg))
40 return true;
41
64 bool handled = true; 42 bool handled = true;
65 IPC_BEGIN_MESSAGE_MAP(UtilityThread, msg) 43 IPC_BEGIN_MESSAGE_MAP(UtilityThread, msg)
66 IPC_MESSAGE_HANDLER(UtilityMsg_UnpackExtension, OnUnpackExtension)
67 IPC_MESSAGE_HANDLER(UtilityMsg_UnpackWebResource, OnUnpackWebResource)
68 IPC_MESSAGE_HANDLER(UtilityMsg_ParseUpdateManifest, OnParseUpdateManifest)
69 IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImage, OnDecodeImage)
70 IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImageBase64, OnDecodeImageBase64)
71 IPC_MESSAGE_HANDLER(UtilityMsg_RenderPDFPagesToMetafile,
72 OnRenderPDFPagesToMetafile)
73 IPC_MESSAGE_HANDLER(UtilityMsg_IDBKeysFromValuesAndKeyPath, 44 IPC_MESSAGE_HANDLER(UtilityMsg_IDBKeysFromValuesAndKeyPath,
74 OnIDBKeysFromValuesAndKeyPath) 45 OnIDBKeysFromValuesAndKeyPath)
75 IPC_MESSAGE_HANDLER(UtilityMsg_InjectIDBKey, 46 IPC_MESSAGE_HANDLER(UtilityMsg_InjectIDBKey, OnInjectIDBKey)
76 OnInjectIDBKey)
77 IPC_MESSAGE_HANDLER(UtilityMsg_ParseJSON, OnParseJSON)
78 IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Started, OnBatchModeStarted) 47 IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Started, OnBatchModeStarted)
79 IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Finished, OnBatchModeFinished) 48 IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Finished, OnBatchModeFinished)
80 IPC_MESSAGE_HANDLER(UtilityMsg_GetPrinterCapsAndDefaults,
81 OnGetPrinterCapsAndDefaults)
82 IPC_MESSAGE_UNHANDLED(handled = false) 49 IPC_MESSAGE_UNHANDLED(handled = false)
83 IPC_END_MESSAGE_MAP() 50 IPC_END_MESSAGE_MAP()
84 return handled; 51 return handled;
85 } 52 }
86 53
87 void UtilityThread::OnUnpackExtension(const FilePath& extension_path) {
88 ExtensionUnpacker unpacker(extension_path);
89 if (unpacker.Run() && unpacker.DumpImagesToFile() &&
90 unpacker.DumpMessageCatalogsToFile()) {
91 Send(new UtilityHostMsg_UnpackExtension_Succeeded(
92 *unpacker.parsed_manifest()));
93 } else {
94 Send(new UtilityHostMsg_UnpackExtension_Failed(unpacker.error_message()));
95 }
96
97 ReleaseProcessIfNeeded();
98 }
99
100 void UtilityThread::OnUnpackWebResource(const std::string& resource_data) {
101 // Parse json data.
102 // TODO(mrc): Add the possibility of a template that controls parsing, and
103 // the ability to download and verify images.
104 WebResourceUnpacker unpacker(resource_data);
105 if (unpacker.Run()) {
106 Send(new UtilityHostMsg_UnpackWebResource_Succeeded(
107 *unpacker.parsed_json()));
108 } else {
109 Send(new UtilityHostMsg_UnpackWebResource_Failed(
110 unpacker.error_message()));
111 }
112
113 ReleaseProcessIfNeeded();
114 }
115
116 void UtilityThread::OnParseUpdateManifest(const std::string& xml) {
117 UpdateManifest manifest;
118 if (!manifest.Parse(xml)) {
119 Send(new UtilityHostMsg_ParseUpdateManifest_Failed(manifest.errors()));
120 } else {
121 Send(new UtilityHostMsg_ParseUpdateManifest_Succeeded(manifest.results()));
122 }
123 ReleaseProcessIfNeeded();
124 }
125
126 void UtilityThread::OnDecodeImage(
127 const std::vector<unsigned char>& encoded_data) {
128 webkit_glue::ImageDecoder decoder;
129 const SkBitmap& decoded_image = decoder.Decode(&encoded_data[0],
130 encoded_data.size());
131 if (decoded_image.empty()) {
132 Send(new UtilityHostMsg_DecodeImage_Failed());
133 } else {
134 Send(new UtilityHostMsg_DecodeImage_Succeeded(decoded_image));
135 }
136 ReleaseProcessIfNeeded();
137 }
138
139 void UtilityThread::OnDecodeImageBase64(
140 const std::string& encoded_string) {
141 std::string decoded_string;
142
143 if (!base::Base64Decode(encoded_string, &decoded_string)) {
144 Send(new UtilityHostMsg_DecodeImage_Failed());
145 return;
146 }
147
148 std::vector<unsigned char> decoded_vector(decoded_string.size());
149 for (size_t i = 0; i < decoded_string.size(); ++i) {
150 decoded_vector[i] = static_cast<unsigned char>(decoded_string[i]);
151 }
152
153 OnDecodeImage(decoded_vector);
154 }
155
156 void UtilityThread::OnRenderPDFPagesToMetafile(
157 base::PlatformFile pdf_file,
158 const FilePath& metafile_path,
159 const gfx::Rect& render_area,
160 int render_dpi,
161 const std::vector<printing::PageRange>& page_ranges) {
162 bool succeeded = false;
163 #if defined(OS_WIN)
164 int highest_rendered_page_number = 0;
165 succeeded = RenderPDFToWinMetafile(pdf_file,
166 metafile_path,
167 render_area,
168 render_dpi,
169 page_ranges,
170 &highest_rendered_page_number);
171 if (succeeded) {
172 Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Succeeded(
173 highest_rendered_page_number));
174 }
175 #endif // defined(OS_WIN)
176 if (!succeeded) {
177 Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Failed());
178 }
179 ReleaseProcessIfNeeded();
180 }
181
182 #if defined(OS_WIN)
183 // Exported by pdf.dll
184 typedef bool (*RenderPDFPageToDCProc)(
185 const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
186 int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
187 int bounds_width, int bounds_height, bool fit_to_bounds,
188 bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds);
189
190 typedef bool (*GetPDFDocInfoProc)(const unsigned char* pdf_buffer,
191 int buffer_size, int* page_count,
192 double* max_page_width);
193
194 // The 2 below IAT patch functions are almost identical to the code in
195 // render_process_impl.cc. This is needed to work around specific Windows APIs
196 // used by the Chrome PDF plugin that will fail in the sandbox.
197 static app::win::IATPatchFunction g_iat_patch_createdca;
198 HDC WINAPI UtilityProcess_CreateDCAPatch(LPCSTR driver_name,
199 LPCSTR device_name,
200 LPCSTR output,
201 const DEVMODEA* init_data) {
202 if (driver_name &&
203 (std::string("DISPLAY") == std::string(driver_name)))
204 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
205 return CreateCompatibleDC(NULL);
206
207 NOTREACHED();
208 return CreateDCA(driver_name, device_name, output, init_data);
209 }
210
211 static app::win::IATPatchFunction g_iat_patch_get_font_data;
212 DWORD WINAPI UtilityProcess_GetFontDataPatch(
213 HDC hdc, DWORD table, DWORD offset, LPVOID buffer, DWORD length) {
214 int rv = GetFontData(hdc, table, offset, buffer, length);
215 if (rv == GDI_ERROR && hdc) {
216 HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));
217
218 LOGFONT logfont;
219 if (GetObject(font, sizeof(LOGFONT), &logfont)) {
220 std::vector<char> font_data;
221 if (UtilityThread::current()->Send(
222 new UtilityHostMsg_PreCacheFont(logfont)))
223 rv = GetFontData(hdc, table, offset, buffer, length);
224 }
225 }
226 return rv;
227 }
228
229 bool UtilityThread::RenderPDFToWinMetafile(
230 base::PlatformFile pdf_file,
231 const FilePath& metafile_path,
232 const gfx::Rect& render_area,
233 int render_dpi,
234 const std::vector<printing::PageRange>& page_ranges,
235 int* highest_rendered_page_number) {
236 *highest_rendered_page_number = -1;
237 base::win::ScopedHandle file(pdf_file);
238 FilePath pdf_module_path;
239 PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path);
240 HMODULE pdf_module = GetModuleHandle(pdf_module_path.value().c_str());
241 if (!pdf_module)
242 return false;
243
244 RenderPDFPageToDCProc render_proc =
245 reinterpret_cast<RenderPDFPageToDCProc>(
246 GetProcAddress(pdf_module, "RenderPDFPageToDC"));
247 if (!render_proc)
248 return false;
249
250 GetPDFDocInfoProc get_info_proc = reinterpret_cast<GetPDFDocInfoProc>(
251 GetProcAddress(pdf_module, "GetPDFDocInfo"));
252 if (!get_info_proc)
253 return false;
254
255 // Patch the IAT for handling specific APIs known to fail in the sandbox.
256 if (!g_iat_patch_createdca.is_patched())
257 g_iat_patch_createdca.Patch(pdf_module_path.value().c_str(),
258 "gdi32.dll", "CreateDCA",
259 UtilityProcess_CreateDCAPatch);
260
261 if (!g_iat_patch_get_font_data.is_patched())
262 g_iat_patch_get_font_data.Patch(pdf_module_path.value().c_str(),
263 "gdi32.dll", "GetFontData",
264 UtilityProcess_GetFontDataPatch);
265
266 // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle
267 // and a page range array. That way we don't need to read the entire PDF into
268 // memory.
269 DWORD length = ::GetFileSize(file, NULL);
270 if (length == INVALID_FILE_SIZE)
271 return false;
272
273 std::vector<uint8> buffer;
274 buffer.resize(length);
275 DWORD bytes_read = 0;
276 if (!ReadFile(pdf_file, &buffer.front(), length, &bytes_read, NULL) ||
277 (bytes_read != length))
278 return false;
279
280 int total_page_count = 0;
281 if (!get_info_proc(&buffer.front(), buffer.size(), &total_page_count, NULL))
282 return false;
283
284 printing::Emf metafile;
285 metafile.InitToFile(metafile_path);
286 // Since we created the metafile using the screen DPI (but we actually want
287 // the PDF DLL to print using the passed in render_dpi, we apply the following
288 // transformation.
289 SetGraphicsMode(metafile.context(), GM_ADVANCED);
290 XFORM xform = {0};
291 int screen_dpi = GetDeviceCaps(GetDC(NULL), LOGPIXELSX);
292 xform.eM11 = xform.eM22 =
293 static_cast<float>(screen_dpi) / static_cast<float>(render_dpi);
294 ModifyWorldTransform(metafile.context(), &xform, MWT_LEFTMULTIPLY);
295
296 bool ret = false;
297 std::vector<printing::PageRange>::const_iterator iter;
298 for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) {
299 for (int page_number = iter->from; page_number <= iter->to; ++page_number) {
300 if (page_number >= total_page_count)
301 break;
302 // The underlying metafile is of type Emf and ignores the arguments passed
303 // to StartPage.
304 metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
305 if (render_proc(&buffer.front(), buffer.size(), page_number,
306 metafile.context(), render_dpi, render_dpi,
307 render_area.x(), render_area.y(), render_area.width(),
308 render_area.height(), true, false, true, true))
309 if (*highest_rendered_page_number < page_number)
310 *highest_rendered_page_number = page_number;
311 ret = true;
312 metafile.FinishPage();
313 }
314 }
315 metafile.FinishDocument();
316 return ret;
317 }
318 #endif // defined(OS_WIN)
319
320 void UtilityThread::OnIDBKeysFromValuesAndKeyPath( 54 void UtilityThread::OnIDBKeysFromValuesAndKeyPath(
321 int id, 55 int id,
322 const std::vector<SerializedScriptValue>& serialized_script_values, 56 const std::vector<SerializedScriptValue>& serialized_script_values,
323 const string16& idb_key_path) { 57 const string16& idb_key_path) {
324 std::vector<WebKit::WebSerializedScriptValue> web_values; 58 std::vector<WebKit::WebSerializedScriptValue> web_values;
325 ConvertVector(serialized_script_values, &web_values); 59 ConvertVector(serialized_script_values, &web_values);
326 std::vector<WebKit::WebIDBKey> web_keys; 60 std::vector<WebKit::WebIDBKey> web_keys;
327 bool error = webkit_glue::IDBKeysFromValuesAndKeyPath( 61 bool error = webkit_glue::IDBKeysFromValuesAndKeyPath(
328 web_values, idb_key_path, &web_keys); 62 web_values, idb_key_path, &web_keys);
329 if (error) { 63 if (error) {
330 Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed(id)); 64 Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed(id));
331 return; 65 return;
332 } 66 }
333 std::vector<IndexedDBKey> keys; 67 std::vector<IndexedDBKey> keys;
334 ConvertVector(web_keys, &keys); 68 ConvertVector(web_keys, &keys);
335 Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded(id, keys)); 69 Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded(id, keys));
336 ReleaseProcessIfNeeded(); 70 ReleaseProcessIfNeeded();
337 } 71 }
338 72
339 void UtilityThread::OnInjectIDBKey(const IndexedDBKey& key, 73 void UtilityThread::OnInjectIDBKey(const IndexedDBKey& key,
340 const SerializedScriptValue& value, 74 const SerializedScriptValue& value,
341 const string16& key_path) { 75 const string16& key_path) {
342 SerializedScriptValue new_value(webkit_glue::InjectIDBKey(key, value, 76 SerializedScriptValue new_value(webkit_glue::InjectIDBKey(key, value,
343 key_path)); 77 key_path));
344 Send(new UtilityHostMsg_InjectIDBKey_Finished(new_value)); 78 Send(new UtilityHostMsg_InjectIDBKey_Finished(new_value));
345 ReleaseProcessIfNeeded(); 79 ReleaseProcessIfNeeded();
346 } 80 }
347 81
348 void UtilityThread::OnParseJSON(const std::string& json) {
349 int error_code;
350 std::string error;
351 Value* value =
352 base::JSONReader::ReadAndReturnError(json, false, &error_code, &error);
353 if (value) {
354 ListValue wrapper;
355 wrapper.Append(value);
356 Send(new UtilityHostMsg_ParseJSON_Succeeded(wrapper));
357 } else {
358 Send(new UtilityHostMsg_ParseJSON_Failed(error));
359 }
360 ReleaseProcessIfNeeded();
361 }
362
363 void UtilityThread::OnBatchModeStarted() { 82 void UtilityThread::OnBatchModeStarted() {
364 batch_mode_ = true; 83 batch_mode_ = true;
365 } 84 }
366 85
367 void UtilityThread::OnBatchModeFinished() { 86 void UtilityThread::OnBatchModeFinished() {
368 ChildProcess::current()->ReleaseProcess(); 87 ChildProcess::current()->ReleaseProcess();
369 } 88 }
370 89
371 void UtilityThread::OnGetPrinterCapsAndDefaults(
372 const std::string& printer_name) {
373 scoped_refptr<printing::PrintBackend> print_backend =
374 printing::PrintBackend::CreateInstance(NULL);
375 printing::PrinterCapsAndDefaults printer_info;
376 if (print_backend->GetPrinterCapsAndDefaults(printer_name, &printer_info)) {
377 Send(new UtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(printer_name,
378 printer_info));
379 } else {
380 Send(new UtilityHostMsg_GetPrinterCapsAndDefaults_Failed(printer_name));
381 }
382 ReleaseProcessIfNeeded();
383 }
384
385 void UtilityThread::ReleaseProcessIfNeeded() { 90 void UtilityThread::ReleaseProcessIfNeeded() {
386 if (!batch_mode_) 91 if (!batch_mode_)
387 ChildProcess::current()->ReleaseProcess(); 92 ChildProcess::current()->ReleaseProcess();
388 } 93 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698