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/apps/app_shim/app_shim_host_mac.h"
6
7#include "base/bind.h"
8#include "base/files/file_path.h"
9#include "base/logging.h"
10#include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
11#include "chrome/common/mac/app_shim_messages.h"
12#include "content/public/browser/browser_thread.h"
13#include "ipc/ipc_channel_proxy.h"
14
15AppShimHost::AppShimHost() : initial_launch_finished_(false) {}
16
17AppShimHost::~AppShimHost() {
18  DCHECK(CalledOnValidThread());
19  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
20  if (handler)
21    handler->OnShimClose(this);
22}
23
24void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) {
25  DCHECK(CalledOnValidThread());
26  DCHECK(!channel_.get());
27  channel_ = IPC::ChannelProxy::Create(
28      handle,
29      IPC::Channel::MODE_SERVER,
30      this,
31      content::BrowserThread::GetMessageLoopProxyForThread(
32          content::BrowserThread::IO).get());
33}
34
35base::FilePath AppShimHost::GetProfilePath() const {
36  return profile_path_;
37}
38
39std::string AppShimHost::GetAppId() const {
40  return app_id_;
41}
42
43bool AppShimHost::OnMessageReceived(const IPC::Message& message) {
44  DCHECK(CalledOnValidThread());
45  bool handled = true;
46  IPC_BEGIN_MESSAGE_MAP(AppShimHost, message)
47    IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp)
48    IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus)
49    IPC_MESSAGE_HANDLER(AppShimHostMsg_SetAppHidden, OnSetHidden)
50    IPC_MESSAGE_HANDLER(AppShimHostMsg_QuitApp, OnQuit)
51    IPC_MESSAGE_UNHANDLED(handled = false)
52  IPC_END_MESSAGE_MAP()
53
54  return handled;
55}
56
57void AppShimHost::OnChannelError() {
58  Close();
59}
60
61bool AppShimHost::Send(IPC::Message* message) {
62  DCHECK(channel_.get());
63  return channel_->Send(message);
64}
65
66void AppShimHost::OnLaunchApp(const base::FilePath& profile_dir,
67                              const std::string& app_id,
68                              apps::AppShimLaunchType launch_type,
69                              const std::vector<base::FilePath>& files) {
70  DCHECK(CalledOnValidThread());
71  DCHECK(profile_path_.empty());
72  // Only one app launch message per channel.
73  if (!profile_path_.empty())
74    return;
75
76  profile_path_ = profile_dir;
77  app_id_ = app_id;
78
79  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
80  if (handler)
81    handler->OnShimLaunch(this, launch_type, files);
82  // |handler| can only be NULL after AppShimHostManager is destroyed. Since
83  // this only happens at shutdown, do nothing here.
84}
85
86void AppShimHost::OnFocus(apps::AppShimFocusType focus_type,
87                          const std::vector<base::FilePath>& files) {
88  DCHECK(CalledOnValidThread());
89  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
90  if (handler)
91    handler->OnShimFocus(this, focus_type, files);
92}
93
94void AppShimHost::OnSetHidden(bool hidden) {
95  DCHECK(CalledOnValidThread());
96  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
97  if (handler)
98    handler->OnShimSetHidden(this, hidden);
99}
100
101void AppShimHost::OnQuit() {
102  DCHECK(CalledOnValidThread());
103  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
104  if (handler)
105    handler->OnShimQuit(this);
106}
107
108void AppShimHost::OnAppLaunchComplete(apps::AppShimLaunchResult result) {
109  if (!initial_launch_finished_) {
110    Send(new AppShimMsg_LaunchApp_Done(result));
111    initial_launch_finished_ = true;
112  }
113}
114
115void AppShimHost::OnAppClosed() {
116  Close();
117}
118
119void AppShimHost::OnAppHide() {
120  Send(new AppShimMsg_Hide);
121}
122
123void AppShimHost::OnAppRequestUserAttention(apps::AppShimAttentionType type) {
124  Send(new AppShimMsg_SetUserAttention(type));
125}
126
127void AppShimHost::Close() {
128  DCHECK(CalledOnValidThread());
129  delete this;
130}
131