15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/utility/chrome_content_utility_client.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/files/file_path.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/time/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_utility_messages.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/safe_browsing/zip_analyzer.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/utility/chrome_content_utility_ipc_whitelist.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/utility/utility_message_handler.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/utility/web_resource_unpacker.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/child/image_decoder_utils.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/common/content_switches.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/utility/utility_thread.h"
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "courgette/courgette.h"
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "courgette/third_party/bsdiff.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ipc/ipc_channel.h"
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "skia/ext/image_operations.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/zlib/google/zip.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/jpeg_codec.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/size.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined(OS_ANDROID)
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/utility/profile_import_handler.h"
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_WIN)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/utility/shell_handler_win.h"
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/chrome_utility_extensions_messages.h"
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/utility/extensions/extensions_handler.h"
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/utility/image_writer/image_writer_handler.h"
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/utility/media_galleries/ipc_data_source.h"
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/utility/media_galleries/media_metadata_parser.h"
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_FULL_PRINTING) || defined(OS_WIN)
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/utility/printing_handler.h"
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(ENABLE_MDNS)
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/utility/local_discovery/service_discovery_message_handler.h"
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool Send(IPC::Message* message) {
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return content::UtilityThread::Get()->Send(message);
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ReleaseProcessIfNeeded() {
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::UtilityThread::Get()->ReleaseProcessIfNeeded();
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void FinishParseMediaMetadata(
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    metadata::MediaMetadataParser* /* parser */,
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const extensions::api::media_galleries::MediaMetadata& metadata,
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<metadata::AttachedImage>& attached_images) {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Send(new ChromeUtilityHostMsg_ParseMediaMetadata_Finished(
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      true, *metadata.ToValue(), attached_images));
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ReleaseProcessIfNeeded();
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint64_t ChromeContentUtilityClient::max_ipc_message_size_ =
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    IPC::Channel::kMaximumMessageSize;
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChromeContentUtilityClient::ChromeContentUtilityClient()
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : filter_messages_(false) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  handlers_.push_back(new ProfileImportHandler());
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  handlers_.push_back(new extensions::ExtensionsHandler());
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  handlers_.push_back(new image_writer::ImageWriterHandler());
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_FULL_PRINTING) || defined(OS_WIN)
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  handlers_.push_back(new PrintingHandler());
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(ENABLE_MDNS)
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          switches::kUtilityProcessEnableMDns)) {
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    handlers_.push_back(new local_discovery::ServiceDiscoveryMessageHandler());
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_WIN)
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  handlers_.push_back(new ShellHandler());
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeContentUtilityClient::~ChromeContentUtilityClient() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeContentUtilityClient::UtilityThreadStarted() {
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  extensions::ExtensionsHandler::UtilityThreadStarted();
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (kMessageWhitelistSize > 0) {
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (command_line->HasSwitch(switches::kUtilityProcessRunningElevated)) {
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      message_id_whitelist_.insert(kMessageWhitelist,
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                   kMessageWhitelist + kMessageWhitelistSize);
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      filter_messages_ = true;
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChromeContentUtilityClient::OnMessageReceived(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPC::Message& message) {
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (filter_messages_ && !ContainsKey(message_id_whitelist_, message.type()))
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient, message)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackWebResource,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnUnpackWebResource)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_DecodeImage, OnDecodeImage)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RobustJPEGDecodeImage,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnRobustJPEGDecodeImage)
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileBsdiff,
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                        OnPatchFileBsdiff)
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileCourgette,
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                        OnPatchFileCourgette)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing)
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(FULL_SAFE_BROWSING)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnAnalyzeZipFileForDownloadProtection)
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseMediaMetadata,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        OnParseMediaMetadata)
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile, OnCreateZipFile)
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (Handlers::iterator it = handlers_.begin();
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       !handled && it != handlers_.end(); ++it) {
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    handled = (*it)->OnMessageReceived(message);
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ChromeContentUtilityClient::PreSandboxStartup() {
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  extensions::ExtensionsHandler::PreSandboxStartup();
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_FULL_PRINTING) || defined(OS_WIN)
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PrintingHandler::PreSandboxStartup();
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(ENABLE_MDNS)
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          switches::kUtilityProcessEnableMDns)) {
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    local_discovery::ServiceDiscoveryMessageHandler::PreSandboxStartup();
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif  // ENABLE_MDNS
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSkBitmap ChromeContentUtilityClient::DecodeImage(
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<unsigned char>& encoded_data, bool shrink_to_fit) {
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkBitmap decoded_image = content::DecodeImage(&encoded_data[0],
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                gfx::Size(),
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                encoded_data.size());
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int64_t struct_size = sizeof(ChromeUtilityHostMsg_DecodeImage_Succeeded);
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int64_t image_size = decoded_image.computeSize64();
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int halves = 0;
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (struct_size + (image_size >> 2*halves) > max_ipc_message_size_)
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    halves++;
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (halves) {
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (shrink_to_fit) {
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // If decoded image is too large for IPC message, shrink it by halves.
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // This prevents quality loss, and should never overshrink on displays
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // smaller than 3600x2400.
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // TODO (Issue 416916): Instead of shrinking, return via shared memory
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      decoded_image = skia::ImageOperations::Resize(
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          decoded_image, skia::ImageOperations::RESIZE_LANCZOS3,
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          decoded_image.width() >> halves, decoded_image.height() >> halves);
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Image too big for IPC message, but caller didn't request resize;
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // pre-delete image so DecodeImageAndSend() will send an error.
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      decoded_image.reset();
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      LOG(ERROR) << "Decoded image too large for IPC message";
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return decoded_image;
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ChromeContentUtilityClient::DecodeImageAndSend(
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<unsigned char>& encoded_data, bool shrink_to_fit){
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkBitmap decoded_image = DecodeImage(encoded_data, shrink_to_fit);
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (decoded_image.empty()) {
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(decoded_image));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ReleaseProcessIfNeeded();
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeContentUtilityClient::OnUnpackWebResource(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& resource_data) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse json data.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mrc): Add the possibility of a template that controls parsing, and
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the ability to download and verify images.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebResourceUnpacker unpacker(resource_data);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unpacker.Run()) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new ChromeUtilityHostMsg_UnpackWebResource_Succeeded(
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *unpacker.parsed_json()));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new ChromeUtilityHostMsg_UnpackWebResource_Failed(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unpacker.error_message()));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ReleaseProcessIfNeeded();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeContentUtilityClient::OnDecodeImage(
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<unsigned char>& encoded_data, bool shrink_to_fit) {
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DecodeImageAndSend(encoded_data, shrink_to_fit);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeContentUtilityClient::OnCreateZipFile(
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& src_dir,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<base::FilePath>& src_relative_paths,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FileDescriptor& dest_fd) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool succeeded = true;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check sanity of source relative paths. Reject if path is absolute or
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // contains any attempt to reference a parent directory ("../" tricks).
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<base::FilePath>::const_iterator iter =
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           src_relative_paths.begin(); iter != src_relative_paths.end();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (iter->IsAbsolute() || iter->ReferencesParent()) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      succeeded = false;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (succeeded)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    succeeded = zip::ZipFiles(src_dir, src_relative_paths, dest_fd.fd);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (succeeded)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Send(new ChromeUtilityHostMsg_CreateZipFile_Succeeded());
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Send(new ChromeUtilityHostMsg_CreateZipFile_Failed());
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ReleaseProcessIfNeeded();
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(OS_CHROMEOS)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeContentUtilityClient::OnRobustJPEGDecodeImage(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<unsigned char>& encoded_data) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our robust jpeg decoding is using IJG libjpeg.
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (gfx::JPEGCodec::JpegLibraryVariant() == gfx::JPEGCodec::IJG_LIBJPEG &&
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !encoded_data.empty()) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SkBitmap> decoded_image(gfx::JPEGCodec::Decode(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &encoded_data[0], encoded_data.size()));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!decoded_image.get() || decoded_image->empty()) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Send(new ChromeUtilityHostMsg_DecodeImage_Succeeded(*decoded_image));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Send(new ChromeUtilityHostMsg_DecodeImage_Failed());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ReleaseProcessIfNeeded();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ChromeContentUtilityClient::OnPatchFileBsdiff(
295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& input_file,
296effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& patch_file,
297effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& output_file) {
298effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (input_file.empty() || patch_file.empty() || output_file.empty()) {
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Send(new ChromeUtilityHostMsg_PatchFile_Finished(-1));
300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const int patch_status = courgette::ApplyBinaryPatch(input_file,
302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                         patch_file,
303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                         output_file);
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Send(new ChromeUtilityHostMsg_PatchFile_Finished(patch_status));
305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ReleaseProcessIfNeeded();
307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ChromeContentUtilityClient::OnPatchFileCourgette(
310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& input_file,
311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& patch_file,
312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::FilePath& output_file) {
313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (input_file.empty() || patch_file.empty() || output_file.empty()) {
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Send(new ChromeUtilityHostMsg_PatchFile_Finished(-1));
315effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } else {
316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const int patch_status = courgette::ApplyEnsemblePatch(
317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        input_file.value().c_str(),
318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        patch_file.value().c_str(),
319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        output_file.value().c_str());
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Send(new ChromeUtilityHostMsg_PatchFile_Finished(patch_status));
321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ReleaseProcessIfNeeded();
323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeContentUtilityClient::OnStartupPing() {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Send(new ChromeUtilityHostMsg_ProcessStarted);
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't release the process, we assume further messages are on the way.
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(FULL_SAFE_BROWSING)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const IPC::PlatformFileForTransit& zip_file) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  safe_browsing::zip_analyzer::Results results;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  safe_browsing::zip_analyzer::AnalyzeZipFile(
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      IPC::PlatformFileForTransitToFile(zip_file), &results);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Send(new ChromeUtilityHostMsg_AnalyzeZipFileForDownloadProtection_Finished(
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      results));
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ReleaseProcessIfNeeded();
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(ENABLE_EXTENSIONS)
343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// TODO(thestig): Try to move this to
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// chrome/utility/extensions/extensions_handler.cc.
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ChromeContentUtilityClient::OnParseMediaMetadata(
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& mime_type, int64 total_size, bool get_attached_images) {
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only one IPCDataSource may be created and added to the list of handlers.
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  metadata::IPCDataSource* source = new metadata::IPCDataSource(total_size);
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  handlers_.push_back(source);
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metadata::MediaMetadataParser* parser = new metadata::MediaMetadataParser(
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      source, mime_type, get_attached_images);
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  parser->Start(base::Bind(&FinishParseMediaMetadata, base::Owned(parser)));
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
356