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_itunes_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 chrome::MediaFileSystemBackend; 14 using content::BrowserThread; 15 using content::UtilityProcessHost; 16 17 namespace itunes { 18 19 SafeITunesLibraryParser::SafeITunesLibraryParser( 20 const base::FilePath& itunes_library_file, 21 const ParserCallback& callback) 22 : itunes_library_file_(itunes_library_file), 23 callback_(callback), 24 parser_state_(INITIAL_STATE) {} 25 26 void SafeITunesLibraryParser::Start() { 27 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); 28 29 // |itunes_library_platform_file_| will be closed on the IO thread once it 30 // has been handed off to the child process. 31 itunes_library_platform_file_ = base::CreatePlatformFile( 32 itunes_library_file_, 33 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, 34 NULL, // created 35 NULL); // error_code 36 if (itunes_library_platform_file_ == base::kInvalidPlatformFileValue) { 37 VLOG(1) << "Could not open iTunes library XML file: " 38 << itunes_library_file_.value(); 39 callback_.Run(false /* failed */, parser::Library()); 40 BrowserThread::PostTask( 41 BrowserThread::IO, FROM_HERE, 42 base::Bind(&SafeITunesLibraryParser::OnOpenLibraryFileFailed, this)); 43 return; 44 } 45 46 BrowserThread::PostTask( 47 BrowserThread::IO, FROM_HERE, 48 base::Bind(&SafeITunesLibraryParser::StartProcessOnIOThread, this)); 49 } 50 51 SafeITunesLibraryParser::~SafeITunesLibraryParser() {} 52 53 void SafeITunesLibraryParser::StartProcessOnIOThread() { 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 55 DCHECK_EQ(INITIAL_STATE, parser_state_); 56 57 scoped_refptr<base::MessageLoopProxy> message_loop_proxy = 58 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 59 utility_process_host_ = 60 UtilityProcessHost::Create(this, message_loop_proxy.get())->AsWeakPtr(); 61 // Wait for the startup notification before sending the main IPC to the 62 // utility process, so that we can dup the file handle. 63 utility_process_host_->Send(new ChromeUtilityMsg_StartupPing); 64 parser_state_ = PINGED_UTILITY_PROCESS_STATE; 65 } 66 67 void SafeITunesLibraryParser::OnUtilityProcessStarted() { 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 69 if (parser_state_ != PINGED_UTILITY_PROCESS_STATE) 70 return; 71 72 if (utility_process_host_->GetData().handle == base::kNullProcessHandle) 73 DLOG(ERROR) << "Child process handle is null"; 74 utility_process_host_->Send( 75 new ChromeUtilityMsg_ParseITunesLibraryXmlFile( 76 IPC::GetFileHandleForProcess( 77 itunes_library_platform_file_, 78 utility_process_host_->GetData().handle, 79 true /* close_source_handle */))); 80 parser_state_ = STARTED_PARSING_STATE; 81 } 82 83 void SafeITunesLibraryParser::OnGotITunesLibrary( 84 bool result, const parser::Library& library) { 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 86 87 if (parser_state_ != STARTED_PARSING_STATE) 88 return; 89 90 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 91 FROM_HERE, 92 base::Bind(callback_, result, library)); 93 parser_state_ = FINISHED_PARSING_STATE; 94 } 95 96 void SafeITunesLibraryParser::OnOpenLibraryFileFailed() { 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 98 parser_state_ = FINISHED_PARSING_STATE; 99 } 100 101 void SafeITunesLibraryParser::OnProcessCrashed(int exit_code) { 102 OnGotITunesLibrary(false /* failed */, parser::Library()); 103 } 104 105 bool SafeITunesLibraryParser::OnMessageReceived( 106 const IPC::Message& message) { 107 bool handled = true; 108 IPC_BEGIN_MESSAGE_MAP(SafeITunesLibraryParser, message) 109 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, 110 OnUtilityProcessStarted) 111 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GotITunesLibrary, 112 OnGotITunesLibrary) 113 IPC_MESSAGE_UNHANDLED(handled = false) 114 IPC_END_MESSAGE_MAP() 115 return handled; 116 } 117 118 } // namespace itunes 119