Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / app_controller_mac_browsertest.mm
1 // Copyright (c) 2012 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 #import <Carbon/Carbon.h>
6 #import <Cocoa/Cocoa.h>
7 #import <Foundation/Foundation.h>
8 #import <Foundation/NSAppleEventDescriptor.h>
9 #import <objc/message.h>
10 #import <objc/runtime.h>
11
12 #include "base/command_line.h"
13 #include "base/mac/foundation_util.h"
14 #include "base/mac/scoped_nsobject.h"
15 #include "base/prefs/pref_service.h"
16 #include "chrome/app/chrome_command_ids.h"
17 #import "chrome/browser/app_controller_mac.h"
18 #include "chrome/browser/apps/app_browsertest_util.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_list.h"
23 #include "chrome/browser/ui/browser_window.h"
24 #include "chrome/browser/ui/host_desktop.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/browser/ui/user_manager.h"
27 #include "chrome/common/chrome_constants.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/test/base/in_process_browser_test.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "components/signin/core/common/profile_management_switches.h"
34 #include "content/public/browser/web_contents.h"
35 #include "extensions/browser/app_window/app_window_registry.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/test/extension_test_message_listener.h"
38 #include "net/test/embedded_test_server/embedded_test_server.h"
39
40 namespace {
41
42 GURL g_open_shortcut_url = GURL::EmptyGURL();
43
44 }  // namespace
45
46 @interface TestOpenShortcutOnStartup : NSObject
47 - (void)applicationWillFinishLaunching:(NSNotification*)notification;
48 @end
49
50 @implementation TestOpenShortcutOnStartup
51
52 - (void)applicationWillFinishLaunching:(NSNotification*)notification {
53   if (!g_open_shortcut_url.is_valid())
54     return;
55
56   AppController* controller =
57       base::mac::ObjCCast<AppController>([NSApp delegate]);
58   Method getUrl = class_getInstanceMethod([controller class],
59       @selector(getUrl:withReply:));
60
61   if (getUrl == nil)
62     return;
63
64   base::scoped_nsobject<NSAppleEventDescriptor> shortcutEvent(
65       [[NSAppleEventDescriptor alloc]
66           initWithEventClass:kASAppleScriptSuite
67                      eventID:kASSubroutineEvent
68             targetDescriptor:nil
69                     returnID:kAutoGenerateReturnID
70                transactionID:kAnyTransactionID]);
71   NSString* url =
72       [NSString stringWithUTF8String:g_open_shortcut_url.spec().c_str()];
73   [shortcutEvent setParamDescriptor:
74       [NSAppleEventDescriptor descriptorWithString:url]
75                          forKeyword:keyDirectObject];
76
77   method_invoke(controller, getUrl, shortcutEvent.get(), NULL);
78 }
79
80 @end
81
82 namespace {
83
84 class AppControllerPlatformAppBrowserTest
85     : public extensions::PlatformAppBrowserTest {
86  protected:
87   AppControllerPlatformAppBrowserTest()
88       : active_browser_list_(BrowserList::GetInstance(
89                                 chrome::GetActiveDesktop())) {
90   }
91
92   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
93     PlatformAppBrowserTest::SetUpCommandLine(command_line);
94     command_line->AppendSwitchASCII(switches::kAppId,
95                                     "1234");
96   }
97
98   const BrowserList* active_browser_list_;
99 };
100
101 // Test that if only a platform app window is open and no browser windows are
102 // open then a reopen event does nothing.
103 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
104                        PlatformAppReopenWithWindows) {
105   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
106   NSUInteger old_window_count = [[NSApp windows] count];
107   EXPECT_EQ(1u, active_browser_list_->size());
108   [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:YES];
109   // We do not EXPECT_TRUE the result here because the method
110   // deminiaturizes windows manually rather than return YES and have
111   // AppKit do it.
112
113   EXPECT_EQ(old_window_count, [[NSApp windows] count]);
114   EXPECT_EQ(1u, active_browser_list_->size());
115 }
116
117 IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
118                        ActivationFocusesBrowserWindow) {
119   base::scoped_nsobject<AppController> app_controller(
120       [[AppController alloc] init]);
121
122   ExtensionTestMessageListener listener("Launched", false);
123   const extensions::Extension* app =
124       InstallAndLaunchPlatformApp("minimal");
125   ASSERT_TRUE(listener.WaitUntilSatisfied());
126
127   NSWindow* app_window = extensions::AppWindowRegistry::Get(profile())
128                              ->GetAppWindowsForApp(app->id())
129                              .front()
130                              ->GetNativeWindow();
131   NSWindow* browser_window = browser()->window()->GetNativeWindow();
132
133   EXPECT_LE([[NSApp orderedWindows] indexOfObject:app_window],
134             [[NSApp orderedWindows] indexOfObject:browser_window]);
135   [app_controller applicationShouldHandleReopen:NSApp
136                               hasVisibleWindows:YES];
137   EXPECT_LE([[NSApp orderedWindows] indexOfObject:browser_window],
138             [[NSApp orderedWindows] indexOfObject:app_window]);
139 }
140
141 class AppControllerWebAppBrowserTest : public InProcessBrowserTest {
142  protected:
143   AppControllerWebAppBrowserTest()
144       : active_browser_list_(BrowserList::GetInstance(
145                                 chrome::GetActiveDesktop())) {
146   }
147
148   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
149     command_line->AppendSwitchASCII(switches::kApp, GetAppURL());
150   }
151
152   std::string GetAppURL() const {
153     return "http://example.com/";
154   }
155
156   const BrowserList* active_browser_list_;
157 };
158
159 // Test that in web app mode a reopen event opens the app URL.
160 IN_PROC_BROWSER_TEST_F(AppControllerWebAppBrowserTest,
161                        WebAppReopenWithNoWindows) {
162   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
163   EXPECT_EQ(1u, active_browser_list_->size());
164   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
165
166   EXPECT_FALSE(result);
167   EXPECT_EQ(2u, active_browser_list_->size());
168
169   Browser* browser = active_browser_list_->get(0);
170   GURL current_url =
171       browser->tab_strip_model()->GetActiveWebContents()->GetURL();
172   EXPECT_EQ(GetAppURL(), current_url.spec());
173 }
174
175 // Called when the ProfileManager has created a profile.
176 void CreateProfileCallback(const base::Closure& quit_closure,
177                            Profile* profile,
178                            Profile::CreateStatus status) {
179   EXPECT_TRUE(profile);
180   EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
181   EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
182   // This will be called multiple times. Wait until the profile is initialized
183   // fully to quit the loop.
184   if (status == Profile::CREATE_STATUS_INITIALIZED)
185     quit_closure.Run();
186 }
187
188 void CreateAndWaitForGuestProfile() {
189   ProfileManager::CreateCallback create_callback =
190       base::Bind(&CreateProfileCallback,
191                  base::MessageLoop::current()->QuitClosure());
192   g_browser_process->profile_manager()->CreateProfileAsync(
193       ProfileManager::GetGuestProfilePath(),
194       create_callback,
195       base::string16(),
196       base::string16(),
197       std::string());
198   base::RunLoop().Run();
199 }
200
201 class AppControllerNewProfileManagementBrowserTest
202     : public InProcessBrowserTest {
203  protected:
204   AppControllerNewProfileManagementBrowserTest()
205       : active_browser_list_(BrowserList::GetInstance(
206                                 chrome::GetActiveDesktop())) {
207   }
208
209   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
210     switches::EnableNewProfileManagementForTesting(command_line);
211   }
212
213   const BrowserList* active_browser_list_;
214 };
215
216 // Test that for a regular last profile, a reopen event opens a browser.
217 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
218                        RegularProfileReopenWithNoWindows) {
219   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
220   EXPECT_EQ(1u, active_browser_list_->size());
221   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
222
223   EXPECT_FALSE(result);
224   EXPECT_EQ(2u, active_browser_list_->size());
225   EXPECT_FALSE(UserManager::IsShowing());
226 }
227
228 // Test that for a locked last profile, a reopen event opens the User Manager.
229 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
230                        LockedProfileReopenWithNoWindows) {
231   // The User Manager uses the guest profile as its underlying profile. To
232   // minimize flakiness due to the scheduling/descheduling of tasks on the
233   // different threads, pre-initialize the guest profile before it is needed.
234   CreateAndWaitForGuestProfile();
235   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
236
237   // Lock the active profile.
238   Profile* profile = [ac lastProfile];
239   ProfileInfoCache& cache =
240       g_browser_process->profile_manager()->GetProfileInfoCache();
241   size_t profile_index = cache.GetIndexOfProfileWithPath(profile->GetPath());
242   cache.SetProfileSigninRequiredAtIndex(profile_index, true);
243   EXPECT_TRUE(cache.ProfileIsSigninRequiredAtIndex(profile_index));
244
245   EXPECT_EQ(1u, active_browser_list_->size());
246   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
247   EXPECT_FALSE(result);
248
249   base::RunLoop().RunUntilIdle();
250   EXPECT_EQ(1u, active_browser_list_->size());
251   EXPECT_TRUE(UserManager::IsShowing());
252   UserManager::Hide();
253 }
254
255 // Test that for a guest last profile, a reopen event opens the User Manager.
256 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest,
257                        GuestProfileReopenWithNoWindows) {
258   // Create the guest profile, and set it as the last used profile so the
259   // app controller can use it on init.
260   CreateAndWaitForGuestProfile();
261   PrefService* local_state = g_browser_process->local_state();
262   local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
263
264   base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
265
266   Profile* profile = [ac lastProfile];
267   EXPECT_EQ(ProfileManager::GetGuestProfilePath(), profile->GetPath());
268   EXPECT_TRUE(profile->IsGuestSession());
269
270   EXPECT_EQ(1u, active_browser_list_->size());
271   BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO];
272   EXPECT_FALSE(result);
273
274   base::RunLoop().RunUntilIdle();
275
276   EXPECT_EQ(1u, active_browser_list_->size());
277   EXPECT_TRUE(UserManager::IsShowing());
278   UserManager::Hide();
279 }
280
281 class AppControllerOpenShortcutBrowserTest : public InProcessBrowserTest {
282  protected:
283   AppControllerOpenShortcutBrowserTest() {
284   }
285
286   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
287     // In order to mimic opening shortcut during browser startup, we need to
288     // send the event before -applicationDidFinishLaunching is called, but
289     // after AppController is loaded.
290     //
291     // Since -applicationWillFinishLaunching does nothing now, we swizzle it to
292     // our function to send the event. We need to do this early before running
293     // the main message loop.
294     //
295     // NSApp does not exist yet. We need to get the AppController using
296     // reflection.
297     Class appControllerClass = NSClassFromString(@"AppController");
298     Class openShortcutClass = NSClassFromString(@"TestOpenShortcutOnStartup");
299
300     ASSERT_TRUE(appControllerClass != nil);
301     ASSERT_TRUE(openShortcutClass != nil);
302
303     SEL targetMethod = @selector(applicationWillFinishLaunching:);
304     Method original = class_getInstanceMethod(appControllerClass,
305         targetMethod);
306     Method destination = class_getInstanceMethod(openShortcutClass,
307         targetMethod);
308
309     ASSERT_TRUE(original != NULL);
310     ASSERT_TRUE(destination != NULL);
311
312     method_exchangeImplementations(original, destination);
313
314     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
315     g_open_shortcut_url = embedded_test_server()->GetURL("/simple.html");
316   }
317
318   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
319     // If the arg is empty, PrepareTestCommandLine() after this function will
320     // append about:blank as default url.
321     command_line->AppendArg(chrome::kChromeUINewTabURL);
322   }
323 };
324
325 IN_PROC_BROWSER_TEST_F(AppControllerOpenShortcutBrowserTest,
326                        OpenShortcutOnStartup) {
327   EXPECT_EQ(1, browser()->tab_strip_model()->count());
328   EXPECT_EQ(g_open_shortcut_url,
329       browser()->tab_strip_model()->GetActiveWebContents()
330           ->GetLastCommittedURL());
331 }
332
333 }  // namespace