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 <vector>
8
9#include "base/basictypes.h"
10#include "base/memory/scoped_vector.h"
11#include "chrome/common/mac/app_shim_messages.h"
12#include "ipc/ipc_message.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace {
16
17class TestingAppShimHost : public AppShimHost {
18 public:
19  TestingAppShimHost() {}
20  virtual ~TestingAppShimHost() {}
21
22  bool ReceiveMessage(IPC::Message* message);
23
24  const std::vector<IPC::Message*>& sent_messages() {
25    return sent_messages_.get();
26  }
27
28 protected:
29  virtual bool Send(IPC::Message* message) OVERRIDE;
30
31 private:
32  ScopedVector<IPC::Message> sent_messages_;
33
34  DISALLOW_COPY_AND_ASSIGN(TestingAppShimHost);
35};
36
37bool TestingAppShimHost::ReceiveMessage(IPC::Message* message) {
38  bool handled = OnMessageReceived(*message);
39  delete message;
40  return handled;
41}
42
43bool TestingAppShimHost::Send(IPC::Message* message) {
44  sent_messages_.push_back(message);
45  return true;
46}
47
48const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
49const char kTestProfileDir[] = "Profile 1";
50
51class AppShimHostTest : public testing::Test,
52                        public apps::AppShimHandler {
53 public:
54  AppShimHostTest() : launch_result_(apps::APP_SHIM_LAUNCH_SUCCESS),
55                      launch_count_(0),
56                      launch_now_count_(0),
57                      close_count_(0),
58                      focus_count_(0),
59                      quit_count_(0) {}
60
61  TestingAppShimHost* host() { return host_.get(); }
62
63  void LaunchApp(apps::AppShimLaunchType launch_type) {
64    EXPECT_TRUE(host()->ReceiveMessage(
65        new AppShimHostMsg_LaunchApp(base::FilePath(kTestProfileDir),
66                                     kTestAppId,
67                                     launch_type,
68                                     std::vector<base::FilePath>())));
69  }
70
71  apps::AppShimLaunchResult GetLaunchResult() {
72    EXPECT_EQ(1u, host()->sent_messages().size());
73    IPC::Message* message = host()->sent_messages()[0];
74    EXPECT_EQ(AppShimMsg_LaunchApp_Done::ID, message->type());
75    AppShimMsg_LaunchApp_Done::Param param;
76    AppShimMsg_LaunchApp_Done::Read(message, &param);
77    return param.a;
78  }
79
80  void SimulateDisconnect() {
81    implicit_cast<IPC::Listener*>(host_.release())->OnChannelError();
82  }
83
84 protected:
85  virtual void OnShimLaunch(Host* host,
86                            apps::AppShimLaunchType launch_type,
87                            const std::vector<base::FilePath>& file) OVERRIDE {
88    ++launch_count_;
89    if (launch_type == apps::APP_SHIM_LAUNCH_NORMAL)
90      ++launch_now_count_;
91    host->OnAppLaunchComplete(launch_result_);
92  }
93
94  virtual void OnShimClose(Host* host) OVERRIDE { ++close_count_; }
95
96  virtual void OnShimFocus(Host* host,
97                           apps::AppShimFocusType focus_type,
98                           const std::vector<base::FilePath>& file) OVERRIDE {
99    ++focus_count_;
100  }
101
102  virtual void OnShimSetHidden(Host* host, bool hidden) OVERRIDE {}
103
104  virtual void OnShimQuit(Host* host) OVERRIDE { ++quit_count_; }
105
106  apps::AppShimLaunchResult launch_result_;
107  int launch_count_;
108  int launch_now_count_;
109  int close_count_;
110  int focus_count_;
111  int quit_count_;
112
113 private:
114  virtual void SetUp() OVERRIDE {
115    testing::Test::SetUp();
116    host_.reset(new TestingAppShimHost());
117  }
118
119  scoped_ptr<TestingAppShimHost> host_;
120
121  DISALLOW_COPY_AND_ASSIGN(AppShimHostTest);
122};
123
124
125}  // namespace
126
127TEST_F(AppShimHostTest, TestLaunchAppWithHandler) {
128  apps::AppShimHandler::RegisterHandler(kTestAppId, this);
129  LaunchApp(apps::APP_SHIM_LAUNCH_NORMAL);
130  EXPECT_EQ(kTestAppId,
131            implicit_cast<apps::AppShimHandler::Host*>(host())->GetAppId());
132  EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult());
133  EXPECT_EQ(1, launch_count_);
134  EXPECT_EQ(1, launch_now_count_);
135  EXPECT_EQ(0, focus_count_);
136  EXPECT_EQ(0, close_count_);
137
138  // A second OnAppLaunchComplete is ignored.
139  implicit_cast<apps::AppShimHandler::Host*>(host())->
140      OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_APP_NOT_FOUND);
141  EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult());
142
143  EXPECT_TRUE(host()->ReceiveMessage(
144      new AppShimHostMsg_FocusApp(apps::APP_SHIM_FOCUS_NORMAL,
145                                  std::vector<base::FilePath>())));
146  EXPECT_EQ(1, focus_count_);
147
148  EXPECT_TRUE(host()->ReceiveMessage(new AppShimHostMsg_QuitApp()));
149  EXPECT_EQ(1, quit_count_);
150
151  SimulateDisconnect();
152  EXPECT_EQ(1, close_count_);
153  apps::AppShimHandler::RemoveHandler(kTestAppId);
154}
155
156TEST_F(AppShimHostTest, TestNoLaunchNow) {
157  apps::AppShimHandler::RegisterHandler(kTestAppId, this);
158  LaunchApp(apps::APP_SHIM_LAUNCH_REGISTER_ONLY);
159  EXPECT_EQ(kTestAppId,
160            implicit_cast<apps::AppShimHandler::Host*>(host())->GetAppId());
161  EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult());
162  EXPECT_EQ(1, launch_count_);
163  EXPECT_EQ(0, launch_now_count_);
164  EXPECT_EQ(0, focus_count_);
165  EXPECT_EQ(0, close_count_);
166  apps::AppShimHandler::RemoveHandler(kTestAppId);
167}
168
169TEST_F(AppShimHostTest, TestFailLaunch) {
170  apps::AppShimHandler::RegisterHandler(kTestAppId, this);
171  launch_result_ = apps::APP_SHIM_LAUNCH_APP_NOT_FOUND;
172  LaunchApp(apps::APP_SHIM_LAUNCH_NORMAL);
173  EXPECT_EQ(apps::APP_SHIM_LAUNCH_APP_NOT_FOUND, GetLaunchResult());
174  apps::AppShimHandler::RemoveHandler(kTestAppId);
175}
176