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