Use Histogram algorithm to calculate DNS timeout.
[chromium-blink-merge.git] / chrome / utility / chrome_content_utility_client.cc
blob967352b6ca42ebae43d52b012e844d01f1134af7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/utility/chrome_content_utility_client.h"
7 #include "base/base64.h"
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/json/json_reader.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "chrome/common/chrome_utility_messages.h"
14 #include "chrome/common/extensions/chrome_manifest_handlers.h"
15 #include "chrome/common/extensions/extension.h"
16 #include "chrome/common/extensions/extension_l10n_util.h"
17 #include "chrome/common/extensions/manifest.h"
18 #include "chrome/common/extensions/permissions/chrome_api_permissions.h"
19 #include "chrome/common/extensions/update_manifest.h"
20 #include "chrome/common/safe_browsing/zip_analyzer.h"
21 #include "chrome/utility/extensions/unpacker.h"
22 #include "chrome/utility/profile_import_handler.h"
23 #include "chrome/utility/web_resource_unpacker.h"
24 #include "content/public/child/image_decoder_utils.h"
25 #include "content/public/utility/utility_thread.h"
26 #include "printing/page_range.h"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "third_party/zlib/google/zip.h"
29 #include "ui/base/ui_base_switches.h"
30 #include "ui/gfx/codec/jpeg_codec.h"
31 #include "ui/gfx/rect.h"
32 #include "ui/gfx/size.h"
34 #if defined(OS_WIN)
35 #include "base/file_util.h"
36 #include "base/path_service.h"
37 #include "base/win/iat_patch_function.h"
38 #include "base/win/scoped_handle.h"
39 #include "chrome/common/chrome_paths.h"
40 #include "chrome/utility/itunes_pref_parser_win.h"
41 #include "printing/emf_win.h"
42 #include "ui/gfx/gdi_util.h"
43 #endif // defined(OS_WIN)
45 #if defined(OS_WIN) || defined(OS_MACOSX)
46 #include "chrome/common/media_galleries/picasa_types.h"
47 #include "chrome/utility/itunes_library_parser.h"
48 #include "chrome/utility/media_galleries/picasa_album_table_reader.h"
49 #endif // defined(OS_WIN) || defined(OS_MACOSX)
51 #if defined(ENABLE_PRINTING)
52 #include "chrome/common/child_process_logging.h"
53 #include "printing/backend/print_backend.h"
54 #endif
56 #if defined(ENABLE_MDNS)
57 #include "chrome/utility/local_discovery/service_discovery_message_handler.h"
58 #endif // ENABLE_MDNS
60 namespace chrome {
62 namespace {
64 bool Send(IPC::Message* message) {
65 return content::UtilityThread::Get()->Send(message);
68 void ReleaseProcessIfNeeded() {
69 content::UtilityThread::Get()->ReleaseProcessIfNeeded();
72 } // namespace
74 ChromeContentUtilityClient::ChromeContentUtilityClient() {
75 #if !defined(OS_ANDROID)
76 handlers_.push_back(new ProfileImportHandler());
77 #endif // OS_ANDROID
79 #if defined(ENABLE_MDNS)
80 handlers_.push_back(new local_discovery::ServiceDiscoveryMessageHandler());
81 #endif // ENABLE_MDNS
84 ChromeContentUtilityClient::~ChromeContentUtilityClient() {
87 void ChromeContentUtilityClient::UtilityThreadStarted() {
88 #if defined(OS_WIN)
89 // Load the pdf plugin before the sandbox is turned on. This is for Windows
90 // only because we need this DLL only on Windows.
91 base::FilePath pdf;
92 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&
93 base::PathExists(pdf)) {
94 bool rv = !!LoadLibrary(pdf.value().c_str());
95 DCHECK(rv) << "Couldn't load PDF plugin";
97 #endif
99 CommandLine* command_line = CommandLine::ForCurrentProcess();
100 std::string lang = command_line->GetSwitchValueASCII(switches::kLang);
101 if (!lang.empty())
102 extension_l10n_util::SetProcessLocale(lang);
105 bool ChromeContentUtilityClient::OnMessageReceived(
106 const IPC::Message& message) {
107 bool handled = true;
108 IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient, message)
109 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackExtension, OnUnpackExtension)
110 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackWebResource,
111 OnUnpackWebResource)
112 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseUpdateManifest,
113 OnParseUpdateManifest)
114 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImage, OnDecodeImage)
115 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImageBase64, OnDecodeImageBase64)
116 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafile,
117 OnRenderPDFPagesToMetafile)
118 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RobustJPEGDecodeImage,
119 OnRobustJPEGDecodeImage)
120 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseJSON, OnParseJSON)
121 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterCapsAndDefaults,
122 OnGetPrinterCapsAndDefaults)
123 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing)
124 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
125 OnAnalyzeZipFileForDownloadProtection)
127 #if defined(OS_CHROMEOS)
128 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile, OnCreateZipFile)
129 #endif // defined(OS_CHROMEOS)
131 #if defined(OS_WIN)
132 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesPrefXml,
133 OnParseITunesPrefXml)
134 #endif // defined(OS_WIN)
136 #if defined(OS_WIN) || defined(OS_MACOSX)
137 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesLibraryXmlFile,
138 OnParseITunesLibraryXmlFile)
139 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParsePicasaPMPDatabase,
140 OnParsePicasaPMPDatabase)
141 #endif // defined(OS_WIN) || defined(OS_MACOSX)
143 IPC_MESSAGE_UNHANDLED(handled = false)
144 IPC_END_MESSAGE_MAP()
146 for (Handlers::iterator it = handlers_.begin();
147 !handled && it != handlers_.end(); ++it) {
148 handled = (*it)->OnMessageReceived(message);
151 return handled;
154 void ChromeContentUtilityClient::OnUnpackExtension(
155 const base::FilePath& extension_path,
156 const std::string& extension_id,
157 int location,
158 int creation_flags) {
159 CHECK_GT(location, extensions::Manifest::INVALID_LOCATION);
160 CHECK_LT(location, extensions::Manifest::NUM_LOCATIONS);
161 extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
162 extensions::ChromeAPIPermissions());
163 extensions::RegisterChromeManifestHandlers();
164 extensions::Unpacker unpacker(
165 extension_path,
166 extension_id,
167 static_cast<extensions::Manifest::Location>(location),
168 creation_flags);
169 if (unpacker.Run() && unpacker.DumpImagesToFile() &&
170 unpacker.DumpMessageCatalogsToFile()) {
171 Send(new ChromeUtilityHostMsg_UnpackExtension_Succeeded(
172 *unpacker.parsed_manifest()));
173 } else {
174 Send(new ChromeUtilityHostMsg_UnpackExtension_Failed(
175 unpacker.error_message()));
178 ReleaseProcessIfNeeded();
181 void ChromeContentUtilityClient::OnUnpackWebResource(
182 const std::string& resource_data) {
183 // Parse json data.
184 // TODO(mrc): Add the possibility of a template that controls parsing, and
185 // the ability to download and verify images.
186 WebResourceUnpacker unpacker(resource_data);
187 if (unpacker.Run()) {
188 Send(new ChromeUtilityHostMsg_UnpackWebResource_Succeeded(
189 *unpacker.parsed_json()));
190 } else {
191 Send(new ChromeUtilityHostMsg_UnpackWebResource_Failed(
192 unpacker.error_message()));
195 ReleaseProcessIfNeeded();
198 void ChromeContentUtilityClient::OnParseUpdateManifest(const std::string& xml) {
199 UpdateManifest manifest;
200 if (!manifest.Parse(xml)) {
201 Send(new ChromeUtilityHostMsg_ParseUpdateManifest_Failed(
202 manifest.errors()));
203 } else {
204 Send(new ChromeUtilityHostMsg_ParseUpdateManifest_Succeeded(
205 manifest.results()));
207 ReleaseProcessIfNeeded();
210 void ChromeContentUtilityClient::OnDecodeImage(
211 const std::vector<unsigned char>& encoded_data) {
212 const SkBitmap& decoded_image = content::DecodeImage(&encoded_data[0],
213 gfx::Size(),
214 encoded_data.size());
215 if (decoded_image.empty()) {
216 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
217 } else {
218 Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(decoded_image));
220 ReleaseProcessIfNeeded();
223 void ChromeContentUtilityClient::OnDecodeImageBase64(
224 const std::string& encoded_string) {
225 std::string decoded_string;
227 if (!base::Base64Decode(encoded_string, &decoded_string)) {
228 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
229 return;
232 std::vector<unsigned char> decoded_vector(decoded_string.size());
233 for (size_t i = 0; i < decoded_string.size(); ++i) {
234 decoded_vector[i] = static_cast<unsigned char>(decoded_string[i]);
237 OnDecodeImage(decoded_vector);
240 #if defined(OS_CHROMEOS)
241 void ChromeContentUtilityClient::OnCreateZipFile(
242 const base::FilePath& src_dir,
243 const std::vector<base::FilePath>& src_relative_paths,
244 const base::FileDescriptor& dest_fd) {
245 bool succeeded = true;
247 // Check sanity of source relative paths. Reject if path is absolute or
248 // contains any attempt to reference a parent directory ("../" tricks).
249 for (std::vector<base::FilePath>::const_iterator iter =
250 src_relative_paths.begin(); iter != src_relative_paths.end();
251 ++iter) {
252 if (iter->IsAbsolute() || iter->ReferencesParent()) {
253 succeeded = false;
254 break;
258 if (succeeded)
259 succeeded = zip::ZipFiles(src_dir, src_relative_paths, dest_fd.fd);
261 if (succeeded)
262 Send(new ChromeUtilityHostMsg_CreateZipFile_Succeeded());
263 else
264 Send(new ChromeUtilityHostMsg_CreateZipFile_Failed());
265 ReleaseProcessIfNeeded();
267 #endif // defined(OS_CHROMEOS)
269 void ChromeContentUtilityClient::OnRenderPDFPagesToMetafile(
270 base::PlatformFile pdf_file,
271 const base::FilePath& metafile_path,
272 const printing::PdfRenderSettings& pdf_render_settings,
273 const std::vector<printing::PageRange>& page_ranges) {
274 bool succeeded = false;
275 #if defined(OS_WIN)
276 int highest_rendered_page_number = 0;
277 double scale_factor = 1.0;
278 succeeded = RenderPDFToWinMetafile(pdf_file,
279 metafile_path,
280 pdf_render_settings.area(),
281 pdf_render_settings.dpi(),
282 pdf_render_settings.autorotate(),
283 page_ranges,
284 &highest_rendered_page_number,
285 &scale_factor);
286 if (succeeded) {
287 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Succeeded(
288 highest_rendered_page_number, scale_factor));
290 #endif // defined(OS_WIN)
291 if (!succeeded) {
292 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed());
294 ReleaseProcessIfNeeded();
297 #if defined(OS_WIN)
298 // Exported by pdf.dll
299 typedef bool (*RenderPDFPageToDCProc)(
300 const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
301 int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
302 int bounds_width, int bounds_height, bool fit_to_bounds,
303 bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds,
304 bool autorotate);
306 typedef bool (*GetPDFDocInfoProc)(const unsigned char* pdf_buffer,
307 int buffer_size, int* page_count,
308 double* max_page_width);
310 // The 2 below IAT patch functions are almost identical to the code in
311 // render_process_impl.cc. This is needed to work around specific Windows APIs
312 // used by the Chrome PDF plugin that will fail in the sandbox.
313 static base::win::IATPatchFunction g_iat_patch_createdca;
314 HDC WINAPI UtilityProcess_CreateDCAPatch(LPCSTR driver_name,
315 LPCSTR device_name,
316 LPCSTR output,
317 const DEVMODEA* init_data) {
318 if (driver_name &&
319 (std::string("DISPLAY") == std::string(driver_name)))
320 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
321 return CreateCompatibleDC(NULL);
323 NOTREACHED();
324 return CreateDCA(driver_name, device_name, output, init_data);
327 static base::win::IATPatchFunction g_iat_patch_get_font_data;
328 DWORD WINAPI UtilityProcess_GetFontDataPatch(
329 HDC hdc, DWORD table, DWORD offset, LPVOID buffer, DWORD length) {
330 int rv = GetFontData(hdc, table, offset, buffer, length);
331 if (rv == GDI_ERROR && hdc) {
332 HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));
334 LOGFONT logfont;
335 if (GetObject(font, sizeof(LOGFONT), &logfont)) {
336 std::vector<char> font_data;
337 content::UtilityThread::Get()->PreCacheFont(logfont);
338 rv = GetFontData(hdc, table, offset, buffer, length);
339 content::UtilityThread::Get()->ReleaseCachedFonts();
342 return rv;
345 bool ChromeContentUtilityClient::RenderPDFToWinMetafile(
346 base::PlatformFile pdf_file,
347 const base::FilePath& metafile_path,
348 const gfx::Rect& render_area,
349 int render_dpi,
350 bool autorotate,
351 const std::vector<printing::PageRange>& page_ranges,
352 int* highest_rendered_page_number,
353 double* scale_factor) {
354 *highest_rendered_page_number = -1;
355 *scale_factor = 1.0;
356 base::win::ScopedHandle file(pdf_file);
357 base::FilePath pdf_module_path;
358 PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path);
359 HMODULE pdf_module = GetModuleHandle(pdf_module_path.value().c_str());
360 if (!pdf_module)
361 return false;
363 RenderPDFPageToDCProc render_proc =
364 reinterpret_cast<RenderPDFPageToDCProc>(
365 GetProcAddress(pdf_module, "RenderPDFPageToDC"));
366 if (!render_proc)
367 return false;
369 GetPDFDocInfoProc get_info_proc = reinterpret_cast<GetPDFDocInfoProc>(
370 GetProcAddress(pdf_module, "GetPDFDocInfo"));
371 if (!get_info_proc)
372 return false;
374 // Patch the IAT for handling specific APIs known to fail in the sandbox.
375 if (!g_iat_patch_createdca.is_patched())
376 g_iat_patch_createdca.Patch(pdf_module_path.value().c_str(),
377 "gdi32.dll", "CreateDCA",
378 UtilityProcess_CreateDCAPatch);
380 if (!g_iat_patch_get_font_data.is_patched())
381 g_iat_patch_get_font_data.Patch(pdf_module_path.value().c_str(),
382 "gdi32.dll", "GetFontData",
383 UtilityProcess_GetFontDataPatch);
385 // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle
386 // and a page range array. That way we don't need to read the entire PDF into
387 // memory.
388 DWORD length = ::GetFileSize(file, NULL);
389 if (length == INVALID_FILE_SIZE)
390 return false;
392 std::vector<uint8> buffer;
393 buffer.resize(length);
394 DWORD bytes_read = 0;
395 if (!ReadFile(pdf_file, &buffer.front(), length, &bytes_read, NULL) ||
396 (bytes_read != length))
397 return false;
399 int total_page_count = 0;
400 if (!get_info_proc(&buffer.front(), buffer.size(), &total_page_count, NULL))
401 return false;
403 printing::Emf metafile;
404 metafile.InitToFile(metafile_path);
405 // We need to scale down DC to fit an entire page into DC available area.
406 // Current metafile is based on screen DC and have current screen size.
407 // Writing outside of those boundaries will result in the cut-off output.
408 // On metafiles (this is the case here), scaling down will still record
409 // original coordinates and we'll be able to print in full resolution.
410 // Before playback we'll need to counter the scaling up that will happen
411 // in the service (print_system_win.cc).
412 *scale_factor = gfx::CalculatePageScale(metafile.context(),
413 render_area.right(),
414 render_area.bottom());
415 gfx::ScaleDC(metafile.context(), *scale_factor);
417 bool ret = false;
418 std::vector<printing::PageRange>::const_iterator iter;
419 for (iter = page_ranges.begin(); iter != page_ranges.end(); ++iter) {
420 for (int page_number = iter->from; page_number <= iter->to; ++page_number) {
421 if (page_number >= total_page_count)
422 break;
423 // The underlying metafile is of type Emf and ignores the arguments passed
424 // to StartPage.
425 metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
426 if (render_proc(&buffer.front(), buffer.size(), page_number,
427 metafile.context(), render_dpi, render_dpi,
428 render_area.x(), render_area.y(), render_area.width(),
429 render_area.height(), true, false, true, true,
430 autorotate))
431 if (*highest_rendered_page_number < page_number)
432 *highest_rendered_page_number = page_number;
433 ret = true;
434 metafile.FinishPage();
437 metafile.FinishDocument();
438 return ret;
440 #endif // defined(OS_WIN)
442 void ChromeContentUtilityClient::OnRobustJPEGDecodeImage(
443 const std::vector<unsigned char>& encoded_data) {
444 // Our robust jpeg decoding is using IJG libjpeg.
445 if (gfx::JPEGCodec::JpegLibraryVariant() == gfx::JPEGCodec::IJG_LIBJPEG) {
446 scoped_ptr<SkBitmap> decoded_image(gfx::JPEGCodec::Decode(
447 &encoded_data[0], encoded_data.size()));
448 if (!decoded_image.get() || decoded_image->empty()) {
449 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
450 } else {
451 Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(*decoded_image));
453 } else {
454 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
456 ReleaseProcessIfNeeded();
459 void ChromeContentUtilityClient::OnParseJSON(const std::string& json) {
460 int error_code;
461 std::string error;
462 base::Value* value = base::JSONReader::ReadAndReturnError(
463 json, base::JSON_PARSE_RFC, &error_code, &error);
464 if (value) {
465 base::ListValue wrapper;
466 wrapper.Append(value);
467 Send(new ChromeUtilityHostMsg_ParseJSON_Succeeded(wrapper));
468 } else {
469 Send(new ChromeUtilityHostMsg_ParseJSON_Failed(error));
471 ReleaseProcessIfNeeded();
474 void ChromeContentUtilityClient::OnGetPrinterCapsAndDefaults(
475 const std::string& printer_name) {
476 #if defined(ENABLE_PRINTING)
477 scoped_refptr<printing::PrintBackend> print_backend =
478 printing::PrintBackend::CreateInstance(NULL);
479 printing::PrinterCapsAndDefaults printer_info;
481 child_process_logging::ScopedPrinterInfoSetter prn_info(
482 print_backend->GetPrinterDriverInfo(printer_name));
484 if (print_backend->GetPrinterCapsAndDefaults(printer_name, &printer_info)) {
485 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(
486 printer_name, printer_info));
487 } else // NOLINT
488 #endif
490 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed(
491 printer_name));
493 ReleaseProcessIfNeeded();
496 void ChromeContentUtilityClient::OnStartupPing() {
497 Send(new ChromeUtilityHostMsg_ProcessStarted);
498 // Don't release the process, we assume further messages are on the way.
501 void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
502 IPC::PlatformFileForTransit zip_file) {
503 safe_browsing::zip_analyzer::Results results;
504 safe_browsing::zip_analyzer::AnalyzeZipFile(
505 IPC::PlatformFileForTransitToPlatformFile(zip_file), &results);
506 Send(new ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished(
507 results));
508 ReleaseProcessIfNeeded();
511 #if defined(OS_WIN)
512 void ChromeContentUtilityClient::OnParseITunesPrefXml(
513 const std::string& itunes_xml_data) {
514 base::FilePath library_path(
515 itunes::FindLibraryLocationInPrefXml(itunes_xml_data));
516 Send(new ChromeUtilityHostMsg_GotITunesDirectory(library_path));
517 ReleaseProcessIfNeeded();
519 #endif // defined(OS_WIN)
521 #if defined(OS_WIN) || defined(OS_MACOSX)
522 void ChromeContentUtilityClient::OnParseITunesLibraryXmlFile(
523 IPC::PlatformFileForTransit itunes_library_file) {
524 itunes::ITunesLibraryParser parser;
525 base::PlatformFile file =
526 IPC::PlatformFileForTransitToPlatformFile(itunes_library_file);
527 bool result = parser.Parse(
528 itunes::ITunesLibraryParser::ReadITunesLibraryXmlFile(file));
529 Send(new ChromeUtilityHostMsg_GotITunesLibrary(result, parser.library()));
530 ReleaseProcessIfNeeded();
533 void ChromeContentUtilityClient::OnParsePicasaPMPDatabase(
534 const picasa::AlbumTableFilesForTransit& album_table_files) {
535 picasa::AlbumTableFiles files;
536 files.indicator_file = IPC::PlatformFileForTransitToPlatformFile(
537 album_table_files.indicator_file);
538 files.category_file = IPC::PlatformFileForTransitToPlatformFile(
539 album_table_files.category_file);
540 files.date_file = IPC::PlatformFileForTransitToPlatformFile(
541 album_table_files.date_file);
542 files.filename_file = IPC::PlatformFileForTransitToPlatformFile(
543 album_table_files.filename_file);
544 files.name_file = IPC::PlatformFileForTransitToPlatformFile(
545 album_table_files.name_file);
546 files.token_file = IPC::PlatformFileForTransitToPlatformFile(
547 album_table_files.token_file);
548 files.uid_file = IPC::PlatformFileForTransitToPlatformFile(
549 album_table_files.uid_file);
551 picasa::PicasaAlbumTableReader reader(files);
552 bool parse_success = reader.Init();
553 Send(new ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished(
554 parse_success,
555 reader.albums(),
556 reader.folders()));
557 ReleaseProcessIfNeeded();
559 #endif // defined(OS_WIN) || defined(OS_MACOSX)
561 } // namespace chrome