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/profile_import_handler.h"
28 #include "chrome/utility/web_resource_unpacker.h"
29 #include "content/public/child/image_decoder_utils.h"
30 #include "content/public/common/content_paths.h"
31 #include "content/public/common/content_switches.h"
32 #include "content/public/utility/utility_thread.h"
33 #include "extensions/common/extension.h"
34 #include "extensions/common/manifest.h"
35 #include "media/base/media.h"
36 #include "media/base/media_file_checker.h"
37 #include "printing/page_range.h"
38 #include "printing/pdf_render_settings.h"
39 #include "third_party/skia/include/core/SkBitmap.h"
40 #include "third_party/zlib/google/zip.h"
41 #include "ui/base/ui_base_switches.h"
42 #include "ui/gfx/codec/jpeg_codec.h"
43 #include "ui/gfx/rect.h"
44 #include "ui/gfx/size.h"
47 #include "base/win/iat_patch_function.h"
48 #include "base/win/scoped_handle.h"
49 #include "chrome/utility/media_galleries/itunes_pref_parser_win.h"
50 #include "printing/emf_win.h"
51 #include "ui/gfx/gdi_util.h"
52 #endif // defined(OS_WIN)
54 #if defined(OS_MACOSX)
55 #include "chrome/utility/media_galleries/iphoto_library_parser.h"
56 #endif // defined(OS_MACOSX)
58 #if defined(OS_WIN) || defined(OS_MACOSX)
59 #include "chrome/utility/media_galleries/iapps_xml_utils.h"
60 #include "chrome/utility/media_galleries/itunes_library_parser.h"
61 #include "chrome/utility/media_galleries/picasa_album_table_reader.h"
62 #include "chrome/utility/media_galleries/picasa_albums_indexer.h"
63 #endif // defined(OS_WIN) || defined(OS_MACOSX)
65 #if !defined(OS_ANDROID) && !defined(OS_IOS)
66 #include "chrome/utility/media_galleries/ipc_data_source.h"
67 #include "chrome/utility/media_galleries/media_metadata_parser.h"
68 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
70 #if defined(ENABLE_FULL_PRINTING)
71 #include "chrome/common/crash_keys.h"
72 #include "printing/backend/print_backend.h"
75 #if defined(ENABLE_MDNS)
76 #include "chrome/utility/local_discovery/service_discovery_message_handler.h"
83 bool Send(IPC::Message
* message
) {
84 return content::UtilityThread::Get()->Send(message
);
87 void ReleaseProcessIfNeeded() {
88 content::UtilityThread::Get()->ReleaseProcessIfNeeded();
91 class PdfFunctionsBase
{
93 PdfFunctionsBase() : render_pdf_to_bitmap_func_(NULL
),
94 get_pdf_doc_info_func_(NULL
) {}
97 base::FilePath pdf_module_path
;
98 if (!PathService::Get(chrome::FILE_PDF_PLUGIN
, &pdf_module_path
) ||
99 !base::PathExists(pdf_module_path
)) {
103 pdf_lib_
.Reset(base::LoadNativeLibrary(pdf_module_path
, NULL
));
104 if (!pdf_lib_
.is_valid()) {
105 LOG(WARNING
) << "Couldn't load PDF plugin";
109 render_pdf_to_bitmap_func_
=
110 reinterpret_cast<RenderPDFPageToBitmapProc
>(
111 pdf_lib_
.GetFunctionPointer("RenderPDFPageToBitmap"));
112 LOG_IF(WARNING
, !render_pdf_to_bitmap_func_
) <<
113 "Missing RenderPDFPageToBitmap";
115 get_pdf_doc_info_func_
=
116 reinterpret_cast<GetPDFDocInfoProc
>(
117 pdf_lib_
.GetFunctionPointer("GetPDFDocInfo"));
118 LOG_IF(WARNING
, !get_pdf_doc_info_func_
) << "Missing GetPDFDocInfo";
120 if (!render_pdf_to_bitmap_func_
|| !get_pdf_doc_info_func_
||
121 !PlatformInit(pdf_module_path
, pdf_lib_
)) {
128 bool IsValid() const {
129 return pdf_lib_
.is_valid();
133 pdf_lib_
.Reset(NULL
);
136 bool RenderPDFPageToBitmap(const void* pdf_buffer
,
145 if (!render_pdf_to_bitmap_func_
)
147 return render_pdf_to_bitmap_func_(pdf_buffer
, pdf_buffer_size
, page_number
,
148 bitmap_buffer
, bitmap_width
,
149 bitmap_height
, dpi_x
, dpi_y
, autorotate
);
152 bool GetPDFDocInfo(const void* pdf_buffer
,
155 double* max_page_width
) {
156 if (!get_pdf_doc_info_func_
)
158 return get_pdf_doc_info_func_(pdf_buffer
, buffer_size
, page_count
,
163 virtual bool PlatformInit(
164 const base::FilePath
& pdf_module_path
,
165 const base::ScopedNativeLibrary
& pdf_lib
) {
170 // Exported by PDF plugin.
171 typedef bool (*RenderPDFPageToBitmapProc
)(const void* pdf_buffer
,
180 typedef bool (*GetPDFDocInfoProc
)(const void* pdf_buffer
,
181 int buffer_size
, int* page_count
,
182 double* max_page_width
);
184 RenderPDFPageToBitmapProc render_pdf_to_bitmap_func_
;
185 GetPDFDocInfoProc get_pdf_doc_info_func_
;
187 base::ScopedNativeLibrary pdf_lib_
;
188 DISALLOW_COPY_AND_ASSIGN(PdfFunctionsBase
);
192 // The 2 below IAT patch functions are almost identical to the code in
193 // render_process_impl.cc. This is needed to work around specific Windows APIs
194 // used by the Chrome PDF plugin that will fail in the sandbox.
195 static base::win::IATPatchFunction g_iat_patch_createdca
;
196 HDC WINAPI
UtilityProcess_CreateDCAPatch(LPCSTR driver_name
,
199 const DEVMODEA
* init_data
) {
200 if (driver_name
&& (std::string("DISPLAY") == driver_name
)) {
201 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
202 return CreateCompatibleDC(NULL
);
206 return CreateDCA(driver_name
, device_name
, output
, init_data
);
209 static base::win::IATPatchFunction g_iat_patch_get_font_data
;
210 DWORD WINAPI
UtilityProcess_GetFontDataPatch(
211 HDC hdc
, DWORD table
, DWORD offset
, LPVOID buffer
, DWORD length
) {
212 int rv
= GetFontData(hdc
, table
, offset
, buffer
, length
);
213 if (rv
== GDI_ERROR
&& hdc
) {
214 HFONT font
= static_cast<HFONT
>(GetCurrentObject(hdc
, OBJ_FONT
));
217 if (GetObject(font
, sizeof(LOGFONT
), &logfont
)) {
218 content::UtilityThread::Get()->PreCacheFont(logfont
);
219 rv
= GetFontData(hdc
, table
, offset
, buffer
, length
);
220 content::UtilityThread::Get()->ReleaseCachedFonts();
226 class PdfFunctionsWin
: public PdfFunctionsBase
{
228 PdfFunctionsWin() : render_pdf_to_dc_func_(NULL
) {
232 const base::FilePath
& pdf_module_path
,
233 const base::ScopedNativeLibrary
& pdf_lib
) OVERRIDE
{
234 // Patch the IAT for handling specific APIs known to fail in the sandbox.
235 if (!g_iat_patch_createdca
.is_patched()) {
236 g_iat_patch_createdca
.Patch(pdf_module_path
.value().c_str(),
237 "gdi32.dll", "CreateDCA",
238 UtilityProcess_CreateDCAPatch
);
241 if (!g_iat_patch_get_font_data
.is_patched()) {
242 g_iat_patch_get_font_data
.Patch(pdf_module_path
.value().c_str(),
243 "gdi32.dll", "GetFontData",
244 UtilityProcess_GetFontDataPatch
);
246 render_pdf_to_dc_func_
=
247 reinterpret_cast<RenderPDFPageToDCProc
>(
248 pdf_lib
.GetFunctionPointer("RenderPDFPageToDC"));
249 LOG_IF(WARNING
, !render_pdf_to_dc_func_
) << "Missing RenderPDFPageToDC";
251 return render_pdf_to_dc_func_
!= NULL
;
254 bool RenderPDFPageToDC(const void* pdf_buffer
,
265 bool stretch_to_bounds
,
266 bool keep_aspect_ratio
,
267 bool center_in_bounds
,
269 if (!render_pdf_to_dc_func_
)
271 return render_pdf_to_dc_func_(pdf_buffer
, buffer_size
, page_number
,
272 dc
, dpi_x
, dpi_y
, bounds_origin_x
,
273 bounds_origin_y
, bounds_width
, bounds_height
,
274 fit_to_bounds
, stretch_to_bounds
,
275 keep_aspect_ratio
, center_in_bounds
,
280 // Exported by PDF plugin.
281 typedef bool (*RenderPDFPageToDCProc
)(
282 const void* pdf_buffer
, int buffer_size
, int page_number
, HDC dc
,
283 int dpi_x
, int dpi_y
, int bounds_origin_x
, int bounds_origin_y
,
284 int bounds_width
, int bounds_height
, bool fit_to_bounds
,
285 bool stretch_to_bounds
, bool keep_aspect_ratio
, bool center_in_bounds
,
287 RenderPDFPageToDCProc render_pdf_to_dc_func_
;
289 DISALLOW_COPY_AND_ASSIGN(PdfFunctionsWin
);
292 typedef PdfFunctionsWin PdfFunctions
;
294 typedef PdfFunctionsBase PdfFunctions
;
297 #if !defined(OS_ANDROID) && !defined(OS_IOS)
298 void SendMediaMetadataToHost(
299 scoped_ptr
<extensions::api::media_galleries::MediaMetadata
> metadata
) {
300 Send(new ChromeUtilityHostMsg_ParseMediaMetadata_Finished(
301 true, *(metadata
->ToValue().get())));
303 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
305 static base::LazyInstance
<PdfFunctions
> g_pdf_lib
= LAZY_INSTANCE_INITIALIZER
;
309 ChromeContentUtilityClient::ChromeContentUtilityClient()
310 : filter_messages_(false) {
311 #if !defined(OS_ANDROID)
312 handlers_
.push_back(new ProfileImportHandler());
315 #if defined(ENABLE_MDNS)
316 if (CommandLine::ForCurrentProcess()->HasSwitch(
317 switches::kUtilityProcessEnableMDns
)) {
318 handlers_
.push_back(new local_discovery::ServiceDiscoveryMessageHandler());
320 #endif // ENABLE_MDNS
323 ChromeContentUtilityClient::~ChromeContentUtilityClient() {
326 void ChromeContentUtilityClient::UtilityThreadStarted() {
327 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
328 std::string lang
= command_line
->GetSwitchValueASCII(switches::kLang
);
330 extension_l10n_util::SetProcessLocale(lang
);
332 if (command_line
->HasSwitch(switches::kUtilityProcessRunningElevated
)) {
333 message_id_whitelist_
.insert(kMessageWhitelist
,
334 kMessageWhitelist
+ kMessageWhitelistSize
);
335 filter_messages_
= true;
339 bool ChromeContentUtilityClient::OnMessageReceived(
340 const IPC::Message
& message
) {
341 if (filter_messages_
&&
342 (message_id_whitelist_
.find(message
.type()) ==
343 message_id_whitelist_
.end())) {
348 IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient
, message
)
349 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackExtension
, OnUnpackExtension
)
350 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackWebResource
,
352 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseUpdateManifest
,
353 OnParseUpdateManifest
)
354 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImage
, OnDecodeImage
)
355 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImageBase64
, OnDecodeImageBase64
)
356 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafile
,
357 OnRenderPDFPagesToMetafile
)
358 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToPWGRaster
,
359 OnRenderPDFPagesToPWGRaster
)
360 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RobustJPEGDecodeImage
,
361 OnRobustJPEGDecodeImage
)
362 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseJSON
, OnParseJSON
)
363 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterCapsAndDefaults
,
364 OnGetPrinterCapsAndDefaults
)
365 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults
,
366 OnGetPrinterSemanticCapsAndDefaults
)
367 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing
, OnStartupPing
)
368 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection
,
369 OnAnalyzeZipFileForDownloadProtection
)
371 #if !defined(OS_ANDROID) && !defined(OS_IOS)
372 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CheckMediaFile
, OnCheckMediaFile
)
373 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseMediaMetadata
,
374 OnParseMediaMetadata
)
375 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
377 #if defined(OS_CHROMEOS)
378 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile
, OnCreateZipFile
)
379 #endif // defined(OS_CHROMEOS)
382 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesPrefXml
,
383 OnParseITunesPrefXml
)
384 #endif // defined(OS_WIN)
386 #if defined(OS_MACOSX)
387 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseIPhotoLibraryXmlFile
,
388 OnParseIPhotoLibraryXmlFile
)
389 #endif // defined(OS_MACOSX)
391 #if defined(OS_WIN) || defined(OS_MACOSX)
392 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseITunesLibraryXmlFile
,
393 OnParseITunesLibraryXmlFile
)
394 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParsePicasaPMPDatabase
,
395 OnParsePicasaPMPDatabase
)
396 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_IndexPicasaAlbumsContents
,
397 OnIndexPicasaAlbumsContents
)
398 #endif // defined(OS_WIN) || defined(OS_MACOSX)
400 IPC_MESSAGE_UNHANDLED(handled
= false)
401 IPC_END_MESSAGE_MAP()
403 for (Handlers::iterator it
= handlers_
.begin();
404 !handled
&& it
!= handlers_
.end(); ++it
) {
405 handled
= (*it
)->OnMessageReceived(message
);
412 void ChromeContentUtilityClient::PreSandboxStartup() {
413 #if defined(ENABLE_MDNS)
414 local_discovery::ServiceDiscoveryMessageHandler::PreSandboxStartup();
415 #endif // ENABLE_MDNS
417 g_pdf_lib
.Get().Init();
419 // Load media libraries for media file validation.
420 base::FilePath media_path
;
421 PathService::Get(content::DIR_MEDIA_LIBS
, &media_path
);
422 if (!media_path
.empty())
423 media::InitializeMediaLibrary(media_path
);
426 void ChromeContentUtilityClient::OnUnpackExtension(
427 const base::FilePath
& extension_path
,
428 const std::string
& extension_id
,
430 int creation_flags
) {
431 CHECK_GT(location
, extensions::Manifest::INVALID_LOCATION
);
432 CHECK_LT(location
, extensions::Manifest::NUM_LOCATIONS
);
433 extensions::ExtensionsClient::Set(
434 extensions::ChromeExtensionsClient::GetInstance());
435 extensions::Unpacker
unpacker(
438 static_cast<extensions::Manifest::Location
>(location
),
440 if (unpacker
.Run() && unpacker
.DumpImagesToFile() &&
441 unpacker
.DumpMessageCatalogsToFile()) {
442 Send(new ChromeUtilityHostMsg_UnpackExtension_Succeeded(
443 *unpacker
.parsed_manifest()));
445 Send(new ChromeUtilityHostMsg_UnpackExtension_Failed(
446 unpacker
.error_message()));
449 ReleaseProcessIfNeeded();
452 void ChromeContentUtilityClient::OnUnpackWebResource(
453 const std::string
& resource_data
) {
455 // TODO(mrc): Add the possibility of a template that controls parsing, and
456 // the ability to download and verify images.
457 WebResourceUnpacker
unpacker(resource_data
);
458 if (unpacker
.Run()) {
459 Send(new ChromeUtilityHostMsg_UnpackWebResource_Succeeded(
460 *unpacker
.parsed_json()));
462 Send(new ChromeUtilityHostMsg_UnpackWebResource_Failed(
463 unpacker
.error_message()));
466 ReleaseProcessIfNeeded();
469 void ChromeContentUtilityClient::OnParseUpdateManifest(const std::string
& xml
) {
470 UpdateManifest manifest
;
471 if (!manifest
.Parse(xml
)) {
472 Send(new ChromeUtilityHostMsg_ParseUpdateManifest_Failed(
475 Send(new ChromeUtilityHostMsg_ParseUpdateManifest_Succeeded(
476 manifest
.results()));
478 ReleaseProcessIfNeeded();
481 void ChromeContentUtilityClient::OnDecodeImage(
482 const std::vector
<unsigned char>& encoded_data
) {
483 const SkBitmap
& decoded_image
= content::DecodeImage(&encoded_data
[0],
485 encoded_data
.size());
486 if (decoded_image
.empty()) {
487 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
489 Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(decoded_image
));
491 ReleaseProcessIfNeeded();
494 void ChromeContentUtilityClient::OnDecodeImageBase64(
495 const std::string
& encoded_string
) {
496 std::string decoded_string
;
498 if (!base::Base64Decode(encoded_string
, &decoded_string
)) {
499 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
503 std::vector
<unsigned char> decoded_vector(decoded_string
.size());
504 for (size_t i
= 0; i
< decoded_string
.size(); ++i
) {
505 decoded_vector
[i
] = static_cast<unsigned char>(decoded_string
[i
]);
508 OnDecodeImage(decoded_vector
);
511 #if defined(OS_CHROMEOS)
512 void ChromeContentUtilityClient::OnCreateZipFile(
513 const base::FilePath
& src_dir
,
514 const std::vector
<base::FilePath
>& src_relative_paths
,
515 const base::FileDescriptor
& dest_fd
) {
516 bool succeeded
= true;
518 // Check sanity of source relative paths. Reject if path is absolute or
519 // contains any attempt to reference a parent directory ("../" tricks).
520 for (std::vector
<base::FilePath
>::const_iterator iter
=
521 src_relative_paths
.begin(); iter
!= src_relative_paths
.end();
523 if (iter
->IsAbsolute() || iter
->ReferencesParent()) {
530 succeeded
= zip::ZipFiles(src_dir
, src_relative_paths
, dest_fd
.fd
);
533 Send(new ChromeUtilityHostMsg_CreateZipFile_Succeeded());
535 Send(new ChromeUtilityHostMsg_CreateZipFile_Failed());
536 ReleaseProcessIfNeeded();
538 #endif // defined(OS_CHROMEOS)
540 void ChromeContentUtilityClient::OnRenderPDFPagesToMetafile(
541 base::PlatformFile pdf_file
,
542 const base::FilePath
& metafile_path
,
543 const printing::PdfRenderSettings
& settings
,
544 const std::vector
<printing::PageRange
>& page_ranges
) {
545 bool succeeded
= false;
547 int highest_rendered_page_number
= 0;
548 double scale_factor
= 1.0;
549 succeeded
= RenderPDFToWinMetafile(pdf_file
,
553 &highest_rendered_page_number
,
556 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Succeeded(
557 highest_rendered_page_number
, scale_factor
));
559 #endif // defined(OS_WIN)
561 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed());
563 ReleaseProcessIfNeeded();
566 void ChromeContentUtilityClient::OnRenderPDFPagesToPWGRaster(
567 IPC::PlatformFileForTransit pdf_transit
,
568 const printing::PdfRenderSettings
& settings
,
569 IPC::PlatformFileForTransit bitmap_transit
) {
570 base::PlatformFile pdf
=
571 IPC::PlatformFileForTransitToPlatformFile(pdf_transit
);
572 base::PlatformFile bitmap
=
573 IPC::PlatformFileForTransitToPlatformFile(bitmap_transit
);
574 if (RenderPDFPagesToPWGRaster(pdf
, settings
, bitmap
)) {
575 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded());
577 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed());
579 ReleaseProcessIfNeeded();
583 bool ChromeContentUtilityClient::RenderPDFToWinMetafile(
584 base::PlatformFile pdf_file
,
585 const base::FilePath
& metafile_path
,
586 const printing::PdfRenderSettings
& settings
,
587 const std::vector
<printing::PageRange
>& page_ranges
,
588 int* highest_rendered_page_number
,
589 double* scale_factor
) {
590 *highest_rendered_page_number
= -1;
592 base::win::ScopedHandle
file(pdf_file
);
594 if (!g_pdf_lib
.Get().IsValid())
597 // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle
598 // and a page range array. That way we don't need to read the entire PDF into
600 DWORD length
= ::GetFileSize(file
, NULL
);
601 if (length
== INVALID_FILE_SIZE
)
604 std::vector
<uint8
> buffer
;
605 buffer
.resize(length
);
606 DWORD bytes_read
= 0;
607 if (!ReadFile(pdf_file
, &buffer
.front(), length
, &bytes_read
, NULL
) ||
608 (bytes_read
!= length
)) {
612 int total_page_count
= 0;
613 if (!g_pdf_lib
.Get().GetPDFDocInfo(&buffer
.front(), buffer
.size(),
614 &total_page_count
, NULL
)) {
618 printing::Emf metafile
;
619 metafile
.InitToFile(metafile_path
);
620 // We need to scale down DC to fit an entire page into DC available area.
621 // Current metafile is based on screen DC and have current screen size.
622 // Writing outside of those boundaries will result in the cut-off output.
623 // On metafiles (this is the case here), scaling down will still record
624 // original coordinates and we'll be able to print in full resolution.
625 // Before playback we'll need to counter the scaling up that will happen
626 // in the service (print_system_win.cc).
627 *scale_factor
= gfx::CalculatePageScale(metafile
.context(),
628 settings
.area().right(),
629 settings
.area().bottom());
630 gfx::ScaleDC(metafile
.context(), *scale_factor
);
633 std::vector
<printing::PageRange
>::const_iterator iter
;
634 for (iter
= page_ranges
.begin(); iter
!= page_ranges
.end(); ++iter
) {
635 for (int page_number
= iter
->from
; page_number
<= iter
->to
; ++page_number
) {
636 if (page_number
>= total_page_count
)
638 // The underlying metafile is of type Emf and ignores the arguments passed
640 metafile
.StartPage(gfx::Size(), gfx::Rect(), 1);
641 if (g_pdf_lib
.Get().RenderPDFPageToDC(
642 &buffer
.front(), buffer
.size(), page_number
, metafile
.context(),
643 settings
.dpi(), settings
.dpi(), settings
.area().x(),
644 settings
.area().y(), settings
.area().width(),
645 settings
.area().height(), true, false, true, true,
646 settings
.autorotate())) {
647 if (*highest_rendered_page_number
< page_number
)
648 *highest_rendered_page_number
= page_number
;
651 metafile
.FinishPage();
654 metafile
.FinishDocument();
657 #endif // defined(OS_WIN)
659 bool ChromeContentUtilityClient::RenderPDFPagesToPWGRaster(
660 base::PlatformFile pdf_file
,
661 const printing::PdfRenderSettings
& settings
,
662 base::PlatformFile bitmap_file
) {
663 bool autoupdate
= true;
664 if (!g_pdf_lib
.Get().IsValid())
667 base::PlatformFileInfo info
;
668 if (!base::GetPlatformFileInfo(pdf_file
, &info
) || info
.size
<= 0)
671 std::string
data(info
.size
, 0);
672 int data_size
= base::ReadPlatformFile(pdf_file
, 0, &data
[0], data
.size());
673 if (data_size
!= static_cast<int>(data
.size()))
676 int total_page_count
= 0;
677 if (!g_pdf_lib
.Get().GetPDFDocInfo(data
.data(), data
.size(),
678 &total_page_count
, NULL
)) {
682 cloud_print::PwgEncoder encoder
;
683 std::string pwg_header
;
684 encoder
.EncodeDocumentHeader(&pwg_header
);
685 int bytes_written
= base::WritePlatformFileAtCurrentPos(bitmap_file
,
688 if (bytes_written
!= static_cast<int>(pwg_header
.size()))
691 cloud_print::BitmapImage
image(settings
.area().size(),
692 cloud_print::BitmapImage::BGRA
);
693 for (int i
= 0; i
< total_page_count
; ++i
) {
694 if (!g_pdf_lib
.Get().RenderPDFPageToBitmap(
695 data
.data(), data
.size(), i
, image
.pixel_data(),
696 image
.size().width(), image
.size().height(), settings
.dpi(),
697 settings
.dpi(), autoupdate
)) {
700 std::string pwg_page
;
701 if (!encoder
.EncodePage(image
, settings
.dpi(), total_page_count
, &pwg_page
))
703 bytes_written
= base::WritePlatformFileAtCurrentPos(bitmap_file
,
706 if (bytes_written
!= static_cast<int>(pwg_page
.size()))
712 void ChromeContentUtilityClient::OnRobustJPEGDecodeImage(
713 const std::vector
<unsigned char>& encoded_data
) {
714 // Our robust jpeg decoding is using IJG libjpeg.
715 if (gfx::JPEGCodec::JpegLibraryVariant() == gfx::JPEGCodec::IJG_LIBJPEG
) {
716 scoped_ptr
<SkBitmap
> decoded_image(gfx::JPEGCodec::Decode(
717 &encoded_data
[0], encoded_data
.size()));
718 if (!decoded_image
.get() || decoded_image
->empty()) {
719 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
721 Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(*decoded_image
));
724 Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
726 ReleaseProcessIfNeeded();
729 void ChromeContentUtilityClient::OnParseJSON(const std::string
& json
) {
732 base::Value
* value
= base::JSONReader::ReadAndReturnError(
733 json
, base::JSON_PARSE_RFC
, &error_code
, &error
);
735 base::ListValue wrapper
;
736 wrapper
.Append(value
);
737 Send(new ChromeUtilityHostMsg_ParseJSON_Succeeded(wrapper
));
739 Send(new ChromeUtilityHostMsg_ParseJSON_Failed(error
));
741 ReleaseProcessIfNeeded();
744 void ChromeContentUtilityClient::OnGetPrinterCapsAndDefaults(
745 const std::string
& printer_name
) {
746 #if defined(ENABLE_FULL_PRINTING)
747 scoped_refptr
<printing::PrintBackend
> print_backend
=
748 printing::PrintBackend::CreateInstance(NULL
);
749 printing::PrinterCapsAndDefaults printer_info
;
751 crash_keys::ScopedPrinterInfo
crash_key(
752 print_backend
->GetPrinterDriverInfo(printer_name
));
754 if (print_backend
->GetPrinterCapsAndDefaults(printer_name
, &printer_info
)) {
755 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(
756 printer_name
, printer_info
));
760 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed(
763 ReleaseProcessIfNeeded();
766 void ChromeContentUtilityClient::OnGetPrinterSemanticCapsAndDefaults(
767 const std::string
& printer_name
) {
768 #if defined(ENABLE_FULL_PRINTING)
769 scoped_refptr
<printing::PrintBackend
> print_backend
=
770 printing::PrintBackend::CreateInstance(NULL
);
771 printing::PrinterSemanticCapsAndDefaults printer_info
;
773 crash_keys::ScopedPrinterInfo
crash_key(
774 print_backend
->GetPrinterDriverInfo(printer_name
));
776 if (print_backend
->GetPrinterSemanticCapsAndDefaults(printer_name
,
778 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded(
779 printer_name
, printer_info
));
783 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed(
786 ReleaseProcessIfNeeded();
789 void ChromeContentUtilityClient::OnStartupPing() {
790 Send(new ChromeUtilityHostMsg_ProcessStarted
);
791 // Don't release the process, we assume further messages are on the way.
794 void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
795 const IPC::PlatformFileForTransit
& zip_file
) {
796 safe_browsing::zip_analyzer::Results results
;
797 safe_browsing::zip_analyzer::AnalyzeZipFile(
798 IPC::PlatformFileForTransitToPlatformFile(zip_file
), &results
);
799 Send(new ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished(
801 ReleaseProcessIfNeeded();
804 #if !defined(OS_ANDROID) && !defined(OS_IOS)
805 void ChromeContentUtilityClient::OnCheckMediaFile(
806 int64 milliseconds_of_decoding
,
807 const IPC::PlatformFileForTransit
& media_file
) {
808 media::MediaFileChecker
checker(
809 base::File(IPC::PlatformFileForTransitToPlatformFile(media_file
)));
810 const bool check_success
= checker
.Start(
811 base::TimeDelta::FromMilliseconds(milliseconds_of_decoding
));
812 Send(new ChromeUtilityHostMsg_CheckMediaFile_Finished(check_success
));
813 ReleaseProcessIfNeeded();
816 void ChromeContentUtilityClient::OnParseMediaMetadata(
817 const std::string
& mime_type
,
819 // Only one IPCDataSource may be created and added to the list of handlers.
820 CHECK(!media_metadata_parser_
);
821 metadata::IPCDataSource
* source
= new metadata::IPCDataSource(total_size
);
822 handlers_
.push_back(source
);
824 media_metadata_parser_
.reset(new metadata::MediaMetadataParser(source
,
826 media_metadata_parser_
->Start(base::Bind(&SendMediaMetadataToHost
));
828 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
831 void ChromeContentUtilityClient::OnParseITunesPrefXml(
832 const std::string
& itunes_xml_data
) {
833 base::FilePath
library_path(
834 itunes::FindLibraryLocationInPrefXml(itunes_xml_data
));
835 Send(new ChromeUtilityHostMsg_GotITunesDirectory(library_path
));
836 ReleaseProcessIfNeeded();
838 #endif // defined(OS_WIN)
840 #if defined(OS_MACOSX)
841 void ChromeContentUtilityClient::OnParseIPhotoLibraryXmlFile(
842 const IPC::PlatformFileForTransit
& iphoto_library_file
) {
843 iphoto::IPhotoLibraryParser parser
;
844 base::PlatformFile file
=
845 IPC::PlatformFileForTransitToPlatformFile(iphoto_library_file
);
846 bool result
= parser
.Parse(iapps::ReadPlatformFileAsString(file
));
847 Send(new ChromeUtilityHostMsg_GotIPhotoLibrary(result
, parser
.library()));
848 ReleaseProcessIfNeeded();
850 #endif // defined(OS_MACOSX)
852 #if defined(OS_WIN) || defined(OS_MACOSX)
853 void ChromeContentUtilityClient::OnParseITunesLibraryXmlFile(
854 const IPC::PlatformFileForTransit
& itunes_library_file
) {
855 itunes::ITunesLibraryParser parser
;
856 base::PlatformFile file
=
857 IPC::PlatformFileForTransitToPlatformFile(itunes_library_file
);
858 bool result
= parser
.Parse(iapps::ReadPlatformFileAsString(file
));
859 Send(new ChromeUtilityHostMsg_GotITunesLibrary(result
, parser
.library()));
860 ReleaseProcessIfNeeded();
863 void ChromeContentUtilityClient::OnParsePicasaPMPDatabase(
864 const picasa::AlbumTableFilesForTransit
& album_table_files
) {
865 picasa::AlbumTableFiles files
;
866 files
.indicator_file
= IPC::PlatformFileForTransitToPlatformFile(
867 album_table_files
.indicator_file
);
868 files
.category_file
= IPC::PlatformFileForTransitToPlatformFile(
869 album_table_files
.category_file
);
870 files
.date_file
= IPC::PlatformFileForTransitToPlatformFile(
871 album_table_files
.date_file
);
872 files
.filename_file
= IPC::PlatformFileForTransitToPlatformFile(
873 album_table_files
.filename_file
);
874 files
.name_file
= IPC::PlatformFileForTransitToPlatformFile(
875 album_table_files
.name_file
);
876 files
.token_file
= IPC::PlatformFileForTransitToPlatformFile(
877 album_table_files
.token_file
);
878 files
.uid_file
= IPC::PlatformFileForTransitToPlatformFile(
879 album_table_files
.uid_file
);
881 picasa::PicasaAlbumTableReader
reader(files
);
882 bool parse_success
= reader
.Init();
883 Send(new ChromeUtilityHostMsg_ParsePicasaPMPDatabase_Finished(
887 ReleaseProcessIfNeeded();
890 void ChromeContentUtilityClient::OnIndexPicasaAlbumsContents(
891 const picasa::AlbumUIDSet
& album_uids
,
892 const std::vector
<picasa::FolderINIContents
>& folders_inis
) {
893 picasa::PicasaAlbumsIndexer
indexer(album_uids
);
894 indexer
.ParseFolderINI(folders_inis
);
896 Send(new ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished(
897 indexer
.albums_images()));
898 ReleaseProcessIfNeeded();
900 #endif // defined(OS_WIN) || defined(OS_MACOSX)
902 } // namespace chrome