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