Home | History | Annotate | Download | only in fileapi
      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