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"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/json/json_reader.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/path_service.h"
15 #include "base/scoped_native_library.h"
16 #include "base/time/time.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "chrome/common/chrome_utility_messages.h"
19 #include "chrome/common/extensions/chrome_extensions_client.h"
20 #include "chrome/common/extensions/extension_l10n_util.h"
21 #include "chrome/common/extensions/update_manifest.h"
22 #include "chrome/common/safe_browsing/zip_analyzer.h"
23 #include "chrome/utility/chrome_content_utility_ipc_whitelist.h"
24 #include "chrome/utility/cloud_print/bitmap_image.h"
25 #include "chrome/utility/cloud_print/pwg_encoder.h"
26 #include "chrome/utility/extensions/unpacker.h"
27 #include "chrome/utility/image_writer/image_writer_handler.h"
28 #include "chrome/utility/profile_import_handler.h"
29 #include "chrome/utility/web_resource_unpacker.h"
30 #include "content/public/child/image_decoder_utils.h"
31 #include "content/public/common/content_paths.h"
32 #include "content/public/common/content_switches.h"
33 #include "content/public/utility/utility_thread.h"
34 #include "courgette/courgette.h"
35 #include "courgette/third_party/bsdiff.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/common/manifest.h"
38 #include "media/base/media.h"
39 #include "media/base/media_file_checker.h"
40 #include "printing/page_range.h"
41 #include "printing/pdf_render_settings.h"
42 #include "third_party/skia/include/core/SkBitmap.h"
43 #include "third_party/zlib/google/zip.h"
44 #include "ui/base/ui_base_switches.h"
45 #include "ui/gfx/codec/jpeg_codec.h"
46 #include "ui/gfx/rect.h"
47 #include "ui/gfx/size.h"
50 #include "base/win/iat_patch_function.h"
51 #include "base/win/scoped_handle.h"
52 #include "chrome/common/extensions/api/networking_private/networking_private_crypto.h"
53 #include "chrome/utility/media_galleries/itunes_pref_parser_win.h"
54 #include "components/wifi/wifi_service.h"
55 #include "printing/emf_win.h"
56 #include "ui/gfx/gdi_util.h"
57 #endif // defined(OS_WIN)
59 #if defined(OS_MACOSX)
60 #include "chrome/utility/media_galleries/iphoto_library_parser.h"
61 #endif // defined(OS_MACOSX)
63 #if defined(OS_WIN) || defined(OS_MACOSX)
64 #include "chrome/utility/media_galleries/iapps_xml_utils.h"
65 #include "chrome/utility/media_galleries/itunes_library_parser.h"
66 #include "chrome/utility/media_galleries/picasa_album_table_reader.h"
67 #include "chrome/utility/media_galleries/picasa_albums_indexer.h"
68 #endif // defined(OS_WIN) || defined(OS_MACOSX)
70 #if !defined(OS_ANDROID) && !defined(OS_IOS)
71 #include "chrome/utility/media_galleries/ipc_data_source.h"
72 #include "chrome/utility/media_galleries/media_metadata_parser.h"
73 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
75 #if defined(ENABLE_FULL_PRINTING)
76 #include "chrome/common/crash_keys.h"
77 #include "printing/backend/print_backend.h"
80 #if defined(ENABLE_MDNS)
81 #include "chrome/utility/local_discovery/service_discovery_message_handler.h"
88 bool Send(IPC::Message
* message
) {
89 return content::UtilityThread::Get()->Send(message
);
92 void ReleaseProcessIfNeeded() {
93 content::UtilityThread::Get()->ReleaseProcessIfNeeded();
96 class PdfFunctionsBase
{
98 PdfFunctionsBase() : render_pdf_to_bitmap_func_(NULL
),
99 get_pdf_doc_info_func_(NULL
) {}
102 base::FilePath pdf_module_path
;
103 if (!PathService::Get(chrome::FILE_PDF_PLUGIN
, &pdf_module_path
) ||
104 !base::PathExists(pdf_module_path
)) {
108 pdf_lib_
.Reset(base::LoadNativeLibrary(pdf_module_path
, NULL
));
109 if (!pdf_lib_
.is_valid()) {
110 LOG(WARNING
) << "Couldn't load PDF plugin";
114 render_pdf_to_bitmap_func_
=
115 reinterpret_cast<RenderPDFPageToBitmapProc
>(
116 pdf_lib_
.GetFunctionPointer("RenderPDFPageToBitmap"));
117 LOG_IF(WARNING
, !render_pdf_to_bitmap_func_
) <<
118 "Missing RenderPDFPageToBitmap";
120 get_pdf_doc_info_func_
=
121 reinterpret_cast<GetPDFDocInfoProc
>(
122 pdf_lib_
.GetFunctionPointer("GetPDFDocInfo"));
123 LOG_IF(WARNING
, !get_pdf_doc_info_func_
) << "Missing GetPDFDocInfo";
125 if (!render_pdf_to_bitmap_func_
|| !get_pdf_doc_info_func_
||
126 !PlatformInit(pdf_module_path
, pdf_lib_
)) {
133 bool IsValid() const {
134 return pdf_lib_
.is_valid();
138 pdf_lib_
.Reset(NULL
);
141 bool RenderPDFPageToBitmap(const void* pdf_buffer
,
150 if (!render_pdf_to_bitmap_func_
)
152 return render_pdf_to_bitmap_func_(pdf_buffer
, pdf_buffer_size
, page_number
,
153 bitmap_buffer
, bitmap_width
,
154 bitmap_height
, dpi_x
, dpi_y
, autorotate
);
157 bool GetPDFDocInfo(const void* pdf_buffer
,
160 double* max_page_width
) {
161 if (!get_pdf_doc_info_func_
)
163 return get_pdf_doc_info_func_(pdf_buffer
, buffer_size
, page_count
,
168 virtual bool PlatformInit(
169 const base::FilePath
& pdf_module_path
,
170 const base::ScopedNativeLibrary
& pdf_lib
) {
175 // Exported by PDF plugin.
176 typedef bool (*RenderPDFPageToBitmapProc
)(const void* pdf_buffer
,
185 typedef bool (*GetPDFDocInfoProc
)(const void* pdf_buffer
,
186 int buffer_size
, int* page_count
,
187 double* max_page_width
);
189 RenderPDFPageToBitmapProc render_pdf_to_bitmap_func_
;
190 GetPDFDocInfoProc get_pdf_doc_info_func_
;
192 base::ScopedNativeLibrary pdf_lib_
;
193 DISALLOW_COPY_AND_ASSIGN(PdfFunctionsBase
);
197 // The 2 below IAT patch functions are almost identical to the code in
198 // render_process_impl.cc. This is needed to work around specific Windows APIs
199 // used by the Chrome PDF plugin that will fail in the sandbox.
200 static base::win::IATPatchFunction g_iat_patch_createdca
;
201 HDC WINAPI
UtilityProcess_CreateDCAPatch(LPCSTR driver_name
,
204 const DEVMODEA
* init_data
) {
205 if (driver_name
&& (std::string("DISPLAY") == driver_name
)) {
206 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
207 return CreateCompatibleDC(NULL
);
211 return CreateDCA(driver_name
, device_name
, output
, init_data
);
214 static base::win::IATPatchFunction g_iat_patch_get_font_data
;
215 DWORD WINAPI
UtilityProcess_GetFontDataPatch(
216 HDC hdc
, DWORD table
, DWORD offset
, LPVOID buffer
, DWORD length
) {
217 int rv
= GetFontData(hdc
, table
, offset
, buffer
, length
);
218 if (rv
== GDI_ERROR
&& hdc
) {
219 HFONT font
= static_cast<HFONT
>(GetCurrentObject(hdc
, OBJ_FONT
));
222 if (GetObject(font
, sizeof(LOGFONT
), &logfont
)) {
223 content::UtilityThread::Get()->PreCacheFont(logfont
);
224 rv
= GetFontData(hdc
, table
, offset
, buffer
, length
);
225 content::UtilityThread::Get()->ReleaseCachedFonts();
231 class PdfFunctionsWin
: public PdfFunctionsBase
{
233 PdfFunctionsWin() : render_pdf_to_dc_func_(NULL
) {
237 const base::FilePath
& pdf_module_path
,
238 const base::ScopedNativeLibrary
& pdf_lib
) OVERRIDE
{
239 // Patch the IAT for handling specific APIs known to fail in the sandbox.
240 if (!g_iat_patch_createdca
.is_patched()) {
241 g_iat_patch_createdca
.Patch(pdf_module_path
.value().c_str(),
242 "gdi32.dll", "CreateDCA",
243 UtilityProcess_CreateDCAPatch
);
246 if (!g_iat_patch_get_font_data
.is_patched()) {
247 g_iat_patch_get_font_data
.Patch(pdf_module_path
.value().c_str(),
248 "gdi32.dll", "GetFontData",
249 UtilityProcess_GetFontDataPatch
);
251 render_pdf_to_dc_func_
=
252 reinterpret_cast<RenderPDFPageToDCProc
>(
253 pdf_lib
.GetFunctionPointer("RenderPDFPageToDC"));
254 LOG_IF(WARNING
, !render_pdf_to_dc_func_
) << "Missing RenderPDFPageToDC";
256 return render_pdf_to_dc_func_
!= NULL
;
259 bool RenderPDFPageToDC(const void* pdf_buffer
,
270 bool stretch_to_bounds
,
271 bool keep_aspect_ratio
,
272 bool center_in_bounds
,
274 if (!render_pdf_to_dc_func_
)
276 return render_pdf_to_dc_func_(pdf_buffer
, buffer_size
, page_number
,
277 dc
, dpi_x
, dpi_y
, bounds_origin_x
,
278 bounds_origin_y
, bounds_width
, bounds_height
,
279 fit_to_bounds
, stretch_to_bounds
,
280 keep_aspect_ratio
, center_in_bounds
,
285 // Exported by PDF plugin.
286 typedef bool (*RenderPDFPageToDCProc
)(
287 const void* pdf_buffer
, int buffer_size
, int page_number
, HDC dc
,
288 int dpi_x
, int dpi_y
, int bounds_origin_x
, int bounds_origin_y
,
289 int bounds_width
, int bounds_height
, bool fit_to_bounds
,
290 bool stretch_to_bounds
, bool keep_aspect_ratio
, bool center_in_bounds
,
292 RenderPDFPageToDCProc render_pdf_to_dc_func_
;
294 DISALLOW_COPY_AND_ASSIGN(PdfFunctionsWin
);
297 typedef PdfFunctionsWin PdfFunctions
;
299 typedef PdfFunctionsBase PdfFunctions
;
302 #if !defined(OS_ANDROID) && !defined(OS_IOS)
303 void FinishParseMediaMetadata(
304 metadata::MediaMetadataParser
* parser
,
305 scoped_ptr
<extensions::api::media_galleries::MediaMetadata
> metadata
) {
306 Send(new ChromeUtilityHostMsg_ParseMediaMetadata_Finished(
307 true, *(metadata
->ToValue().get())));
308 ReleaseProcessIfNeeded();
310 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
312 static base::LazyInstance
<PdfFunctions
> g_pdf_lib
= LAZY_INSTANCE_INITIALIZER
;
316 ChromeContentUtilityClient::ChromeContentUtilityClient()
317 : filter_messages_(false) {
318 #if !defined(OS_ANDROID)
319 handlers_
.push_back(new ProfileImportHandler());
322 #if defined(ENABLE_MDNS)
323 if (CommandLine::ForCurrentProcess()->HasSwitch(
324 switches::kUtilityProcessEnableMDns
)) {
325 handlers_
.push_back(new local_discovery::ServiceDiscoveryMessageHandler());
327 #endif // ENABLE_MDNS
329 handlers_
.push_back(new image_writer::ImageWriterHandler());
332 ChromeContentUtilityClient::~ChromeContentUtilityClient() {
335 void ChromeContentUtilityClient::UtilityThreadStarted() {
336 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
337 std::string lang
= command_line
->GetSwitchValueASCII(switches::kLang
);
339 extension_l10n_util::SetProcessLocale(lang
);
341 if (command_line
->HasSwitch(switches::kUtilityProcessRunningElevated
)) {
342 message_id_whitelist_
.insert(kMessageWhitelist
,
343 kMessageWhitelist
+ kMessageWhitelistSize
);
344 filter_messages_
= true;
348 bool ChromeContentUtilityClient::OnMessageReceived(
349 const IPC::Message
& message
) {
350 if (filter_messages_
&&
351 (message_id_whitelist_
.find(message
.type()) ==
352 message_id_whitelist_
.end())) {
357 IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient
, message
)
358 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackExtension
, OnUnpackExtension
)
359 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackWebResource
,
361 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseUpdateManifest
,
362 OnParseUpdateManifest
)
363 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImage
, OnDecodeImage
)
364 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImageBase64
, OnDecodeImageBase64
)
365 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafile
,
366 OnRenderPDFPagesToMetafile
)
367 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToPWGRaster
,
368 OnRenderPDFPagesToPWGRaster
)
369 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RobustJPEGDecodeImage
,
370 OnRobustJPEGDecodeImage
)
371 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseJSON
, OnParseJSON
)
372 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterCapsAndDefaults
,
373 OnGetPrinterCapsAndDefaults
)
374 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults
,
375 OnGetPrinterSemanticCapsAndDefaults
)
376 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileBsdiff
,
378 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileCourgette
,
379 OnPatchFileCourgette
)
380 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing
, OnStartupPing
)
381 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection
,
382 OnAnalyzeZipFileForDownloadProtection
)
384 #if !defined(OS_ANDROID) && !defined(OS_IOS)
385 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CheckMediaFile
, OnCheckMediaFile
)
386 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseMediaMetadata
,
387 OnParseMediaMetadata
)
388 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
390 #if defined(OS_CHROMEOS)
391 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile
, OnCreateZipFile
)
392 #endif // defined(OS_CHROMEOS)
395 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesPrefXml
,
396 OnParseITunesPrefXml
)
397 #endif // defined(OS_WIN)
399 #if defined(OS_MACOSX)
400 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseIPhotoLibraryXmlFile
,
401 OnParseIPhotoLibraryXmlFile
)
402 #endif // defined(OS_MACOSX)
404 #if defined(OS_WIN) || defined(OS_MACOSX)
405 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesLibraryXmlFile
,
406 OnParseITunesLibraryXmlFile
)
407 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParsePicasaPMPDatabase
,
408 OnParsePicasaPMPDatabase
)
409 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_IndexPicasaAlbumsContents
,
410 OnIndexPicasaAlbumsContents
)
411 #endif // defined(OS_WIN) || defined(OS_MACOSX)
414 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetAndEncryptWiFiCredentials
,
415 OnGetAndEncryptWiFiCredentials
)
416 #endif // defined(OS_WIN)
418 IPC_MESSAGE_UNHANDLED(handled
= false)
419 IPC_END_MESSAGE_MAP()
421 for (Handlers::iterator it
= handlers_
.begin();
422 !handled
&& it
!= handlers_
.end(); ++it
) {
423 handled
= (*it
)->OnMessageReceived(message
);
430 void ChromeContentUtilityClient::PreSandboxStartup() {
431 #if defined(ENABLE_MDNS)
432 if (CommandLine::ForCurrentProcess()->HasSwitch(
433 switches::kUtilityProcessEnableMDns
)) {
434 local_discovery::ServiceDiscoveryMessageHandler::PreSandboxStartup();
436 #endif // ENABLE_MDNS
438 g_pdf_lib
.Get().Init();
440 // Load media libraries for media file validation.
441 base::FilePath media_path
;
442 PathService::Get(content::DIR_MEDIA_LIBS
, &media_path
);
443 if (!media_path
.empty())
444 media::InitializeMediaLibrary(media_path
);
447 void ChromeContentUtilityClient::OnUnpackExtension(
448 const base::FilePath
& extension_path
,
449 const std::string
& extension_id
,
451 int creation_flags
) {
452 CHECK_GT(location
, extensions::Manifest::INVALID_LOCATION
);
453 CHECK_LT(location
, extensions::Manifest::NUM_LOCATIONS
);
454 extensions::ExtensionsClient::Set(
455 extensions::ChromeExtensionsClient::GetInstance());
456 extensions::Unpacker
unpacker(
459 static_cast<extensions::Manifest::Location
>(location
),
461 if (unpacker
.Run() && unpacker
.DumpImagesToFile() &&
462 unpacker
.DumpMessageCatalogsToFile()) {
463 Send(new ChromeUtilityHostMsg_UnpackExtension_Succeeded(
464 *unpacker
.parsed_manifest()));
466 Send(new ChromeUtilityHostMsg_UnpackExtension_Failed(
467 unpacker
.error_message()));
470 ReleaseProcessIfNeeded();
473 void ChromeContentUtilityClient::OnUnpackWebResource(
474 const std::string
& resource_data
) {
476 // TODO(mrc): Add the possibility of a template that controls parsing, and
477 // the ability to download and verify images.
478 WebResourceUnpacker
unpacker(resource_data
);
479 if (unpacker
.Run()) {
480 Send(new ChromeUtilityHostMsg_UnpackWebResource_Succeeded(
481 *unpacker
.parsed_json()));
483 Send(new ChromeUtilityHostMsg_UnpackWebResource_Failed(
484 unpacker
.error_message()));
487 ReleaseProcessIfNeeded();
490 void ChromeContentUtilityClient::OnParseUpdateManifest(const std::string
& xml
) {
491 UpdateManifest manifest
;
492 if (!manifest
.Parse(xml
)) {
493 Send(new ChromeUtilityHostMsg_ParseUpdateManifest_Failed(
496 Send(new ChromeUtilityHostMsg_ParseUpdateManifest_Succeeded(
497 manifest
.results()));
499 ReleaseProcessIfNeeded();
502 void ChromeContentUtilityClient::OnDecodeImage(
503 const std::vector
<unsigned char>& encoded_data
) {
504 const SkBitmap
& decoded_image
= content::DecodeImage(&encoded_data
[0],
506 encoded_data
.size());
507 if (decoded_image
.empty()) {
508 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
510 Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(decoded_image
));
512 ReleaseProcessIfNeeded();
515 void ChromeContentUtilityClient::OnDecodeImageBase64(
516 const std::string
& encoded_string
) {
517 std::string decoded_string
;
519 if (!base::Base64Decode(encoded_string
, &decoded_string
)) {
520 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
524 std::vector
<unsigned char> decoded_vector(decoded_string
.size());
525 for (size_t i
= 0; i
< decoded_string
.size(); ++i
) {
526 decoded_vector
[i
] = static_cast<unsigned char>(decoded_string
[i
]);
529 OnDecodeImage(decoded_vector
);
532 #if defined(OS_CHROMEOS)
533 void ChromeContentUtilityClient::OnCreateZipFile(
534 const base::FilePath
& src_dir
,
535 const std::vector
<base::FilePath
>& src_relative_paths
,
536 const base::FileDescriptor
& dest_fd
) {
537 bool succeeded
= true;
539 // Check sanity of source relative paths. Reject if path is absolute or
540 // contains any attempt to reference a parent directory ("../" tricks).
541 for (std::vector
<base::FilePath
>::const_iterator iter
=
542 src_relative_paths
.begin(); iter
!= src_relative_paths
.end();
544 if (iter
->IsAbsolute() || iter
->ReferencesParent()) {
551 succeeded
= zip::ZipFiles(src_dir
, src_relative_paths
, dest_fd
.fd
);
554 Send(new ChromeUtilityHostMsg_CreateZipFile_Succeeded());
556 Send(new ChromeUtilityHostMsg_CreateZipFile_Failed());
557 ReleaseProcessIfNeeded();
559 #endif // defined(OS_CHROMEOS)
561 void ChromeContentUtilityClient::OnRenderPDFPagesToMetafile(
562 base::PlatformFile pdf_file
,
563 const base::FilePath
& metafile_path
,
564 const printing::PdfRenderSettings
& settings
,
565 const std::vector
<printing::PageRange
>& page_ranges
) {
566 bool succeeded
= false;
568 int highest_rendered_page_number
= 0;
569 double scale_factor
= 1.0;
570 succeeded
= RenderPDFToWinMetafile(pdf_file
,
574 &highest_rendered_page_number
,
577 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Succeeded(
578 highest_rendered_page_number
, scale_factor
));
580 #endif // defined(OS_WIN)
582 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed());
584 ReleaseProcessIfNeeded();
587 void ChromeContentUtilityClient::OnRenderPDFPagesToPWGRaster(
588 IPC::PlatformFileForTransit pdf_transit
,
589 const printing::PdfRenderSettings
& settings
,
590 const printing::PwgRasterSettings
& bitmap_settings
,
591 IPC::PlatformFileForTransit bitmap_transit
) {
592 base::PlatformFile pdf
=
593 IPC::PlatformFileForTransitToPlatformFile(pdf_transit
);
594 base::PlatformFile bitmap
=
595 IPC::PlatformFileForTransitToPlatformFile(bitmap_transit
);
596 if (RenderPDFPagesToPWGRaster(pdf
, settings
, bitmap_settings
, bitmap
)) {
597 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded());
599 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed());
601 ReleaseProcessIfNeeded();
605 bool ChromeContentUtilityClient::RenderPDFToWinMetafile(
606 base::PlatformFile pdf_file
,
607 const base::FilePath
& metafile_path
,
608 const printing::PdfRenderSettings
& settings
,
609 const std::vector
<printing::PageRange
>& page_ranges
,
610 int* highest_rendered_page_number
,
611 double* scale_factor
) {
612 *highest_rendered_page_number
= -1;
614 base::win::ScopedHandle
file(pdf_file
);
616 if (!g_pdf_lib
.Get().IsValid())
619 // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle
620 // and a page range array. That way we don't need to read the entire PDF into
622 DWORD length
= ::GetFileSize(file
, NULL
);
623 if (length
== INVALID_FILE_SIZE
)
626 std::vector
<uint8
> buffer
;
627 buffer
.resize(length
);
628 DWORD bytes_read
= 0;
629 if (!ReadFile(pdf_file
, &buffer
.front(), length
, &bytes_read
, NULL
) ||
630 (bytes_read
!= length
)) {
634 int total_page_count
= 0;
635 if (!g_pdf_lib
.Get().GetPDFDocInfo(&buffer
.front(), buffer
.size(),
636 &total_page_count
, NULL
)) {
640 printing::Emf metafile
;
641 metafile
.InitToFile(metafile_path
);
642 // We need to scale down DC to fit an entire page into DC available area.
643 // Current metafile is based on screen DC and have current screen size.
644 // Writing outside of those boundaries will result in the cut-off output.
645 // On metafiles (this is the case here), scaling down will still record
646 // original coordinates and we'll be able to print in full resolution.
647 // Before playback we'll need to counter the scaling up that will happen
648 // in the service (print_system_win.cc).
649 *scale_factor
= gfx::CalculatePageScale(metafile
.context(),
650 settings
.area().right(),
651 settings
.area().bottom());
652 gfx::ScaleDC(metafile
.context(), *scale_factor
);
655 std::vector
<printing::PageRange
>::const_iterator iter
;
656 for (iter
= page_ranges
.begin(); iter
!= page_ranges
.end(); ++iter
) {
657 for (int page_number
= iter
->from
; page_number
<= iter
->to
; ++page_number
) {
658 if (page_number
>= total_page_count
)
660 // The underlying metafile is of type Emf and ignores the arguments passed
662 metafile
.StartPage(gfx::Size(), gfx::Rect(), 1);
663 if (g_pdf_lib
.Get().RenderPDFPageToDC(
664 &buffer
.front(), buffer
.size(), page_number
, metafile
.context(),
665 settings
.dpi(), settings
.dpi(), settings
.area().x(),
666 settings
.area().y(), settings
.area().width(),
667 settings
.area().height(), true, false, true, true,
668 settings
.autorotate())) {
669 if (*highest_rendered_page_number
< page_number
)
670 *highest_rendered_page_number
= page_number
;
673 metafile
.FinishPage();
676 metafile
.FinishDocument();
679 #endif // defined(OS_WIN)
681 bool ChromeContentUtilityClient::RenderPDFPagesToPWGRaster(
682 base::PlatformFile pdf_file
,
683 const printing::PdfRenderSettings
& settings
,
684 const printing::PwgRasterSettings
& bitmap_settings
,
685 base::PlatformFile bitmap_file
) {
686 bool autoupdate
= true;
687 if (!g_pdf_lib
.Get().IsValid())
690 base::PlatformFileInfo info
;
691 if (!base::GetPlatformFileInfo(pdf_file
, &info
) || info
.size
<= 0)
694 std::string
data(info
.size
, 0);
695 int data_size
= base::ReadPlatformFile(pdf_file
, 0, &data
[0], data
.size());
696 if (data_size
!= static_cast<int>(data
.size()))
699 int total_page_count
= 0;
700 if (!g_pdf_lib
.Get().GetPDFDocInfo(data
.data(), data
.size(),
701 &total_page_count
, NULL
)) {
705 cloud_print::PwgEncoder encoder
;
706 std::string pwg_header
;
707 encoder
.EncodeDocumentHeader(&pwg_header
);
708 int bytes_written
= base::WritePlatformFileAtCurrentPos(bitmap_file
,
711 if (bytes_written
!= static_cast<int>(pwg_header
.size()))
714 cloud_print::BitmapImage
image(settings
.area().size(),
715 cloud_print::BitmapImage::BGRA
);
716 for (int i
= 0; i
< total_page_count
; ++i
) {
719 if (bitmap_settings
.reverse_page_order
) {
720 page_number
= total_page_count
- 1 - page_number
;
725 // Transform odd pages.
726 if (page_number
% 2) {
728 (bitmap_settings
.odd_page_transform
!= printing::TRANSFORM_NORMAL
);
731 if (!g_pdf_lib
.Get().RenderPDFPageToBitmap(data
.data(),
735 image
.size().width(),
736 image
.size().height(),
742 std::string pwg_page
;
743 if (!encoder
.EncodePage(
744 image
, settings
.dpi(), total_page_count
, &pwg_page
, rotate
))
746 bytes_written
= base::WritePlatformFileAtCurrentPos(bitmap_file
,
749 if (bytes_written
!= static_cast<int>(pwg_page
.size()))
755 void ChromeContentUtilityClient::OnRobustJPEGDecodeImage(
756 const std::vector
<unsigned char>& encoded_data
) {
757 // Our robust jpeg decoding is using IJG libjpeg.
758 if (gfx::JPEGCodec::JpegLibraryVariant() == gfx::JPEGCodec::IJG_LIBJPEG
) {
759 scoped_ptr
<SkBitmap
> decoded_image(gfx::JPEGCodec::Decode(
760 &encoded_data
[0], encoded_data
.size()));
761 if (!decoded_image
.get() || decoded_image
->empty()) {
762 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
764 Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(*decoded_image
));
767 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
769 ReleaseProcessIfNeeded();
772 void ChromeContentUtilityClient::OnParseJSON(const std::string
& json
) {
775 base::Value
* value
= base::JSONReader::ReadAndReturnError(
776 json
, base::JSON_PARSE_RFC
, &error_code
, &error
);
778 base::ListValue wrapper
;
779 wrapper
.Append(value
);
780 Send(new ChromeUtilityHostMsg_ParseJSON_Succeeded(wrapper
));
782 Send(new ChromeUtilityHostMsg_ParseJSON_Failed(error
));
784 ReleaseProcessIfNeeded();
787 void ChromeContentUtilityClient::OnGetPrinterCapsAndDefaults(
788 const std::string
& printer_name
) {
789 #if defined(ENABLE_FULL_PRINTING)
790 scoped_refptr
<printing::PrintBackend
> print_backend
=
791 printing::PrintBackend::CreateInstance(NULL
);
792 printing::PrinterCapsAndDefaults printer_info
;
794 crash_keys::ScopedPrinterInfo
crash_key(
795 print_backend
->GetPrinterDriverInfo(printer_name
));
797 if (print_backend
->GetPrinterCapsAndDefaults(printer_name
, &printer_info
)) {
798 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(
799 printer_name
, printer_info
));
803 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed(
806 ReleaseProcessIfNeeded();
809 void ChromeContentUtilityClient::OnGetPrinterSemanticCapsAndDefaults(
810 const std::string
& printer_name
) {
811 #if defined(ENABLE_FULL_PRINTING)
812 scoped_refptr
<printing::PrintBackend
> print_backend
=
813 printing::PrintBackend::CreateInstance(NULL
);
814 printing::PrinterSemanticCapsAndDefaults printer_info
;
816 crash_keys::ScopedPrinterInfo
crash_key(
817 print_backend
->GetPrinterDriverInfo(printer_name
));
819 if (print_backend
->GetPrinterSemanticCapsAndDefaults(printer_name
,
821 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded(
822 printer_name
, printer_info
));
826 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed(
829 ReleaseProcessIfNeeded();
832 void ChromeContentUtilityClient::OnPatchFileBsdiff(
833 const base::FilePath
& input_file
,
834 const base::FilePath
& patch_file
,
835 const base::FilePath
& output_file
) {
836 if (input_file
.empty() || patch_file
.empty() || output_file
.empty()) {
837 Send(new ChromeUtilityHostMsg_PatchFile_Failed(-1));
839 const int patch_status
= courgette::ApplyBinaryPatch(input_file
,
842 if (patch_status
!= courgette::OK
)
843 Send(new ChromeUtilityHostMsg_PatchFile_Failed(patch_status
));
845 Send(new ChromeUtilityHostMsg_PatchFile_Succeeded());
847 ReleaseProcessIfNeeded();
850 void ChromeContentUtilityClient::OnPatchFileCourgette(
851 const base::FilePath
& input_file
,
852 const base::FilePath
& patch_file
,
853 const base::FilePath
& output_file
) {
854 if (input_file
.empty() || patch_file
.empty() || output_file
.empty()) {
855 Send(new ChromeUtilityHostMsg_PatchFile_Failed(-1));
857 const int patch_status
= courgette::ApplyEnsemblePatch(
858 input_file
.value().c_str(),
859 patch_file
.value().c_str(),
860 output_file
.value().c_str());
861 if (patch_status
!= courgette::C_OK
)
862 Send(new ChromeUtilityHostMsg_PatchFile_Failed(patch_status
));
864 Send(new ChromeUtilityHostMsg_PatchFile_Succeeded());
866 ReleaseProcessIfNeeded();
869 void ChromeContentUtilityClient::OnStartupPing() {
870 Send(new ChromeUtilityHostMsg_ProcessStarted
);
871 // Don't release the process, we assume further messages are on the way.
874 void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
875 const IPC::PlatformFileForTransit
& zip_file
) {
876 safe_browsing::zip_analyzer::Results results
;
877 safe_browsing::zip_analyzer::AnalyzeZipFile(
878 IPC::PlatformFileForTransitToPlatformFile(zip_file
), &results
);
879 Send(new ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished(
881 ReleaseProcessIfNeeded();
884 #if !defined(OS_ANDROID) && !defined(OS_IOS)
885 void ChromeContentUtilityClient::OnCheckMediaFile(
886 int64 milliseconds_of_decoding
,
887 const IPC::PlatformFileForTransit
& media_file
) {
888 media::MediaFileChecker
checker(
889 base::File(IPC::PlatformFileForTransitToPlatformFile(media_file
)));
890 const bool check_success
= checker
.Start(
891 base::TimeDelta::FromMilliseconds(milliseconds_of_decoding
));
892 Send(new ChromeUtilityHostMsg_CheckMediaFile_Finished(check_success
));
893 ReleaseProcessIfNeeded();
896 void ChromeContentUtilityClient::OnParseMediaMetadata(
897 const std::string
& mime_type
,
899 // Only one IPCDataSource may be created and added to the list of handlers.
900 metadata::IPCDataSource
* source
= new metadata::IPCDataSource(total_size
);
901 handlers_
.push_back(source
);
903 metadata::MediaMetadataParser
* parser
=
904 new metadata::MediaMetadataParser(source
, mime_type
);
905 parser
->Start(base::Bind(&FinishParseMediaMetadata
, base::Owned(parser
)));
907 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
910 void ChromeContentUtilityClient::OnParseITunesPrefXml(
911 const std::string
& itunes_xml_data
) {
912 base::FilePath
library_path(
913 itunes::FindLibraryLocationInPrefXml(itunes_xml_data
));
914 Send(new ChromeUtilityHostMsg_GotITunesDirectory(library_path
));
915 ReleaseProcessIfNeeded();
917 #endif // defined(OS_WIN)
919 #if defined(OS_MACOSX)
920 void ChromeContentUtilityClient::OnParseIPhotoLibraryXmlFile(
921 const IPC::PlatformFileForTransit
& iphoto_library_file
) {
922 iphoto::IPhotoLibraryParser parser
;
923 base::PlatformFile file
=
924 IPC::PlatformFileForTransitToPlatformFile(iphoto_library_file
);
925 bool result
= parser
.Parse(iapps::ReadPlatformFileAsString(file
));
926 Send(new ChromeUtilityHostMsg_GotIPhotoLibrary(result
, parser
.library()));
927 ReleaseProcessIfNeeded();
929 #endif // defined(OS_MACOSX)
931 #if defined(OS_WIN) || defined(OS_MACOSX)
932 void ChromeContentUtilityClient::OnParseITunesLibraryXmlFile(
933 const IPC::PlatformFileForTransit
& itunes_library_file
) {
934 itunes::ITunesLibraryParser parser
;
935 base::PlatformFile file
=
936 IPC::PlatformFileForTransitToPlatformFile(itunes_library_file
);
937 bool result
= parser
.Parse(iapps::ReadPlatformFileAsString(file
));
938 Send(new ChromeUtilityHostMsg_GotITunesLibrary(result
, parser
.library()));
939 ReleaseProcessIfNeeded();
942 void ChromeContentUtilityClient::OnParsePicasaPMPDatabase(
943 const picasa::AlbumTableFilesForTransit
& album_table_files
) {
944 picasa::AlbumTableFiles files
;
945 files
.indicator_file
= IPC::PlatformFileForTransitToPlatformFile(
946 album_table_files
.indicator_file
);
947 files
.category_file
= IPC::PlatformFileForTransitToPlatformFile(
948 album_table_files
.category_file
);
949 files
.date_file
= IPC::PlatformFileForTransitToPlatformFile(
950 album_table_files
.date_file
);
951 files
.filename_file
= IPC::PlatformFileForTransitToPlatformFile(
952 album_table_files
.filename_file
);
953 files
.name_file
= IPC::PlatformFileForTransitToPlatformFile(
954 album_table_files
.name_file
);
955 files
.token_file
= IPC::PlatformFileForTransitToPlatformFile(
956 album_table_files
.token_file
);
957 files
.uid_file
= IPC::PlatformFileForTransitToPlatformFile(
958 album_table_files
.uid_file
);
960 picasa::PicasaAlbumTableReader
reader(files
);
961 bool parse_success
= reader
.Init();
962 Send(new ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished(
966 ReleaseProcessIfNeeded();
969 void ChromeContentUtilityClient::OnIndexPicasaAlbumsContents(
970 const picasa::AlbumUIDSet
& album_uids
,
971 const std::vector
<picasa::FolderINIContents
>& folders_inis
) {
972 picasa::PicasaAlbumsIndexer
indexer(album_uids
);
973 indexer
.ParseFolderINI(folders_inis
);
975 Send(new ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished(
976 indexer
.albums_images()));
977 ReleaseProcessIfNeeded();
979 #endif // defined(OS_WIN) || defined(OS_MACOSX)
982 void ChromeContentUtilityClient::OnGetAndEncryptWiFiCredentials(
983 const std::string
& network_guid
,
984 const std::vector
<uint8
>& public_key
) {
985 scoped_ptr
<wifi::WiFiService
> wifi_service(wifi::WiFiService::Create());
986 wifi_service
->Initialize(NULL
);
988 std::string key_data
;
990 wifi_service
->GetKeyFromSystem(network_guid
, &key_data
, &error
);
992 std::vector
<uint8
> ciphertext
;
993 bool success
= error
.empty() && !key_data
.empty();
995 NetworkingPrivateCrypto crypto
;
996 success
= crypto
.EncryptByteString(public_key
, key_data
, &ciphertext
);
999 Send(new ChromeUtilityHostMsg_GotEncryptedWiFiCredentials(ciphertext
,
1002 #endif // defined(OS_WIN)
1004 } // namespace chrome