12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/strings/string_number_conversions.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/win/hwnd_util.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_WIN)
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Name of the command line switch used to pass handle of the native view to
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// the native messaging host.
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char kParentWindowSwitchName[] = "parent-window";
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif  // defined(OS_WIN)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default implementation on NativeProcessLauncher interface.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NativeProcessLauncherImpl : public NativeProcessLauncher {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NativeProcessLauncherImpl(bool allow_user_level_hosts,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            intptr_t native_window);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~NativeProcessLauncherImpl();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Launch(const GURL& origin,
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      const std::string& native_host_name,
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      LaunchedCallback callback) const OVERRIDE;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class Core : public base::RefCountedThreadSafe<Core> {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Core(bool allow_user_level_hosts, intptr_t native_window);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void Launch(const GURL& origin,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                const std::string& native_host_name,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                LaunchedCallback callback);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void Detach();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   private:
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    friend class base::RefCountedThreadSafe<Core>;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~Core();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void DoLaunchOnThreadPool(const GURL& origin,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const std::string& native_host_name,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              LaunchedCallback callback);
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    void PostErrorResult(const LaunchedCallback& callback, LaunchResult error);
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    void PostResult(const LaunchedCallback& callback,
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                    base::ProcessHandle process_handle,
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    base::File read_file,
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    base::File write_file);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void CallCallbackOnIOThread(LaunchedCallback callback,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                LaunchResult result,
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                base::ProcessHandle process_handle,
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                base::File read_file,
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                base::File write_file);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool detached_;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool allow_user_level_hosts_;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Handle of the native window corresponding to the extension.
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    intptr_t window_handle_;
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Core);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<Core> core_;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NativeProcessLauncherImpl);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NativeProcessLauncherImpl::Core::Core(bool allow_user_level_hosts,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      intptr_t window_handle)
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : detached_(false),
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      allow_user_level_hosts_(allow_user_level_hosts),
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window_handle_(window_handle) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NativeProcessLauncherImpl::Core::~Core() {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(detached_);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NativeProcessLauncherImpl::Core::Detach() {
102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  detached_ = true;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NativeProcessLauncherImpl::Core::Launch(
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& native_host_name,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LaunchedCallback callback) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostBlockingPoolTask(
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&Core::DoLaunchOnThreadPool, this,
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            origin, native_host_name, callback));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool(
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& origin,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& native_host_name,
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LaunchedCallback callback) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!NativeMessagingHostManifest::IsValidName(native_host_name)) {
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_INVALID_NAME);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string error_message;
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::FilePath manifest_path =
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      FindManifest(native_host_name, allow_user_level_hosts_, &error_message);
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (manifest_path.empty()) {
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(ERROR) << "Can't find manifest for native messaging host "
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << native_host_name;
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_NOT_FOUND);
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_ptr<NativeMessagingHostManifest> manifest =
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      NativeMessagingHostManifest::Load(manifest_path, &error_message);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!manifest) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Failed to load manifest for native messaging host "
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << native_host_name << ": " << error_message;
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_NOT_FOUND);
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (manifest->name() != native_host_name) {
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(ERROR) << "Failed to load manifest for native messaging host "
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << native_host_name
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << ": Invalid name specified in the manifest.";
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_NOT_FOUND);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!manifest->allowed_origins().MatchesSecurityOrigin(origin)) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Not an allowed origin.
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_FORBIDDEN);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::FilePath host_path = manifest->path();
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!host_path.IsAbsolute()) {
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // On Windows host path is allowed to be relative to the location of the
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // manifest file. On all other platforms the path must be absolute.
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_WIN)
166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    host_path = manifest_path.DirName().Append(host_path);
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#else  // defined(OS_WIN)
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(ERROR) << "Native messaging host path must be absolute for "
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << native_host_name;
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_NOT_FOUND);
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif  // !defined(OS_WIN)
173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // In case when the manifest file is there, but the host binary doesn't exist
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // report the NOT_FOUND error.
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!base::PathExists(host_path)) {
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR)
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << "Found manifest, but not the binary for native messaging host "
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << native_host_name << ". Host path specified in the manifest: "
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << host_path.AsUTF8Unsafe();
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    PostErrorResult(callback, RESULT_NOT_FOUND);
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  CommandLine command_line(host_path);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  command_line.AppendArg(origin.spec());
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Pass handle of the native view window to the native messaging host. This
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // way the host will be able to create properly focused UI windows.
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if defined(OS_WIN)
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  command_line.AppendSwitchASCII(kParentWindowSwitchName,
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 base::Int64ToString(window_handle_));
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif  // !defined(OS_WIN)
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::ProcessHandle process_handle;
19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::File read_file;
19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::File write_file;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NativeProcessLauncher::LaunchNativeProcess(
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          command_line, &process_handle, &read_file, &write_file)) {
20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    PostResult(callback, process_handle, read_file.Pass(), write_file.Pass());
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  } else {
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    PostErrorResult(callback, RESULT_FAILED_TO_START);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NativeProcessLauncherImpl::Core::CallCallbackOnIOThread(
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LaunchedCallback callback,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LaunchResult result,
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::ProcessHandle process_handle,
21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::File read_file,
21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::File write_file) {
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (detached_)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  callback.Run(result, process_handle, read_file.Pass(), write_file.Pass());
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void NativeProcessLauncherImpl::Core::PostErrorResult(
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const LaunchedCallback& callback,
222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LaunchResult error) {
223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::BrowserThread::PostTask(
224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::BrowserThread::IO, FROM_HERE,
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, this,
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 callback, error, base::kNullProcessHandle,
22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 Passed(base::File()), Passed(base::File())));
228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void NativeProcessLauncherImpl::Core::PostResult(
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const LaunchedCallback& callback,
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::ProcessHandle process_handle,
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::File read_file,
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::File write_file) {
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  content::BrowserThread::PostTask(
236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      content::BrowserThread::IO, FROM_HERE,
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread, this,
23823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 callback, RESULT_SUCCESS, process_handle,
23923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 Passed(read_file.Pass()), Passed(write_file.Pass())));
240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochNativeProcessLauncherImpl::NativeProcessLauncherImpl(
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool allow_user_level_hosts,
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    intptr_t window_handle)
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : core_(new Core(allow_user_level_hosts, window_handle)) {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NativeProcessLauncherImpl::~NativeProcessLauncherImpl() {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core_->Detach();
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NativeProcessLauncherImpl::Launch(const GURL& origin,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& native_host_name,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       LaunchedCallback callback) const {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core_->Launch(origin, native_host_name, callback);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochscoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault(
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool allow_user_level_hosts,
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    gfx::NativeView native_view) {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  intptr_t window_handle = 0;
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window_handle = reinterpret_cast<intptr_t>(
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      views::HWNDForNativeView(native_view));
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return scoped_ptr<NativeProcessLauncher>(
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new NativeProcessLauncherImpl(allow_user_level_hosts, window_handle));
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
274