• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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.
4 
5 #include "chrome/browser/media_galleries/fileapi/safe_iapps_library_parser.h"
6 
7 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
8 #include "chrome/common/chrome_utility_messages.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/browser/child_process_data.h"
11 #include "ipc/ipc_platform_file.h"
12 
13 using content::BrowserThread;
14 using content::UtilityProcessHost;
15 
16 namespace iapps {
17 
SafeIAppsLibraryParser()18 SafeIAppsLibraryParser::SafeIAppsLibraryParser()
19     : parser_state_(INITIAL_STATE) {}
20 
ParseIPhotoLibrary(const base::FilePath & library_file,const IPhotoParserCallback & callback)21 void SafeIAppsLibraryParser::ParseIPhotoLibrary(
22     const base::FilePath& library_file,
23     const IPhotoParserCallback& callback) {
24   library_file_path_ = library_file;
25   iphoto_callback_ = callback;
26   Start();
27 }
28 
ParseITunesLibrary(const base::FilePath & library_file,const ITunesParserCallback & callback)29 void SafeIAppsLibraryParser::ParseITunesLibrary(
30     const base::FilePath& library_file,
31     const ITunesParserCallback& callback) {
32   library_file_path_ = library_file;
33   itunes_callback_ = callback;
34   Start();
35 }
36 
Start()37 void SafeIAppsLibraryParser::Start() {
38   DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
39 
40   // |library_file_| will be closed on the IO thread once it has been handed
41   // off to the child process.
42   library_file_.Initialize(library_file_path_,
43                            base::File::FLAG_OPEN | base::File::FLAG_READ);
44   if (!library_file_.IsValid()) {
45     VLOG(1) << "Could not open iApps library XML file: "
46             << library_file_path_.value();
47     BrowserThread::PostTask(
48         BrowserThread::IO, FROM_HERE,
49         base::Bind(&SafeIAppsLibraryParser::OnOpenLibraryFileFailed, this));
50     return;
51   }
52 
53   BrowserThread::PostTask(
54       BrowserThread::IO, FROM_HERE,
55       base::Bind(&SafeIAppsLibraryParser::StartProcessOnIOThread, this));
56 }
57 
~SafeIAppsLibraryParser()58 SafeIAppsLibraryParser::~SafeIAppsLibraryParser() {}
59 
StartProcessOnIOThread()60 void SafeIAppsLibraryParser::StartProcessOnIOThread() {
61   DCHECK_CURRENTLY_ON(BrowserThread::IO);
62   DCHECK_EQ(INITIAL_STATE, parser_state_);
63 
64   scoped_refptr<base::MessageLoopProxy> message_loop_proxy =
65       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
66   utility_process_host_ =
67       UtilityProcessHost::Create(this, message_loop_proxy.get())->AsWeakPtr();
68   // Wait for the startup notification before sending the main IPC to the
69   // utility process, so that we can dup the file handle.
70   utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
71   parser_state_ = PINGED_UTILITY_PROCESS_STATE;
72 }
73 
OnUtilityProcessStarted()74 void SafeIAppsLibraryParser::OnUtilityProcessStarted() {
75   DCHECK_CURRENTLY_ON(BrowserThread::IO);
76   if (parser_state_ != PINGED_UTILITY_PROCESS_STATE)
77     return;
78 
79   if (utility_process_host_->GetData().handle == base::kNullProcessHandle) {
80     DLOG(ERROR) << "Child process handle is null";
81     OnError();
82     return;
83   }
84 
85   if (!itunes_callback_.is_null()) {
86     utility_process_host_->Send(
87         new ChromeUtilityMsg_ParseITunesLibraryXmlFile(
88             IPC::TakeFileHandleForProcess(
89                 library_file_.Pass(),
90                 utility_process_host_->GetData().handle)));
91   } else if (!iphoto_callback_.is_null()) {
92 #if defined(OS_MACOSX)
93     utility_process_host_->Send(
94         new ChromeUtilityMsg_ParseIPhotoLibraryXmlFile(
95             IPC::TakeFileHandleForProcess(
96                 library_file_.Pass(),
97                 utility_process_host_->GetData().handle)));
98 #endif
99   }
100 
101   parser_state_ = STARTED_PARSING_STATE;
102 }
103 
104 #if defined(OS_MACOSX)
OnGotIPhotoLibrary(bool result,const iphoto::parser::Library & library)105 void SafeIAppsLibraryParser::OnGotIPhotoLibrary(
106     bool result, const iphoto::parser::Library& library) {
107   DCHECK_CURRENTLY_ON(BrowserThread::IO);
108   DCHECK(!iphoto_callback_.is_null());
109 
110   if (parser_state_ != STARTED_PARSING_STATE)
111     return;
112 
113   MediaFileSystemBackend::MediaTaskRunner()->PostTask(
114       FROM_HERE,
115       base::Bind(iphoto_callback_, result, library));
116   parser_state_ = FINISHED_PARSING_STATE;
117 }
118 #endif
119 
OnGotITunesLibrary(bool result,const itunes::parser::Library & library)120 void SafeIAppsLibraryParser::OnGotITunesLibrary(
121     bool result, const itunes::parser::Library& library) {
122   DCHECK_CURRENTLY_ON(BrowserThread::IO);
123   DCHECK(!itunes_callback_.is_null());
124 
125   if (parser_state_ != STARTED_PARSING_STATE)
126     return;
127 
128   MediaFileSystemBackend::MediaTaskRunner()->PostTask(
129       FROM_HERE,
130       base::Bind(itunes_callback_, result, library));
131   parser_state_ = FINISHED_PARSING_STATE;
132 }
133 
OnOpenLibraryFileFailed()134 void SafeIAppsLibraryParser::OnOpenLibraryFileFailed() {
135   DCHECK_CURRENTLY_ON(BrowserThread::IO);
136   OnError();
137 }
138 
OnProcessCrashed(int exit_code)139 void SafeIAppsLibraryParser::OnProcessCrashed(int exit_code) {
140   OnError();
141 }
142 
OnError()143 void SafeIAppsLibraryParser::OnError() {
144   parser_state_ = FINISHED_PARSING_STATE;
145   if (!itunes_callback_.is_null())
146     OnGotITunesLibrary(false /* failed */, itunes::parser::Library());
147 
148 #if defined(OS_MACOSX)
149   if (!iphoto_callback_.is_null())
150     OnGotIPhotoLibrary(false /* failed */, iphoto::parser::Library());
151 #endif
152 }
153 
OnMessageReceived(const IPC::Message & message)154 bool SafeIAppsLibraryParser::OnMessageReceived(
155     const IPC::Message& message) {
156   bool handled = true;
157   IPC_BEGIN_MESSAGE_MAP(SafeIAppsLibraryParser, message)
158     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
159                         OnUtilityProcessStarted)
160 #if defined(OS_MACOSX)
161     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotIPhotoLibrary,
162                         OnGotIPhotoLibrary)
163 #endif
164     IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotITunesLibrary,
165                         OnGotITunesLibrary)
166     IPC_MESSAGE_UNHANDLED(handled = false)
167   IPC_END_MESSAGE_MAP()
168   return handled;
169 }
170 
171 }  // namespace iapps
172