18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h"
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/common/chrome_utility_messages.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/chrome_utility_extensions_messages.h"
108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/child_process_data.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ipc/ipc_platform_file.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)using content::BrowserThread;
158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)using content::UtilityProcessHost;
168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace iapps {
188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)SafeIAppsLibraryParser::SafeIAppsLibraryParser()
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : parser_state_(INITIAL_STATE) {}
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::ParseIPhotoLibrary(
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const base::FilePath& library_file,
248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const IPhotoParserCallback& callback) {
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  library_file_path_ = library_file;
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  iphoto_callback_ = callback;
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  Start();
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::ParseITunesLibrary(
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const base::FilePath& library_file,
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const ITunesParserCallback& callback) {
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  library_file_path_ = library_file;
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  itunes_callback_ = callback;
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  Start();
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::Start() {
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // |library_file_| will be closed on the IO thread once it has been handed
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // off to the child process.
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  library_file_.Initialize(library_file_path_,
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           base::File::FLAG_OPEN | base::File::FLAG_READ);
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!library_file_.IsValid()) {
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    VLOG(1) << "Could not open iApps library XML file: "
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            << library_file_path_.value();
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    BrowserThread::PostTask(
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        BrowserThread::IO, FROM_HERE,
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        base::Bind(&SafeIAppsLibraryParser::OnOpenLibraryFileFailed, this));
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  BrowserThread::PostTask(
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&SafeIAppsLibraryParser::StartProcessOnIOThread, this));
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)SafeIAppsLibraryParser::~SafeIAppsLibraryParser() {}
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::StartProcessOnIOThread() {
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK_EQ(INITIAL_STATE, parser_state_);
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> message_loop_proxy =
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  utility_process_host_ =
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      UtilityProcessHost::Create(this, message_loop_proxy.get())->AsWeakPtr();
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Wait for the startup notification before sending the main IPC to the
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // utility process, so that we can dup the file handle.
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  parser_state_ = PINGED_UTILITY_PROCESS_STATE;
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::OnUtilityProcessStarted() {
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (parser_state_ != PINGED_UTILITY_PROCESS_STATE)
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (utility_process_host_->GetData().handle == base::kNullProcessHandle) {
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DLOG(ERROR) << "Child process handle is null";
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    OnError();
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!itunes_callback_.is_null()) {
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    utility_process_host_->Send(
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        new ChromeUtilityMsg_ParseITunesLibraryXmlFile(
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            IPC::TakeFileHandleForProcess(
90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                library_file_.Pass(),
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                utility_process_host_->GetData().handle)));
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } else if (!iphoto_callback_.is_null()) {
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_MACOSX)
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    utility_process_host_->Send(
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        new ChromeUtilityMsg_ParseIPhotoLibraryXmlFile(
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            IPC::TakeFileHandleForProcess(
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                library_file_.Pass(),
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                utility_process_host_->GetData().handle)));
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  parser_state_ = STARTED_PARSING_STATE;
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_MACOSX)
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::OnGotIPhotoLibrary(
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    bool result, const iphoto::parser::Library& library) {
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!iphoto_callback_.is_null());
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (parser_state_ != STARTED_PARSING_STATE)
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  MediaFileSystemBackend::MediaTaskRunner()->PostTask(
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FROM_HERE,
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(iphoto_callback_, result, library));
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  parser_state_ = FINISHED_PARSING_STATE;
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::OnGotITunesLibrary(
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    bool result, const itunes::parser::Library& library) {
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!itunes_callback_.is_null());
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (parser_state_ != STARTED_PARSING_STATE)
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  MediaFileSystemBackend::MediaTaskRunner()->PostTask(
1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FROM_HERE,
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(itunes_callback_, result, library));
1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  parser_state_ = FINISHED_PARSING_STATE;
1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::OnOpenLibraryFileFailed() {
136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  OnError();
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::OnProcessCrashed(int exit_code) {
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  OnError();
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SafeIAppsLibraryParser::OnError() {
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  parser_state_ = FINISHED_PARSING_STATE;
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!itunes_callback_.is_null())
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    OnGotITunesLibrary(false /* failed */, itunes::parser::Library());
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_MACOSX)
1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!iphoto_callback_.is_null())
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    OnGotIPhotoLibrary(false /* failed */, iphoto::parser::Library());
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SafeIAppsLibraryParser::OnMessageReceived(
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const IPC::Message& message) {
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool handled = true;
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(SafeIAppsLibraryParser, message)
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        OnUtilityProcessStarted)
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_MACOSX)
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotIPhotoLibrary,
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        OnGotIPhotoLibrary)
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotITunesLibrary,
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        OnGotITunesLibrary)
1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  IPC_END_MESSAGE_MAP()
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return handled;
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace iapps
173