12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 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)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/path_service.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/run_loop.h"
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_browsertest.h"
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_service.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/chrome_paths.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/app_list/app_list_model.h"
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/app_list/search_box_model.h"
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/app_list/search_result.h"
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/app_list/search_result_observer.h"
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/base/models/list_model_observer.h"
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Browser Test for AppListController that runs on all platforms supporting
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// app_list.
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef InProcessBrowserTest AppListControllerBrowserTest;
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Test the CreateNewWindow function of the controller delegate.
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest, CreateNewWindow) {
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const chrome::HostDesktopType desktop = chrome::GetActiveDesktop();
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListService* service = test::GetAppListService();
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AppListControllerDelegate* controller(service->GetControllerDelegate());
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_TRUE(controller);
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(1U, chrome::GetBrowserCount(browser()->profile(), desktop));
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0U, chrome::GetBrowserCount(
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      browser()->profile()->GetOffTheRecordProfile(), desktop));
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  controller->CreateNewWindow(browser()->profile(), false);
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(2U, chrome::GetBrowserCount(browser()->profile(), desktop));
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  controller->CreateNewWindow(browser()->profile(), true);
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(1U, chrome::GetBrowserCount(
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      browser()->profile()->GetOffTheRecordProfile(), desktop));
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Browser Test for AppListController that observes search result changes.
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class AppListControllerSearchResultsBrowserTest
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : public ExtensionBrowserTest,
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      public app_list::SearchResultObserver,
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      public ui::ListModelObserver {
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  AppListControllerSearchResultsBrowserTest()
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      : observed_result_(NULL),
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        item_uninstall_count_(0),
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        observed_results_list_(NULL) {}
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void WatchResultsLookingForItem(
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      app_list::AppListModel::SearchResults* search_results,
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const std::string& extension_name) {
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_FALSE(observed_results_list_);
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    observed_results_list_ = search_results;
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    observed_results_list_->AddObserver(this);
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    item_to_observe_ = base::ASCIIToUTF16(extension_name);
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void StopWatchingResults() {
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_TRUE(observed_results_list_);
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    observed_results_list_->RemoveObserver(this);
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) protected:
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void AttemptToLocateItem() {
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (observed_result_) {
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      observed_result_->RemoveObserver(this);
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      observed_result_ = NULL;
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (size_t i = 0; i < observed_results_list_->item_count(); ++i) {
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (observed_results_list_->GetItemAt(i)->title() != item_to_observe_)
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        continue;
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Ensure there is at most one.
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      EXPECT_FALSE(observed_result_);
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      observed_result_ = observed_results_list_->GetItemAt(i);
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (observed_result_)
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      observed_result_->AddObserver(this);
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Overridden from SearchResultObserver:
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnIconChanged() OVERRIDE {}
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnActionsChanged() OVERRIDE {}
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnIsInstallingChanged() OVERRIDE {}
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnPercentDownloadedChanged() OVERRIDE {}
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnItemInstalled() OVERRIDE {}
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnItemUninstalled() OVERRIDE {
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ++item_uninstall_count_;
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    EXPECT_TRUE(observed_result_);
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Overridden from ui::ListModelObserver:
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void ListItemsAdded(size_t start, size_t count) OVERRIDE {
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AttemptToLocateItem();
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void ListItemsRemoved(size_t start, size_t count) OVERRIDE {
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AttemptToLocateItem();
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void ListItemMoved(size_t index, size_t target_index) OVERRIDE {}
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void ListItemsChanged(size_t start, size_t count) OVERRIDE {}
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  app_list::SearchResult* observed_result_;
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int item_uninstall_count_;
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::string16 item_to_observe_;
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  app_list::AppListModel::SearchResults* observed_results_list_;
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AppListControllerSearchResultsBrowserTest);
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Flaky on Mac. https://crbug.com/415264
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX)
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define MAYBE_UninstallSearchResult DISABLED_UninstallSearchResult
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define MAYBE_UninstallSearchResult UninstallSearchResult
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Test showing search results, and uninstalling one of them while displayed.
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(AppListControllerSearchResultsBrowserTest,
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       MAYBE_UninstallSearchResult) {
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::FilePath test_extension_path;
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_extension_path));
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  test_extension_path = test_extension_path.AppendASCII("extensions")
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .AppendASCII("platform_apps")
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .AppendASCII("minimal");
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const extensions::Extension* extension =
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      InstallExtension(test_extension_path,
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       1 /* expected_change: new install */);
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(extension);
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppListService* service = test::GetAppListService();
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(service);
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service->ShowForProfile(browser()->profile());
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  app_list::AppListModel* model = test::GetAppListModel(service);
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(model);
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  WatchResultsLookingForItem(model->results(), extension->name());
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Ensure a search finds the extension.
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_FALSE(observed_result_);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model->search_box()->SetText(base::ASCIIToUTF16("minimal"));
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(observed_result_);
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Ensure the UI is updated. This is via PostTask in views.
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Now uninstall and ensure this browser test observes it.
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(0, item_uninstall_count_);
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  UninstallExtension(extension->id());
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(1, item_uninstall_count_);
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Results should not be immediately refreshed. When they are, the item should
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // be removed from the model.
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(observed_result_);
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_FALSE(observed_result_);
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  StopWatchingResults();
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service->DismissAppList();
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
172