summaryrefslogtreecommitdiff
path: root/athena
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-11-12 17:59:43 +0000
committerTorne (Richard Coles) <torne@google.com>2014-11-12 17:59:43 +0000
commit1850ca92fc5c5faa2907b3befcf40067265148cc (patch)
tree7d10585f25356b3ee63b5ab4255161fe27725ee4 /athena
parente9e1f6521e4fef99aa1a1928c70ef3dfb55a8d9e (diff)
downloadchromium_org-1850ca92fc5c5faa2907b3befcf40067265148cc.tar.gz
Merge from Chromium at DEPS revision 03655fd3f6d7
This commit was generated by merge_to_master.py. Change-Id: Ifba5396691b9164ba027be04398f7bc8e938750d
Diffstat (limited to 'athena')
-rw-r--r--athena/athena.gyp49
-rw-r--r--athena/content/DEPS1
-rw-r--r--athena/content/app_activity_browsertest.cc14
-rw-r--r--athena/content/chrome/web_activity_browsertest.cc18
-rw-r--r--athena/content/chrome/web_activity_helpers_browsertest.cc12
-rw-r--r--athena/content/content_proxy_browsertest.cc10
-rw-r--r--athena/content/web_activity.cc4
-rw-r--r--athena/env/DEPS1
-rw-r--r--athena/env/athena_env_impl.cc84
-rw-r--r--athena/extensions/DEPS5
-rw-r--r--athena/extensions/athena_constrained_window_views_client.cc139
-rw-r--r--athena/extensions/athena_constrained_window_views_client.h15
-rw-r--r--athena/extensions/athena_javascript_native_dialog_factory.cc46
-rw-r--r--athena/extensions/athena_javascript_native_dialog_factory.h14
-rw-r--r--athena/extensions/extensions_delegate.cc7
-rw-r--r--athena/home/app_list_view_delegate.cc13
-rw-r--r--athena/home/athena_start_page_view.cc476
-rw-r--r--athena/home/athena_start_page_view.h128
-rw-r--r--athena/home/athena_start_page_view_unittest.cc279
-rw-r--r--athena/home/home_card_constants.cc2
-rw-r--r--athena/home/home_card_gesture_manager_unittest.cc8
-rw-r--r--athena/home/home_card_impl.cc143
-rw-r--r--athena/home/home_card_impl.h9
-rw-r--r--athena/home/home_card_unittest.cc40
-rw-r--r--athena/main/DEPS2
-rw-r--r--athena/main/athena_frame_view.h6
-rw-r--r--athena/main/athena_main.cc189
-rw-r--r--athena/main/athena_main.gyp2
-rw-r--r--athena/main/athena_main_delegate.cc175
-rw-r--r--athena/main/athena_main_delegate.h29
-rw-r--r--athena/screen/modal_window_controller.cc6
-rw-r--r--athena/screen/screen_manager_impl.cc44
-rw-r--r--athena/screen/screen_manager_unittest.cc88
-rw-r--r--athena/test/base/DEPS6
-rw-r--r--athena/test/base/athena_browser_test.cc61
-rw-r--r--athena/test/base/athena_browser_test.h45
-rw-r--r--athena/test/base/athena_browser_test_main.cc15
-rw-r--r--athena/test/base/athena_test_launcher_delegate.cc29
-rw-r--r--athena/test/base/athena_test_launcher_delegate.h25
-rw-r--r--athena/test/base/test_util.cc (renamed from athena/test/chrome/test_util.cc)7
-rw-r--r--athena/test/base/test_util.h (renamed from athena/test/chrome/test_util.h)10
-rw-r--r--athena/test/chrome/DEPS2
-rw-r--r--athena/test/chrome/athena_app_browser_test.cc (renamed from athena/test/chrome/athena_app_browsertest.cc)11
-rw-r--r--athena/test/chrome/athena_app_browser_test.h (renamed from athena/test/chrome/athena_app_browsertest.h)10
-rw-r--r--athena/test/chrome/athena_chrome_browser_test.cc (renamed from athena/test/chrome/athena_browsertest.cc)18
-rw-r--r--athena/test/chrome/athena_chrome_browser_test.h (renamed from athena/test/chrome/athena_browsertest.h)22
46 files changed, 1067 insertions, 1252 deletions
diff --git a/athena/athena.gyp b/athena/athena.gyp
index 25dafb0164..c47515666f 100644
--- a/athena/athena.gyp
+++ b/athena/athena.gyp
@@ -25,6 +25,7 @@
'../ui/aura/aura.gyp:aura_test_support',
'../ui/chromeos/ui_chromeos.gyp:ui_chromeos',
'../ui/display/display.gyp:display',
+ '../ui/events/devices/events_devices.gyp:events_devices',
'../ui/events/events.gyp:events_base',
'../ui/strings/ui_strings.gyp:ui_strings',
'../ui/views/views.gyp:views',
@@ -55,8 +56,6 @@
'env/public/athena_env.h',
'home/app_list_view_delegate.cc',
'home/app_list_view_delegate.h',
- 'home/athena_start_page_view.cc',
- 'home/athena_start_page_view.h',
'home/home_card_constants.cc',
'home/home_card_constants.h',
'home/home_card_gesture_manager.cc',
@@ -130,11 +129,14 @@
'dependencies': [
'athena_lib',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../components/components.gyp:app_modal_dialogs',
+ '../components/components.gyp:constrained_window',
'../components/components.gyp:component_metrics_proto',
'../components/components.gyp:omnibox',
'../components/components.gyp:renderer_context_menu',
'../components/components.gyp:web_modal',
'../content/content.gyp:content_browser',
+ '../extensions/components/extensions_components.gyp:javascript_dialog_extensions_client',
'../extensions/components/extensions_components.gyp:native_app_window',
'../extensions/extensions.gyp:extensions_browser',
'../extensions/extensions.gyp:extensions_common',
@@ -172,6 +174,10 @@
'extensions/athena_app_delegate_base.h',
'extensions/athena_app_window_client_base.cc',
'extensions/athena_app_window_client_base.h',
+ 'extensions/athena_constrained_window_views_client.cc',
+ 'extensions/athena_constrained_window_views_client.h',
+ 'extensions/athena_javascript_native_dialog_factory.cc',
+ 'extensions/athena_javascript_native_dialog_factory.h',
'extensions/athena_native_app_window_views.cc',
'extensions/athena_native_app_window_views.h',
'extensions/extension_app_model_builder.cc',
@@ -277,11 +283,49 @@
'test/base/test_resource_manager_delegate.cc',
'test/base/test_windows.cc',
'test/base/test_windows.h',
+ 'test/base/test_util.cc',
+ 'test/base/test_util.h',
'wm/test/window_manager_impl_test_api.cc',
'wm/test/window_manager_impl_test_api.h',
],
},
{
+ 'target_name': 'athena_browsertest_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../testing/gtest.gyp:gtest',
+ 'athena_test_support',
+ 'main/athena_main.gyp:athena_main_lib',
+ 'resources/athena_resources.gyp:athena_pak',
+ ],
+ 'sources': [
+ 'test/base/activity_lifetime_tracker.h',
+ 'test/base/activity_lifetime_tracker.cc',
+ 'test/base/athena_browser_test.h',
+ 'test/base/athena_browser_test.cc',
+ 'test/base/athena_browser_test.h',
+ 'test/base/athena_test_launcher_delegate.cc',
+ 'test/base/athena_test_launcher_delegate.h',
+ ],
+ },
+ {
+ 'target_name': 'athena_browsertests',
+ 'type': 'executable',
+ 'dependencies': [
+ '../testing/gtest.gyp:gtest',
+ '../skia/skia.gyp:skia',
+ 'athena_browsertest_support',
+ 'athena_app_shell_lib',
+ 'athena_lib',
+ ],
+ 'defines': [
+ 'HAS_OUT_OF_PROC_TEST_RUNNER',
+ ],
+ 'sources': [
+ 'test/base/athena_browser_test_main.cc',
+ ],
+ },
+ {
'target_name': 'athena_unittests',
'type': 'executable',
'dependencies': [
@@ -297,7 +341,6 @@
'activity/activity_manager_unittest.cc',
'content/app_activity_unittest.cc',
'env/athena_env_unittest.cc',
- 'home/athena_start_page_view_unittest.cc',
'home/home_card_gesture_manager_unittest.cc',
'home/home_card_unittest.cc',
'input/accelerator_manager_unittest.cc',
diff --git a/athena/content/DEPS b/athena/content/DEPS
index f5ed971132..5fc372e507 100644
--- a/athena/content/DEPS
+++ b/athena/content/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+athena/resource_manager/public",
"+athena/strings/grit/athena_strings.h",
"+athena/wm/public",
+ "+components/app_modal_dialogs",
"+components/favicon_base",
"+components/metrics/proto",
"+components/omnibox",
diff --git a/athena/content/app_activity_browsertest.cc b/athena/content/app_activity_browsertest.cc
index 17cc893d5c..2c954efba3 100644
--- a/athena/content/app_activity_browsertest.cc
+++ b/athena/content/app_activity_browsertest.cc
@@ -5,8 +5,8 @@
#include "athena/activity/public/activity.h"
#include "athena/resource_manager/public/resource_manager.h"
#include "athena/test/base/activity_lifetime_tracker.h"
-#include "athena/test/chrome/athena_app_browsertest.h"
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
+#include "athena/test/chrome/athena_app_browser_test.h"
#include "athena/wm/public/window_list_provider.h"
#include "athena/wm/public/window_manager.h"
#include "base/strings/utf_string_conversions.h"
@@ -72,9 +72,7 @@ class AppActivityBrowserTest : public AthenaAppBrowserTest {
// Then a web activity (which will then be in front of the app).
*web_activity = test_util::CreateTestWebActivity(
- test_util::GetBrowserContext(),
- base::UTF8ToUTF16("App1"),
- GURL(kTestUrl));
+ GetBrowserContext(), base::UTF8ToUTF16("App1"), GURL(kTestUrl));
ASSERT_TRUE(*web_activity);
EXPECT_EQ(*web_activity, tracker_->GetNewActivityAndReset());
EXPECT_EQ(nullptr, tracker_->GetDeletedActivityAndReset());
@@ -124,10 +122,8 @@ IN_PROC_BROWSER_TEST_F(AppActivityBrowserTest, StartApplication) {
// Test that creating an application (without a particular activity order
// location) should activate it initially.
IN_PROC_BROWSER_TEST_F(AppActivityBrowserTest, CreatedAppGetsFocus) {
- Activity* web_activity =
- test_util::CreateTestWebActivity(test_util::GetBrowserContext(),
- base::UTF8ToUTF16("App1"),
- GURL(kTestUrl));
+ Activity* web_activity = test_util::CreateTestWebActivity(
+ GetBrowserContext(), base::UTF8ToUTF16("App1"), GURL(kTestUrl));
EXPECT_TRUE(IsActivityActive(web_activity));
Activity* app_activity = CreateTestAppActivity(GetTestAppID());
diff --git a/athena/content/chrome/web_activity_browsertest.cc b/athena/content/chrome/web_activity_browsertest.cc
index 42f6d13170..aabe44919d 100644
--- a/athena/content/chrome/web_activity_browsertest.cc
+++ b/athena/content/chrome/web_activity_browsertest.cc
@@ -4,8 +4,8 @@
#include "athena/activity/public/activity.h"
#include "athena/resource_manager/public/resource_manager.h"
-#include "athena/test/chrome/athena_browsertest.h"
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
+#include "athena/test/chrome/athena_chrome_browser_test.h"
#include "athena/wm/public/window_list_provider.h"
#include "athena/wm/public/window_manager.h"
#include "base/strings/utf_string_conversions.h"
@@ -21,16 +21,14 @@ namespace {
const char kTestUrl[] = "chrome:about";
}
-typedef AthenaBrowserTest WebActivityBrowserTest;
+typedef AthenaChromeBrowserTest WebActivityBrowserTest;
// A simple test to create web content.
IN_PROC_BROWSER_TEST_F(WebActivityBrowserTest, SimpleCreate) {
const GURL target_url(kTestUrl);
// Create an activity, wait until it is loaded and check that it was created.
Activity* activity = test_util::CreateTestWebActivity(
- test_util::GetBrowserContext(),
- base::UTF8ToUTF16("App"),
- target_url);
+ GetBrowserContext(), base::UTF8ToUTF16("App"), target_url);
ASSERT_TRUE(activity);
EXPECT_NE(Activity::ACTIVITY_UNLOADED, activity->GetCurrentState());
// The activity manager should take care of destroying the activity upon
@@ -47,16 +45,12 @@ IN_PROC_BROWSER_TEST_F(WebActivityBrowserTest, LoadUnloadReload) {
// Create an activity (and wait until it is loaded).
// The size of its overview image should be empty since it is visible.
Activity* activity2 = test_util::CreateTestWebActivity(
- test_util::GetBrowserContext(),
- base::UTF8ToUTF16("App2"),
- target_url);
+ GetBrowserContext(), base::UTF8ToUTF16("App2"), target_url);
EXPECT_TRUE(activity2);
EXPECT_EQ(list[0], activity2->GetWindow());
EXPECT_NE(Activity::ACTIVITY_UNLOADED, activity2->GetCurrentState());
Activity* activity1 = test_util::CreateTestWebActivity(
- test_util::GetBrowserContext(),
- base::UTF8ToUTF16("App1"),
- target_url);
+ GetBrowserContext(), base::UTF8ToUTF16("App1"), target_url);
EXPECT_TRUE(activity1);
// |activity2| should now be the second activity. Both activities should have
diff --git a/athena/content/chrome/web_activity_helpers_browsertest.cc b/athena/content/chrome/web_activity_helpers_browsertest.cc
index 4dd8bee593..9dfdb0179c 100644
--- a/athena/content/chrome/web_activity_helpers_browsertest.cc
+++ b/athena/content/chrome/web_activity_helpers_browsertest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "athena/activity/public/activity.h"
-#include "athena/test/chrome/athena_browsertest.h"
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
+#include "athena/test/chrome/athena_chrome_browser_test.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "content/public/browser/notification_observer.h"
@@ -58,7 +58,7 @@ class HelpersCreatedChecker : public content::NotificationObserver {
DISALLOW_COPY_AND_ASSIGN(HelpersCreatedChecker);
};
-typedef AthenaBrowserTest WebActivityHelpersBrowserTest;
+typedef AthenaChromeBrowserTest WebActivityHelpersBrowserTest;
// Test that the WebActivity helpers are attached to the web contents prior to
// the RenderView view being created. This is important because some of the
@@ -70,10 +70,8 @@ IN_PROC_BROWSER_TEST_F(WebActivityHelpersBrowserTest, CreationTime) {
HelpersCreatedChecker checker;
GURL url("http://www.google.com");
- athena::Activity* activity =
- test_util::CreateTestWebActivity(test_util::GetBrowserContext(),
- base::UTF8ToUTF16("App"),
- url);
+ athena::Activity* activity = test_util::CreateTestWebActivity(
+ GetBrowserContext(), base::UTF8ToUTF16("App"), url);
content::WebContents* web_contents1 = activity->GetWebContents();
EXPECT_NE(Activity::ACTIVITY_UNLOADED, activity->GetCurrentState());
EXPECT_TRUE(web_contents1->GetRenderViewHost()->IsRenderViewLive());
diff --git a/athena/content/content_proxy_browsertest.cc b/athena/content/content_proxy_browsertest.cc
index c9628378a8..f48eed56d6 100644
--- a/athena/content/content_proxy_browsertest.cc
+++ b/athena/content/content_proxy_browsertest.cc
@@ -5,8 +5,8 @@
#include "athena/activity/public/activity.h"
#include "athena/activity/public/activity_view_model.h"
#include "athena/resource_manager/public/resource_manager.h"
-#include "athena/test/chrome/athena_browsertest.h"
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
+#include "athena/test/chrome/athena_chrome_browser_test.h"
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/compositor/compositor_switches.h"
@@ -22,7 +22,7 @@ const char kTestUrl[] = "chrome:about";
}
// Need to override the test class to make the test always draw its content.
-class ContentProxyBrowserTest : public AthenaBrowserTest {
+class ContentProxyBrowserTest : public AthenaChromeBrowserTest {
public:
ContentProxyBrowserTest() {}
~ContentProxyBrowserTest() override {}
@@ -31,7 +31,7 @@ class ContentProxyBrowserTest : public AthenaBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
// Make sure that we draw the output - it's required for this test.
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
- AthenaBrowserTest::SetUpCommandLine(command_line);
+ AthenaChromeBrowserTest::SetUpCommandLine(command_line);
}
private:
@@ -42,7 +42,7 @@ IN_PROC_BROWSER_TEST_F(ContentProxyBrowserTest, CreateContent) {
const int kTimeoutMS = 12000; // The timeout: 2 seconds.
const int kIterationSleepMS = 5; // The wait time in ms per iteration.
const GURL gurl(kTestUrl);
- content::BrowserContext* context = test_util::GetBrowserContext();
+ content::BrowserContext* context = GetBrowserContext();
// Create an activity (and wait until it is loaded).
// The size of its overview image should be empty since it is visible.
Activity* activity1 =
diff --git a/athena/content/web_activity.cc b/athena/content/web_activity.cc
index d6801b84a6..a6bdb82b51 100644
--- a/athena/content/web_activity.cc
+++ b/athena/content/web_activity.cc
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/app_modal_dialogs/javascript_dialog_manager.h"
#include "components/favicon_base/select_favicon_frames.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/navigation_controller.h"
@@ -365,8 +366,7 @@ class AthenaWebView : public views::WebView {
}
content::JavaScriptDialogManager* GetJavaScriptDialogManager() override {
- NOTIMPLEMENTED();
- return nullptr;
+ return GetJavaScriptDialogManagerInstance();
}
content::ColorChooser* OpenColorChooser(
diff --git a/athena/env/DEPS b/athena/env/DEPS
index bcac64e2dd..82dec51d6e 100644
--- a/athena/env/DEPS
+++ b/athena/env/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+ui/base",
"+ui/chromeos",
"+ui/display",
+ "+ui/events/devices",
"+ui/gfx",
"+ui/wm",
]
diff --git a/athena/env/athena_env_impl.cc b/athena/env/athena_env_impl.cc
index 326b950cc5..6b5975d7cf 100644
--- a/athena/env/athena_env_impl.cc
+++ b/athena/env/athena_env_impl.cc
@@ -22,6 +22,9 @@
#include "ui/display/chromeos/display_configurator.h"
#include "ui/display/types/display_mode.h"
#include "ui/display/types/display_snapshot.h"
+#include "ui/events/devices/device_data_manager.h"
+#include "ui/events/devices/input_device_event_observer.h"
+#include "ui/events/devices/touchscreen_device.h"
#include "ui/gfx/screen.h"
#include "ui/wm/core/compound_event_filter.h"
#include "ui/wm/core/cursor_manager.h"
@@ -39,6 +42,48 @@ AthenaEnv* instance = nullptr;
// Screen object used during shutdown.
gfx::Screen* screen_for_shutdown = nullptr;
+gfx::Transform GetTouchTransform(const ui::DisplaySnapshot& display,
+ const ui::TouchscreenDevice& touchscreen,
+ const gfx::SizeF& framebuffer_size) {
+ if (!display.current_mode())
+ return gfx::Transform();
+
+ gfx::SizeF display_size = display.current_mode()->size();
+#if defined(USE_X11)
+ gfx::SizeF touchscreen_size = framebuffer_size;
+#elif defined(USE_OZONE)
+ gfx::SizeF touchscreen_size = touchscreen.size;
+#endif
+
+ if (display_size.IsEmpty() || touchscreen_size.IsEmpty())
+ return gfx::Transform();
+
+ gfx::Transform transform;
+ transform.Scale(display_size.width() / touchscreen_size.width(),
+ display_size.height() / touchscreen_size.height());
+
+ return transform;
+}
+
+double GetTouchRadiusScale(const ui::DisplaySnapshot& display,
+ const ui::TouchscreenDevice& touchscreen,
+ const gfx::SizeF& framebuffer_size) {
+ if (!display.current_mode())
+ return 1;
+
+ gfx::SizeF display_size = display.current_mode()->size();
+#if defined(USE_X11)
+ gfx::SizeF touchscreen_size = framebuffer_size;
+#elif defined(USE_OZONE)
+ gfx::SizeF touchscreen_size = touchscreen.size;
+#endif
+
+ if (display_size.IsEmpty() || touchscreen_size.IsEmpty())
+ return 1;
+
+ return std::sqrt(display_size.GetArea() / touchscreen_size.GetArea());
+}
+
// TODO(flackr:oshima): Remove this once athena switches to share
// ash::DisplayManager.
class ScreenForShutdown : public gfx::Screen {
@@ -152,13 +197,16 @@ class AthenaNativeCursorManager : public wm::NativeCursorManager {
class AthenaEnvImpl : public AthenaEnv,
public aura::WindowTreeHostObserver,
- public ui::DisplayConfigurator::Observer {
+ public ui::DisplayConfigurator::Observer,
+ public ui::InputDeviceEventObserver {
public:
AthenaEnvImpl() : display_configurator_(new ui::DisplayConfigurator) {
display_configurator_->Init(false);
display_configurator_->ForceInitialConfigure(0);
display_configurator_->AddObserver(this);
+ ui::DeviceDataManager::GetInstance()->AddObserver(this);
+
gfx::Size screen_size = GetPrimaryDisplaySize();
if (screen_size.IsEmpty()) {
// TODO(oshima): Remove this hack.
@@ -234,6 +282,8 @@ class AthenaEnvImpl : public AthenaEnv,
screen_.reset();
aura::Env::DeleteInstance();
+ ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
+
display_configurator_->RemoveObserver(this);
display_configurator_.reset();
}
@@ -286,11 +336,20 @@ class AthenaEnvImpl : public AthenaEnv,
void OnDisplayModeChanged(
const std::vector<ui::DisplayConfigurator::DisplayState>& displays)
override {
+ MapTouchscreenToDisplay();
+
gfx::Size size = GetPrimaryDisplaySize();
if (!size.IsEmpty())
host_->UpdateRootWindowSize(size);
}
+ // ui::InputDeviceEventObserver:
+ void OnTouchscreenDeviceConfigurationChanged() override {
+ MapTouchscreenToDisplay();
+ }
+
+ void OnKeyboardDeviceConfigurationChanged() override {}
+
// aura::WindowTreeHostObserver:
void OnHostCloseRequested(const aura::WindowTreeHost* host) override {
base::MessageLoopForUI::current()->PostTask(
@@ -306,6 +365,29 @@ class AthenaEnvImpl : public AthenaEnv,
return mode ? mode->size() : gfx::Size();
}
+ void MapTouchscreenToDisplay() const {
+ auto device_manager = ui::DeviceDataManager::GetInstance();
+ auto displays = display_configurator_->cached_displays();
+ auto touchscreens = device_manager->touchscreen_devices();
+
+ if (displays.empty() || touchscreens.empty())
+ return;
+
+ gfx::SizeF framebuffer_size = display_configurator_->framebuffer_size();
+ device_manager->ClearTouchTransformerRecord();
+ device_manager->UpdateTouchInfoForDisplay(
+ displays[0].display->display_id(),
+ touchscreens[0].id,
+ GetTouchTransform(*displays[0].display,
+ touchscreens[0],
+ framebuffer_size));
+ device_manager->UpdateTouchRadiusScale(
+ touchscreens[0].id,
+ GetTouchRadiusScale(*displays[0].display,
+ touchscreens[0],
+ framebuffer_size));
+ }
+
scoped_ptr<aura::TestScreen> screen_;
scoped_ptr<aura::WindowTreeHost> host_;
diff --git a/athena/extensions/DEPS b/athena/extensions/DEPS
index 84b22ffdf7..9de66a692c 100644
--- a/athena/extensions/DEPS
+++ b/athena/extensions/DEPS
@@ -3,9 +3,14 @@ include_rules = [
"+athena/activity/public",
"+athena/home/public",
"+athena/wm/public",
+ "+components/app_modal_dialogs",
+ "+components/constrained_window",
+ "+components/web_modal",
"+content/public/browser",
"+extensions/browser",
"+extensions/common",
+ "+extensions/components/app_modal_dialogs",
+ "+extensions/components/javascript_dialog_extensions_client",
"+extensions/components/native_app_window",
"+extensions/grit",
"+ui/app_list",
diff --git a/athena/extensions/athena_constrained_window_views_client.cc b/athena/extensions/athena_constrained_window_views_client.cc
new file mode 100644
index 0000000000..db818f68f2
--- /dev/null
+++ b/athena/extensions/athena_constrained_window_views_client.cc
@@ -0,0 +1,139 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/extensions/athena_constrained_window_views_client.h"
+
+#include "athena/activity/public/activity.h"
+#include "athena/activity/public/activity_manager.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "components/constrained_window/constrained_window_views.h"
+#include "components/constrained_window/constrained_window_views_client.h"
+#include "components/web_modal/web_contents_modal_dialog_host.h"
+#include "extensions/browser/guest_view/guest_view_base.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#include "ui/aura/window_property.h"
+
+namespace athena {
+namespace {
+
+// Provides the host envrionment for web modal dialogs. See
+// web_modal::WebContentsModalDialogHost, and ModalDialogHost for more
+// details.
+class ModalDialogHostImpl : public web_modal::WebContentsModalDialogHost,
+ public aura::WindowObserver {
+ public:
+ // Returns a modal dialog host for |window|. If it doesn't exist it creates
+ // one and stores it as owned property.
+ static ModalDialogHost* Get(aura::Window* window);
+
+ private:
+ explicit ModalDialogHostImpl(aura::Window* host_window)
+ : host_window_(host_window) {
+ host_window_->AddObserver(this);
+ }
+ ~ModalDialogHostImpl() override {}
+
+ // web_modal::ModalDialogHost:
+ gfx::NativeView GetHostView() const override {
+ return host_window_;
+ }
+ gfx::Point GetDialogPosition(const gfx::Size& size) override {
+ gfx::Rect host_bounds = host_window_->GetBoundsInScreen();
+ host_bounds.ClampToCenteredSize(size);
+ return host_bounds.origin();
+ }
+ void AddObserver(web_modal::ModalDialogHostObserver* observer) override {
+ observer_list_.AddObserver(observer);
+ }
+ void RemoveObserver(web_modal::ModalDialogHostObserver* observer) override {
+ observer_list_.RemoveObserver(observer);
+ }
+
+ // web_modal::WebContensModalDialogHost:
+ gfx::Size GetMaximumDialogSize() override {
+ return host_window_->bounds().size();
+ }
+
+ // aura::WindowObserver:
+ void OnWindowDestroying(aura::Window* window) override {
+ if (window != host_window_)
+ return;
+ host_window_->RemoveObserver(this);
+ FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver,
+ observer_list_,
+ OnHostDestroying());
+ }
+ void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override {
+ if (window != host_window_)
+ return;
+ FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver,
+ observer_list_,
+ OnPositionRequiresUpdate());
+ }
+
+ aura::Window* host_window_;
+ ObserverList<web_modal::ModalDialogHostObserver> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(ModalDialogHostImpl);
+};
+
+// A window property key to store the modal dialog host for
+// dialogs created with the window as its parent.
+DEFINE_OWNED_WINDOW_PROPERTY_KEY(web_modal::ModalDialogHost,
+ kModalDialogHostKey,
+ nullptr);
+
+// static
+web_modal::ModalDialogHost* ModalDialogHostImpl::Get(
+ aura::Window* window) {
+ web_modal::ModalDialogHost* host = window->GetProperty(kModalDialogHostKey);
+ if (!host) {
+ host = new ModalDialogHostImpl(window);
+ window->SetProperty(kModalDialogHostKey, host);
+ }
+ return host;
+}
+
+class AthenaConstrainedWindowViewsClient
+ : public ConstrainedWindowViewsClient {
+ public:
+ AthenaConstrainedWindowViewsClient() {}
+ ~AthenaConstrainedWindowViewsClient() override {}
+
+ private:
+ // ConstrainedWindowViewsClient:
+ content::WebContents* GetEmbedderWebContents(
+ content::WebContents* initiator_web_contents) override {
+ extensions::GuestViewBase* guest_view =
+ extensions::GuestViewBase::FromWebContents(initiator_web_contents);
+ return guest_view && guest_view->embedder_web_contents() ?
+ guest_view->embedder_web_contents() : initiator_web_contents;
+ }
+ web_modal::ModalDialogHost* GetModalDialogHost(
+ gfx::NativeWindow parent) override {
+ Activity* activity = ActivityManager::Get()->GetActivityForWindow(parent);
+ if (activity)
+ return ModalDialogHostImpl::Get(parent);
+ return nullptr;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(AthenaConstrainedWindowViewsClient);
+};
+
+} // namespace
+
+void InstallConstrainedWindowViewsClient() {
+ SetConstrainedWindowViewsClient(
+ make_scoped_ptr(new AthenaConstrainedWindowViewsClient));
+}
+
+void UninstallConstrainedWindowViewsClient() {
+ SetConstrainedWindowViewsClient(nullptr);
+}
+
+} // namespace athena
diff --git a/athena/extensions/athena_constrained_window_views_client.h b/athena/extensions/athena_constrained_window_views_client.h
new file mode 100644
index 0000000000..4c5b0bb62f
--- /dev/null
+++ b/athena/extensions/athena_constrained_window_views_client.h
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_EXTENSIONS_ATHENA_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
+#define ATHENA_EXTENSIONS_ATHENA_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
+
+namespace athena {
+
+void InstallConstrainedWindowViewsClient();
+void UninstallConstrainedWindowViewsClient();
+
+} // namespace athena
+
+#endif // ATHENA_EXTENSIONS_ATHENA_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
diff --git a/athena/extensions/athena_javascript_native_dialog_factory.cc b/athena/extensions/athena_javascript_native_dialog_factory.cc
new file mode 100644
index 0000000000..6883a9e536
--- /dev/null
+++ b/athena/extensions/athena_javascript_native_dialog_factory.cc
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/extensions/athena_javascript_native_dialog_factory.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "components/app_modal_dialogs/javascript_dialog_manager.h"
+#include "components/app_modal_dialogs/javascript_native_dialog_factory.h"
+#include "components/app_modal_dialogs/views/javascript_app_modal_dialog_views.h"
+#include "components/constrained_window/constrained_window_views.h"
+
+class JavaScriptAppModalDialog;
+class NativeAppModalDialog;
+
+namespace athena {
+namespace {
+
+class AthenaJavaScriptNativeDialogFactory
+ : public JavaScriptNativeDialogFactory {
+ public:
+ AthenaJavaScriptNativeDialogFactory() {}
+ ~AthenaJavaScriptNativeDialogFactory() override {}
+
+ private:
+ // JavScriptNativeDialogFactory:
+ NativeAppModalDialog* CreateNativeJavaScriptDialog(
+ JavaScriptAppModalDialog* dialog,
+ gfx::NativeWindow parent_window) override{
+ JavaScriptAppModalDialogViews* d =
+ new JavaScriptAppModalDialogViews(dialog);
+ CreateBrowserModalDialogViews(d, parent_window);
+ return d;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(AthenaJavaScriptNativeDialogFactory);
+};
+
+} // namespace
+
+void InstallJavaScriptNativeDialogFactory() {
+ SetJavaScriptNativeDialogFactory(
+ make_scoped_ptr(new AthenaJavaScriptNativeDialogFactory));
+}
+
+} // namespace athena
diff --git a/athena/extensions/athena_javascript_native_dialog_factory.h b/athena/extensions/athena_javascript_native_dialog_factory.h
new file mode 100644
index 0000000000..8792dc84bf
--- /dev/null
+++ b/athena/extensions/athena_javascript_native_dialog_factory.h
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_EXTENSIONS_ATHENA_JAVASCRIPT_NATIVE_DIALOG_FACTORY_H_
+#define ATHENA_EXTENSIONS_ATHENA_JAVASCRIPT_NATIVE_DIALOG_FACTORY_H_
+
+namespace athena {
+
+void InstallJavaScriptNativeDialogFactory();
+
+} // namespace
+
+#endif // ATHENA_EXTENSIONS_ATHENA_JAVASCRIPT_NATIVE_DIALOG_FACTORY_H_
diff --git a/athena/extensions/extensions_delegate.cc b/athena/extensions/extensions_delegate.cc
index a5c39b9162..00a93b96d9 100644
--- a/athena/extensions/extensions_delegate.cc
+++ b/athena/extensions/extensions_delegate.cc
@@ -4,7 +4,10 @@
#include "athena/extensions/public/extensions_delegate.h"
+#include "athena/extensions/athena_constrained_window_views_client.h"
+#include "athena/extensions/athena_javascript_native_dialog_factory.h"
#include "base/logging.h"
+#include "extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.h"
namespace athena {
namespace {
@@ -14,11 +17,15 @@ ExtensionsDelegate* instance = nullptr;
} // namespace
ExtensionsDelegate::ExtensionsDelegate() {
+ InstallConstrainedWindowViewsClient();
+ InstallJavaScriptDialogExtensionsClient();
+ InstallJavaScriptNativeDialogFactory();
DCHECK(!instance);
instance = this;
}
ExtensionsDelegate::~ExtensionsDelegate() {
+ UninstallConstrainedWindowViewsClient();
DCHECK(instance);
instance = nullptr;
}
diff --git a/athena/home/app_list_view_delegate.cc b/athena/home/app_list_view_delegate.cc
index eead245f10..270aae6b32 100644
--- a/athena/home/app_list_view_delegate.cc
+++ b/athena/home/app_list_view_delegate.cc
@@ -22,10 +22,6 @@
#include "ui/app_list/search_result.h"
#include "ui/app_list/speech_ui_model.h"
#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/views/controls/image_view.h"
namespace athena {
@@ -144,14 +140,7 @@ void AppListViewDelegate::ShowForProfileByPath(
views::View* AppListViewDelegate::CreateStartPageWebView(
const gfx::Size& size) {
- // A static image of the logo. This needs to support dynamic Doodles
- // eventually.
- views::ImageView* logo_image = new views::ImageView();
- logo_image->SetImage(ui::ResourceBundle::GetSharedInstance().
- GetImageSkiaNamed(IDR_LOCAL_NTP_IMAGES_LOGO_PNG));
- logo_image->SetHorizontalAlignment(views::ImageView::CENTER);
- logo_image->SetVerticalAlignment(views::ImageView::CENTER);
- return logo_image;
+ return nullptr;
}
std::vector<views::View*> AppListViewDelegate::CreateCustomPageWebViews(
diff --git a/athena/home/athena_start_page_view.cc b/athena/home/athena_start_page_view.cc
deleted file mode 100644
index bb78ec2bc8..0000000000
--- a/athena/home/athena_start_page_view.cc
+++ /dev/null
@@ -1,476 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "athena/home/athena_start_page_view.h"
-
-#include "athena/home/home_card_constants.h"
-#include "athena/system/public/system_ui.h"
-#include "base/bind.h"
-#include "base/strings/string_util.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "ui/app_list/app_list_item.h"
-#include "ui/app_list/app_list_item_list.h"
-#include "ui/app_list/app_list_model.h"
-#include "ui/app_list/app_list_view_delegate.h"
-#include "ui/app_list/search_box_model.h"
-#include "ui/app_list/views/search_box_view.h"
-#include "ui/app_list/views/search_result_list_view.h"
-#include "ui/compositor/closure_animation_observer.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/canvas.h"
-#include "ui/views/background.h"
-#include "ui/views/border.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/round_rect_painter.h"
-
-namespace {
-
-const size_t kMaxIconNum = 3;
-const int kIconSize = 50;
-const int kIconMargin = 25;
-
-const int kTopMargin = 100;
-
-// Copied from ui/app_list/views/start_page_view.cc
-const int kInstantContainerSpacing = 20;
-const int kWebViewWidth = 500;
-const int kWebViewHeight = 105;
-const int kSearchBoxBorderWidth = 1;
-const int kSearchBoxCornerRadius = 2;
-
-// Taken from the mock. The width is not specified by pixel but the search box
-// covers 6 icons with margin.
-const int kSearchBoxWidth = kIconSize * 6 + kIconMargin * 7;
-const int kSearchBoxHeight = 40;
-
-gfx::Size GetIconContainerSize() {
- return gfx::Size(kIconSize * kMaxIconNum + kIconMargin * (kMaxIconNum - 1),
- kIconSize);
-}
-
-class PlaceHolderButton : public views::ImageButton,
- public views::ButtonListener {
- public:
- PlaceHolderButton()
- : ImageButton(this) {
- gfx::Canvas canvas(gfx::Size(kIconSize, kIconSize), 1.0f, true);
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(SkColorSetRGB(86, 119, 252));
- paint.setFlags(SkPaint::kAntiAlias_Flag);
- canvas.DrawCircle(
- gfx::Point(kIconSize / 2, kIconSize / 2), kIconSize / 2, paint);
-
- scoped_ptr<gfx::ImageSkia> image(
- new gfx::ImageSkia(canvas.ExtractImageRep()));
- SetImage(STATE_NORMAL, image.get());
- }
-
- private:
- // views::ButtonListener:
- void ButtonPressed(views::Button* sender, const ui::Event& event) override {
- // Do nothing: remove these place holders.
- }
-
- DISALLOW_COPY_AND_ASSIGN(PlaceHolderButton);
-};
-
-class AppIconButton : public views::ImageButton,
- public views::ButtonListener {
- public:
- explicit AppIconButton(app_list::AppListItem* item)
- : ImageButton(this), item_(nullptr) {
- SetItem(item);
- }
-
- void SetItem(app_list::AppListItem* item) {
- item_ = item;
- // TODO(mukai): icon should be resized.
- SetImage(STATE_NORMAL, &item->icon());
- }
-
- private:
- // views::ButtonListener:
- void ButtonPressed(views::Button* sender, const ui::Event& event) override {
- DCHECK_EQ(sender, this);
- item_->Activate(event.flags());
- }
-
- app_list::AppListItem* item_;
-
- DISALLOW_COPY_AND_ASSIGN(AppIconButton);
-};
-
-// The background to paint the round rectangle of the view area.
-class RoundRectBackground : public views::Background {
- public:
- RoundRectBackground(SkColor color, int corner_radius)
- : color_(color),
- corner_radius_(corner_radius) {}
- ~RoundRectBackground() override {}
-
- private:
- // views::Background:
- void Paint(gfx::Canvas* canvas, views::View* view) const override {
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(color_);
- canvas->DrawRoundRect(view->GetContentsBounds(), corner_radius_, paint);
- }
-
- SkColor color_;
- int corner_radius_;
-
- DISALLOW_COPY_AND_ASSIGN(RoundRectBackground);
-};
-
-class SearchBoxContainer : public views::View {
- public:
- explicit SearchBoxContainer(app_list::SearchBoxView* search_box)
- : search_box_(search_box) {
- search_box->set_background(
- new RoundRectBackground(SK_ColorWHITE, kSearchBoxCornerRadius));
- search_box->SetBorder(views::Border::CreateBorderPainter(
- new views::RoundRectPainter(SK_ColorGRAY, kSearchBoxCornerRadius),
- gfx::Insets(kSearchBoxBorderWidth, kSearchBoxBorderWidth,
- kSearchBoxBorderWidth, kSearchBoxBorderWidth)));
- SetLayoutManager(new views::FillLayout());
- AddChildView(search_box_);
- }
- ~SearchBoxContainer() override {}
-
- private:
- // views::View:
- gfx::Size GetPreferredSize() const override {
- return gfx::Size(kSearchBoxWidth, kSearchBoxHeight);
- }
-
- // Owned by the views hierarchy.
- app_list::SearchBoxView* search_box_;
-
- DISALLOW_COPY_AND_ASSIGN(SearchBoxContainer);
-};
-
-} // namespace
-
-namespace athena {
-
-// static
-const char AthenaStartPageView::kViewClassName[] = "AthenaStartPageView";
-
-AthenaStartPageView::LayoutData::LayoutData()
- : system_info_opacity(1.0f), logo_opacity(1.0f) {
-}
-
-AthenaStartPageView::AthenaStartPageView(
- app_list::AppListViewDelegate* view_delegate)
- : delegate_(view_delegate),
- layout_state_(0.0f),
- weak_factory_(this) {
- system_info_view_ =
- SystemUI::Get()->CreateSystemInfoView(SystemUI::COLOR_SCHEME_DARK);
- system_info_view_->SetPaintToLayer(true);
- system_info_view_->SetFillsBoundsOpaquely(false);
- AddChildView(system_info_view_);
-
- logo_ = view_delegate->CreateStartPageWebView(
- gfx::Size(kWebViewWidth, kWebViewHeight));
- logo_->SetPaintToLayer(true);
- logo_->SetFillsBoundsOpaquely(false);
- logo_->SetSize(gfx::Size(kWebViewWidth, kWebViewHeight));
- AddChildView(logo_);
-
- search_results_view_ =
- new app_list::SearchResultListView(nullptr, view_delegate);
- // search_results_view_'s size will shrink after settings results.
- search_results_height_ = static_cast<views::View*>(
- search_results_view_)->GetHeightForWidth(kSearchBoxWidth);
- search_results_view_->SetResults(view_delegate->GetModel()->results());
-
- search_results_view_->SetVisible(false);
- search_results_view_->SetPaintToLayer(true);
- search_results_view_->SetFillsBoundsOpaquely(false);
- AddChildView(search_results_view_);
-
- app_icon_container_ = new views::View();
- AddChildView(app_icon_container_);
- app_icon_container_->SetPaintToLayer(true);
- app_icon_container_->layer()->SetFillsBoundsOpaquely(false);
- app_icon_container_->SetLayoutManager(new views::BoxLayout(
- views::BoxLayout::kHorizontal, 0, 0, kIconMargin));
- app_icon_container_->SetSize(GetIconContainerSize());
- UpdateAppIcons();
- view_delegate->GetModel()->top_level_item_list()->AddObserver(this);
-
- control_icon_container_ = new views::View();
- control_icon_container_->SetPaintToLayer(true);
- control_icon_container_->SetFillsBoundsOpaquely(false);
- AddChildView(control_icon_container_);
- control_icon_container_->SetLayoutManager(new views::BoxLayout(
- views::BoxLayout::kHorizontal, 0, 0, kIconMargin));
- for (size_t i = 0; i < kMaxIconNum; ++i)
- control_icon_container_->AddChildView(new PlaceHolderButton());
- control_icon_container_->SetSize(GetIconContainerSize());
-
- search_box_view_ = new app_list::SearchBoxView(this, view_delegate);
- search_box_view_->set_contents_view(this);
- search_box_view_->search_box()->set_id(kHomeCardSearchBoxId);
- search_box_container_ = new SearchBoxContainer(search_box_view_);
- search_box_container_->SetPaintToLayer(true);
- search_box_container_->SetFillsBoundsOpaquely(false);
- search_box_container_->SetSize(search_box_container_->GetPreferredSize());
- AddChildView(search_box_container_);
-}
-
-AthenaStartPageView::~AthenaStartPageView() {
- delegate_->GetModel()->top_level_item_list()->RemoveObserver(this);
-}
-
-void AthenaStartPageView::RequestFocusOnSearchBox() {
- search_box_view_->search_box()->RequestFocus();
-}
-
-void AthenaStartPageView::SetLayoutState(float layout_state) {
- layout_state_ = layout_state;
- Layout();
- FOR_EACH_OBSERVER(Observer, observers_, OnLayoutStateChanged(layout_state));
-}
-
-void AthenaStartPageView::SetLayoutStateWithAnimation(
- float layout_state,
- gfx::Tween::Type tween_type) {
- ui::ScopedLayerAnimationSettings system_info(
- system_info_view_->layer()->GetAnimator());
- ui::ScopedLayerAnimationSettings logo(logo_->layer()->GetAnimator());
- ui::ScopedLayerAnimationSettings search_box(
- search_box_container_->layer()->GetAnimator());
- ui::ScopedLayerAnimationSettings icons(
- app_icon_container_->layer()->GetAnimator());
- ui::ScopedLayerAnimationSettings controls(
- control_icon_container_->layer()->GetAnimator());
-
- system_info.SetTweenType(tween_type);
- logo.SetTweenType(tween_type);
- search_box.SetTweenType(tween_type);
- icons.SetTweenType(tween_type);
- controls.SetTweenType(tween_type);
-
- SetLayoutState(layout_state);
-}
-
-void AthenaStartPageView::AddObserver(AthenaStartPageView::Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void AthenaStartPageView::RemoveObserver(
- AthenaStartPageView::Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-AthenaStartPageView::LayoutData AthenaStartPageView::CreateBottomBounds(
- int width) {
- LayoutData state;
- state.icons.set_size(app_icon_container_->size());
- state.icons.set_x(kIconMargin);
- state.icons.set_y(kIconMargin);
-
- state.controls.set_size(control_icon_container_->size());
- state.controls.set_x(width - kIconMargin - state.controls.width());
- state.controls.set_y(kIconMargin);
-
- int search_box_max_width =
- state.controls.x() - state.icons.right() - kIconMargin * 2;
- state.search_box.set_width(std::min(search_box_max_width, kSearchBoxWidth));
- state.search_box.set_height(search_box_container_->height());
- state.search_box.set_x((width - state.search_box.width()) / 2);
- state.search_box.set_y((kHomeCardHeight - state.search_box.height()) / 2);
-
- state.system_info_opacity = 0.0f;
- state.logo_opacity = 0.0f;
- return state;
-}
-
-AthenaStartPageView::LayoutData AthenaStartPageView::CreateCenteredBounds(
- int width) {
- LayoutData state;
-
- state.search_box.set_size(search_box_container_->GetPreferredSize());
- state.search_box.set_x((width - state.search_box.width()) / 2);
- state.search_box.set_y(logo_->bounds().bottom() + kInstantContainerSpacing);
-
- state.icons.set_size(app_icon_container_->size());
- state.icons.set_x(width / 2 - state.icons.width() - kIconMargin / 2);
- state.icons.set_y(state.search_box.bottom() + kInstantContainerSpacing);
-
- state.controls.set_size(control_icon_container_->size());
- state.controls.set_x(width / 2 + kIconMargin / 2 + kIconMargin % 2);
- state.controls.set_y(state.icons.y());
-
- state.system_info_opacity = 1.0f;
- state.logo_opacity = 1.0f;
- return state;
-}
-
-void AthenaStartPageView::UpdateAppIcons() {
- app_list::AppListItemList* top_level =
- delegate_->GetModel()->top_level_item_list();
- size_t max_items = std::min(top_level->item_count(), kMaxIconNum);
- for (size_t i = 0; i < max_items; ++i) {
- if (i < static_cast<size_t>(app_icon_container_->child_count())) {
- AppIconButton* button =
- static_cast<AppIconButton*>(app_icon_container_->child_at(i));
- button->SetItem(top_level->item_at(i));
- } else {
- app_icon_container_->AddChildView(
- new AppIconButton(top_level->item_at(i)));
- }
- }
-
- while (max_items < static_cast<size_t>(app_icon_container_->child_count())) {
- scoped_ptr<views::View> remover(
- app_icon_container_->child_at(app_icon_container_->child_count() - 1));
- app_icon_container_->RemoveChildView(remover.get());
- }
-}
-
-void AthenaStartPageView::LayoutSearchResults(bool should_show_search_results) {
- if (should_show_search_results ==
- search_results_view_->layer()->GetTargetVisibility()) {
- return;
- }
- if (should_show_search_results && layout_state_ != 1.0f)
- SetLayoutState(1.0f);
-
- gfx::Rect search_box_bounds = search_box_container_->bounds();
- if (!search_results_view_->visible()) {
- search_results_view_->SetVisible(true);
- search_results_view_->SetBounds(
- search_box_bounds.x(), search_box_bounds.bottom(),
- search_box_bounds.width(), 0);
- }
- logo_->SetVisible(true);
-
- {
- ui::ScopedLayerAnimationSettings logo_settings(
- logo_->layer()->GetAnimator());
- logo_settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
- logo_settings.AddObserver(new ui::ClosureAnimationObserver(
- base::Bind(&AthenaStartPageView::OnSearchResultLayoutAnimationCompleted,
- weak_factory_.GetWeakPtr(),
- should_show_search_results)));
-
- ui::ScopedLayerAnimationSettings search_box_settings(
- search_box_container_->layer()->GetAnimator());
- search_box_settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
-
- ui::ScopedLayerAnimationSettings search_results_settings(
- search_results_view_->layer()->GetAnimator());
- search_results_settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
-
- if (should_show_search_results) {
- logo_->layer()->SetOpacity(0.0f);
- search_box_bounds.set_y(
- search_box_bounds.y() - search_results_height_ -
- kInstantContainerSpacing);
- search_box_container_->SetBoundsRect(search_box_bounds);
- search_results_view_->SetBounds(
- search_box_bounds.x(),
- search_box_bounds.bottom() + kInstantContainerSpacing,
- search_box_bounds.width(),
- search_results_height_);
- } else {
- logo_->layer()->SetOpacity(1.0f);
- search_box_bounds.set_y(
- logo_->bounds().bottom() + kInstantContainerSpacing);
- search_box_container_->SetBoundsRect(search_box_bounds);
-
- gfx::Rect search_results_bounds = search_results_view_->bounds();
- search_results_bounds.set_y(search_results_bounds.bottom());
- search_results_bounds.set_height(0);
- search_results_view_->SetBoundsRect(search_results_bounds);
- }
- }
-}
-
-void AthenaStartPageView::OnSearchResultLayoutAnimationCompleted(
- bool should_show_search_results) {
- logo_->SetVisible(!should_show_search_results);
- search_results_view_->SetVisible(should_show_search_results);
-}
-
-void AthenaStartPageView::Layout() {
- search_results_view_->SetVisible(false);
-
- system_info_view_->SetBounds(
- 0, 0, width(), system_info_view_->GetPreferredSize().height());
-
- gfx::Rect logo_bounds(x() + width() / 2 - kWebViewWidth / 2, y() + kTopMargin,
- kWebViewWidth, kWebViewHeight);
- logo_->SetBoundsRect(logo_bounds);
-
- LayoutData bottom_bounds = CreateBottomBounds(width());
- LayoutData centered_bounds = CreateCenteredBounds(width());
-
- system_info_view_->layer()->SetOpacity(gfx::Tween::FloatValueBetween(
- gfx::Tween::CalculateValue(gfx::Tween::EASE_IN_2, layout_state_),
- bottom_bounds.system_info_opacity, centered_bounds.system_info_opacity));
- system_info_view_->SetVisible(
- system_info_view_->layer()->GetTargetOpacity() != 0.0f);
-
- logo_->layer()->SetOpacity(gfx::Tween::FloatValueBetween(
- gfx::Tween::CalculateValue(gfx::Tween::EASE_IN_2, layout_state_),
- bottom_bounds.logo_opacity, centered_bounds.logo_opacity));
- logo_->SetVisible(logo_->layer()->GetTargetOpacity() != 0.0f);
-
- app_icon_container_->SetBoundsRect(gfx::Tween::RectValueBetween(
- layout_state_, bottom_bounds.icons, centered_bounds.icons));
- control_icon_container_->SetBoundsRect(gfx::Tween::RectValueBetween(
- layout_state_, bottom_bounds.controls, centered_bounds.controls));
- search_box_container_->SetBoundsRect(gfx::Tween::RectValueBetween(
- layout_state_, bottom_bounds.search_box, centered_bounds.search_box));
-}
-
-bool AthenaStartPageView::OnKeyPressed(const ui::KeyEvent& key_event) {
- return search_results_view_->visible() &&
- search_results_view_->OnKeyPressed(key_event);
-}
-
-void AthenaStartPageView::QueryChanged(app_list::SearchBoxView* sender) {
- delegate_->StartSearch();
-
- base::string16 query;
- base::TrimWhitespace(
- delegate_->GetModel()->search_box()->text(), base::TRIM_ALL, &query);
-
- if (!query.empty())
- search_results_view_->SetSelectedIndex(0);
-
- LayoutSearchResults(!query.empty());
-}
-
-void AthenaStartPageView::OnListItemAdded(size_t index,
- app_list::AppListItem* item) {
- UpdateAppIcons();
-}
-
-void AthenaStartPageView::OnListItemRemoved(size_t index,
- app_list::AppListItem* item) {
- UpdateAppIcons();
-}
-
-void AthenaStartPageView::OnListItemMoved(size_t from_index,
- size_t to_index,
- app_list::AppListItem* item) {
- UpdateAppIcons();
-}
-
-// static
-size_t AthenaStartPageView::GetMaxIconNumForTest() {
- return kMaxIconNum;
-}
-
-} // namespace athena
diff --git a/athena/home/athena_start_page_view.h b/athena/home/athena_start_page_view.h
deleted file mode 100644
index fd15dca207..0000000000
--- a/athena/home/athena_start_page_view.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ATHENA_HOME_ATHENA_START_PAGE_VIEW_H_
-#define ATHENA_HOME_ATHENA_START_PAGE_VIEW_H_
-
-#include "athena/athena_export.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "ui/app_list/app_list_item_list_observer.h"
-#include "ui/app_list/views/search_box_view_delegate.h"
-#include "ui/gfx/animation/tween.h"
-#include "ui/views/view.h"
-
-namespace app_list {
-class AppListModelObserver;
-class AppListViewDelegate;
-class SearchBoxView;
-class SearchResultListView;
-}
-
-namespace athena {
-
-class ATHENA_EXPORT AthenaStartPageView
- : public views::View,
- public app_list::SearchBoxViewDelegate,
- public app_list::AppListItemListObserver {
- public:
- class Observer {
- public:
- virtual void OnLayoutStateChanged(float new_state) = 0;
- };
-
- explicit AthenaStartPageView(app_list::AppListViewDelegate* delegate);
- ~AthenaStartPageView() override;
-
- // Requests the focus on the search box in the start page view.
- void RequestFocusOnSearchBox();
-
- // Updates the layout state. See the comment of |layout_state_| field.
- void SetLayoutState(float layout_state);
-
- // Updates the layout state and move the subviews to the target location with
- // animation.
- void SetLayoutStateWithAnimation(float layout_state,
- gfx::Tween::Type tween_type);
-
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
- private:
- friend class AthenaStartPageViewTest;
-
- static const char kViewClassName[];
-
- static size_t GetMaxIconNumForTest();
-
- // A struct which bundles the layout data of subviews.
- struct LayoutData {
- gfx::Rect search_box;
- gfx::Rect icons;
- gfx::Rect controls;
- float system_info_opacity;
- float logo_opacity;
-
- LayoutData();
- };
-
- // Returns the bounds for |VISIBLE_BOTTOM|.
- LayoutData CreateBottomBounds(int width);
-
- // Returns the bounds for |VISIBLE_CENTERED|.
- LayoutData CreateCenteredBounds(int width);
-
- void UpdateAppIcons();
-
- // Schedules the animation for the layout the search box and the search
- // results.
- void LayoutSearchResults(bool should_show_search_results);
-
- // Called when the animation of search box / search results layout has
- // completed.
- void OnSearchResultLayoutAnimationCompleted(bool should_show_search_results);
-
- // views::View:
- void Layout() override;
- bool OnKeyPressed(const ui::KeyEvent& key_event) override;
-
- // app_list::SearchBoxViewDelegate:
- void QueryChanged(app_list::SearchBoxView* sender) override;
-
- // app_list::AppListItemListObserver:
- void OnListItemAdded(size_t index, app_list::AppListItem* item) override;
- void OnListItemRemoved(size_t index, app_list::AppListItem* item) override;
- void OnListItemMoved(size_t from_index,
- size_t to_index,
- app_list::AppListItem* item) override;
-
- // Not owned.
- app_list::AppListViewDelegate* delegate_;
-
- // Views are owned through its hierarchy.
- views::View* system_info_view_;
- views::View* app_icon_container_;
- views::View* search_box_container_;
- views::View* control_icon_container_;
- views::View* logo_;
- app_list::SearchBoxView* search_box_view_;
- app_list::SearchResultListView* search_results_view_;
-
- // The expected height of |search_results_view_|
- int search_results_height_;
-
- // The state to specify how each of the subviews should be laid out, in the
- // range of [0, 1]. 0 means fully BOTTOM state, and 1 is fully CENTERED state.
- float layout_state_;
-
- ObserverList<Observer> observers_;
-
- base::WeakPtrFactory<AthenaStartPageView> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AthenaStartPageView);
-};
-
-} // namespace athena
-
-#endif // ATHENA_HOME_ATHENA_START_PAGE_VIEW_H_
diff --git a/athena/home/athena_start_page_view_unittest.cc b/athena/home/athena_start_page_view_unittest.cc
deleted file mode 100644
index 9019999134..0000000000
--- a/athena/home/athena_start_page_view_unittest.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "athena/home/athena_start_page_view.h"
-
-#include "athena/home/home_card_constants.h"
-#include "athena/test/base/athena_test_base.h"
-#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "ui/app_list/app_list_switches.h"
-#include "ui/app_list/search_box_model.h"
-#include "ui/app_list/test/app_list_test_model.h"
-#include "ui/app_list/test/app_list_test_view_delegate.h"
-#include "ui/app_list/views/search_box_view.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/views/controls/textfield/textfield.h"
-
-namespace athena {
-
-class AthenaTestViewDelegate : public app_list::test::AppListTestViewDelegate {
- public:
- AthenaTestViewDelegate() {}
- ~AthenaTestViewDelegate() override {}
-
- private:
- // app_list::AppListViewDelegate:
- views::View* CreateStartPageWebView(const gfx::Size& size) override {
- return new views::View();
- }
-
- DISALLOW_COPY_AND_ASSIGN(AthenaTestViewDelegate);
-};
-
-class AthenaStartPageViewTest : public test::AthenaTestBase {
- public:
- AthenaStartPageViewTest() {}
- ~AthenaStartPageViewTest() override {}
-
- // testing::Test:
- void SetUp() override {
- test::AthenaTestBase::SetUp();
- for (size_t i = 0; i < GetMaxIconNum(); ++i)
- AddTestItem(i);
-
- view_.reset(new AthenaStartPageView(&view_delegate_));
- SetSize(gfx::Size(1280, 800));
- }
- void TearDown() override {
- view_.reset();
- test::AthenaTestBase::TearDown();
- }
-
- protected:
- void SetSize(const gfx::Size& new_size) {
- view_->SetSize(new_size);
- view_->Layout();
- }
-
- void AddTestItem(size_t index) {
- app_list::test::AppListTestModel* model = view_delegate_.GetTestModel();
- model->AddItem(new app_list::test::AppListTestModel::AppListTestItem(
- GetAppIdFor(index), model));
- }
-
- static size_t GetMaxIconNum() {
- return AthenaStartPageView::GetMaxIconNumForTest();
- }
-
- static std::string GetAppIdFor(size_t index) {
- return base::StringPrintf("id-%" PRIuS, index);
- }
-
- app_list::AppListModel* GetModel() { return view_delegate_.GetTestModel(); }
-
- views::View* GetIconsContainer() { return view_->app_icon_container_; }
-
- gfx::Rect GetIconsBounds() const {
- return view_->app_icon_container_->layer()->GetTargetBounds();
- }
-
- gfx::Rect GetControlBounds() const {
- return view_->control_icon_container_->layer()->GetTargetBounds();
- }
-
- gfx::Rect GetSearchBoxBounds() const {
- return view_->search_box_container_->layer()->GetTargetBounds();
- }
-
- gfx::Rect GetLogoBounds() const {
- return view_->logo_->layer()->GetTargetBounds();
- }
-
- bool IsLogoVisible() const {
- return view_->logo_->layer()->GetTargetOpacity() > 0 &&
- view_->logo_->layer()->GetTargetVisibility();
- }
-
- gfx::Size GetSearchBoxPreferredSize() {
- return view_->search_box_container_->GetPreferredSize();
- }
-
- void SetSearchQuery(const base::string16& query) {
- view_delegate_.GetModel()->search_box()->SetText(query);
- }
-
- base::string16 GetVisibleQuery() {
- return view_->search_box_view_->search_box()->text();
- }
-
- float layout_state() { return view_->layout_state_; }
-
- scoped_ptr<AthenaStartPageView> view_;
-
- private:
- AthenaTestViewDelegate view_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(AthenaStartPageViewTest);
-};
-
-TEST_F(AthenaStartPageViewTest, BasicLayout) {
- // BOTTOM state. logo is invisible. icons, search box, and controls are
- // arranged horizontally.
- EXPECT_FALSE(IsLogoVisible());
-
- // Three components are aligned at the middle point.
- EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
- GetControlBounds().CenterPoint().y(),
- 1);
- EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
- GetSearchBoxBounds().CenterPoint().y(),
- 1);
- EXPECT_NEAR(GetControlBounds().CenterPoint().y(),
- GetSearchBoxBounds().CenterPoint().y(),
- 1);
-
- // Horizonttaly aligned in the order of icons, search_box, and controls.
- EXPECT_LE(GetIconsBounds().right(), GetSearchBoxBounds().x());
- EXPECT_LE(GetSearchBoxBounds().right(), GetControlBounds().x());
- EXPECT_LE(0, GetIconsBounds().y());
-
- // Search box should appear in the middle.
- EXPECT_NEAR(GetSearchBoxBounds().CenterPoint().x(),
- view_->bounds().CenterPoint().x(),
- 1);
-
- // Should fit inside of the home card height.
- EXPECT_GE(kHomeCardHeight, GetIconsBounds().height());
- EXPECT_GE(kHomeCardHeight, GetSearchBoxBounds().height());
- EXPECT_GE(kHomeCardHeight, GetControlBounds().height());
- EXPECT_EQ(GetSearchBoxPreferredSize().ToString(),
- GetSearchBoxBounds().size().ToString());
-
- // CENTERED state. logo is visible. search box appears below the logo,
- // icons and controls are arranged horizontally and below the search box.
- view_->SetLayoutState(1.0f);
- EXPECT_TRUE(IsLogoVisible());
- EXPECT_NEAR(GetLogoBounds().x() + GetLogoBounds().width() / 2,
- GetSearchBoxBounds().x() + GetSearchBoxBounds().width() / 2,
- 1);
- EXPECT_LE(GetLogoBounds().bottom(), GetSearchBoxBounds().y());
- EXPECT_EQ(GetIconsBounds().y(), GetControlBounds().y());
- EXPECT_LE(GetIconsBounds().right(), GetControlBounds().x());
- EXPECT_LE(GetSearchBoxBounds().bottom(), GetIconsBounds().y());
-}
-
-TEST_F(AthenaStartPageViewTest, NarrowLayout) {
- SetSize(gfx::Size(800, 1280));
-
- // BOTTOM state. Similar to BasicLayout.
- EXPECT_FALSE(IsLogoVisible());
- // Three components are aligned at the middle point.
- EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
- GetControlBounds().CenterPoint().y(),
- 1);
- EXPECT_NEAR(GetIconsBounds().CenterPoint().y(),
- GetSearchBoxBounds().CenterPoint().y(),
- 1);
- EXPECT_NEAR(GetControlBounds().CenterPoint().y(),
- GetSearchBoxBounds().CenterPoint().y(),
- 1);
-
- // Horizonttaly aligned in the order of icons, search_box, and controls.
- EXPECT_LE(GetIconsBounds().right(), GetSearchBoxBounds().x());
- EXPECT_LE(GetSearchBoxBounds().right(), GetControlBounds().x());
- EXPECT_LE(0, GetIconsBounds().y());
-
- // Search box should appear in the middle.
- EXPECT_NEAR(GetSearchBoxBounds().CenterPoint().x(),
- view_->bounds().CenterPoint().x(),
- 1);
-
- // Should fit inside of the home card height.
- EXPECT_GE(kHomeCardHeight, GetIconsBounds().height());
- EXPECT_GE(kHomeCardHeight, GetSearchBoxBounds().height());
- EXPECT_GE(kHomeCardHeight, GetControlBounds().height());
-
- // Search box is narrower because of the size is too narrow.
- EXPECT_GT(GetSearchBoxPreferredSize().width(), GetSearchBoxBounds().width());
- EXPECT_EQ(GetSearchBoxPreferredSize().height(),
- GetSearchBoxBounds().height());
-
- // CENTERED state. Search box should be back to the preferred size.
- view_->SetLayoutState(1.0f);
- EXPECT_EQ(GetSearchBoxPreferredSize().ToString(),
- GetSearchBoxBounds().size().ToString());
-
- // Back to BOTTOM state, the search box shrinks again.
- view_->SetLayoutState(0.0f);
- EXPECT_GT(GetSearchBoxPreferredSize().width(), GetSearchBoxBounds().width());
-
- // Then set back to the original size, now the size is wide enough so the
- // search box bounds becomes as preferred.
- SetSize(gfx::Size(1280, 800));
- EXPECT_EQ(GetSearchBoxPreferredSize().ToString(),
- GetSearchBoxBounds().size().ToString());
-}
-
-TEST_F(AthenaStartPageViewTest, SearchBox) {
- view_->SetLayoutState(1.0f);
- EXPECT_TRUE(IsLogoVisible());
-
- const gfx::Rect base_search_box_bounds = GetSearchBoxBounds();
-
- const base::string16 query = base::UTF8ToUTF16("test");
- SetSearchQuery(query);
-
- EXPECT_FALSE(IsLogoVisible());
- EXPECT_GT(base_search_box_bounds.y(), GetSearchBoxBounds().y());
- EXPECT_EQ(query, GetVisibleQuery());
-
- SetSearchQuery(base::string16());
- EXPECT_TRUE(IsLogoVisible());
- EXPECT_EQ(base_search_box_bounds.ToString(), GetSearchBoxBounds().ToString());
- EXPECT_TRUE(GetVisibleQuery().empty());
-}
-
-TEST_F(AthenaStartPageViewTest, SearchFromBottom) {
- view_->SetLayoutState(0.0f);
-
- const base::string16 query = base::UTF8ToUTF16("test");
- SetSearchQuery(query);
-
- EXPECT_FALSE(IsLogoVisible());
- EXPECT_EQ(query, GetVisibleQuery());
- EXPECT_EQ(1.0f, layout_state());
-
- SetSearchQuery(base::string16());
- EXPECT_TRUE(IsLogoVisible());
- EXPECT_TRUE(GetVisibleQuery().empty());
- EXPECT_EQ(1.0f, layout_state());
-}
-
-TEST_F(AthenaStartPageViewTest, AppAddRemove) {
- gfx::Rect icons_bounds = GetIconsBounds();
- EXPECT_EQ(GetMaxIconNum(),
- static_cast<size_t>(GetIconsContainer()->child_count()));
-
- GetModel()->DeleteItem(GetAppIdFor(1));
-
- // The removed icon disappear, however its bound should not change.
- EXPECT_EQ(GetMaxIconNum() - 1,
- static_cast<size_t>(GetIconsContainer()->child_count()));
- EXPECT_EQ(icons_bounds.size().ToString(), GetIconsBounds().size().ToString());
-
- AddTestItem(GetMaxIconNum() + 1);
- EXPECT_EQ(GetMaxIconNum(),
- static_cast<size_t>(GetIconsContainer()->child_count()));
- EXPECT_EQ(icons_bounds.size().ToString(), GetIconsBounds().size().ToString());
-
- // Adding more doesn't cause any effects.
- AddTestItem(GetMaxIconNum() + 2);
- EXPECT_EQ(GetMaxIconNum(),
- static_cast<size_t>(GetIconsContainer()->child_count()));
- EXPECT_EQ(icons_bounds.size().ToString(), GetIconsBounds().size().ToString());
-}
-
-} // namespace athena
diff --git a/athena/home/home_card_constants.cc b/athena/home/home_card_constants.cc
index 1bf28753bf..2a951c6acf 100644
--- a/athena/home/home_card_constants.cc
+++ b/athena/home/home_card_constants.cc
@@ -6,7 +6,7 @@
namespace athena {
-const int kHomeCardHeight = 100;
+const int kHomeCardHeight = 212;
const int kHomeCardDragIndicatorHeight = 2;
const int kHomeCardDragIndicatorWidth = 48;
const int kHomeCardDragIndicatorMarginHeight = 7;
diff --git a/athena/home/home_card_gesture_manager_unittest.cc b/athena/home/home_card_gesture_manager_unittest.cc
index c5c40fcfee..91d70305fc 100644
--- a/athena/home/home_card_gesture_manager_unittest.cc
+++ b/athena/home/home_card_gesture_manager_unittest.cc
@@ -186,8 +186,8 @@ TEST_F(HomeCardGestureManagerTest, StartCentered) {
EXPECT_EQ(HomeCard::VISIBLE_CENTERED, last_to_state_);
EXPECT_EQ(1.0f, last_progress_);
- ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 900);
- ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 910);
+ ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 700);
+ ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 710);
EXPECT_EQ(2, GetProgressCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, last_from_state_);
EXPECT_EQ(HomeCard::VISIBLE_CENTERED, last_to_state_);
@@ -218,13 +218,13 @@ TEST_F(HomeCardGestureManagerTest, StartBottom) {
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, final_state_);
// State change for the bigger moves.
- EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 950));
+ EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 850));
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 1000);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 1000));
EXPECT_EQ(1, GetEndCountAndReset());
EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, final_state_);
- EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 950));
+ EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN, 850));
ProcessGestureEvent(ui::ET_GESTURE_SCROLL_UPDATE, 300);
EXPECT_TRUE(ProcessGestureEvent(ui::ET_GESTURE_SCROLL_END, 300));
EXPECT_EQ(1, GetEndCountAndReset());
diff --git a/athena/home/home_card_impl.cc b/athena/home/home_card_impl.cc
index f6a64f382f..e9f468a4c0 100644
--- a/athena/home/home_card_impl.cc
+++ b/athena/home/home_card_impl.cc
@@ -9,14 +9,14 @@
#include "athena/env/public/athena_env.h"
#include "athena/home/app_list_view_delegate.h"
-#include "athena/home/athena_start_page_view.h"
#include "athena/home/home_card_constants.h"
#include "athena/home/public/app_model_builder.h"
#include "athena/screen/public/screen_manager.h"
#include "athena/util/container_priorities.h"
#include "athena/wm/public/window_manager.h"
+#include "ui/app_list/search_box_model.h"
#include "ui/app_list/views/app_list_main_view.h"
-#include "ui/app_list/views/contents_view.h"
+#include "ui/app_list/views/search_box_view.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/compositor/closure_animation_observer.h"
@@ -36,6 +36,8 @@ namespace {
HomeCard* instance = nullptr;
const float kMinimizedHomeOpacity = 0.65f;
+const int kIndicatorOffset = 24;
+const int kAppListOffset = -128;
gfx::Rect GetBoundsForState(const gfx::Rect& screen_bounds,
HomeCard::State state) {
@@ -122,14 +124,15 @@ class HomeCardLayoutManager : public aura::LayoutManager {
};
// The container view of home card contents of each state.
-class HomeCardView : public views::WidgetDelegateView,
- public AthenaStartPageView::Observer {
+class HomeCardView : public views::WidgetDelegateView {
public:
HomeCardView(app_list::AppListViewDelegate* view_delegate,
aura::Window* container,
HomeCardGestureManager::Delegate* gesture_delegate)
: background_(new views::View),
- main_view_(new AthenaStartPageView(view_delegate)),
+ main_view_(new app_list::AppListMainView(view_delegate)),
+ search_box_view_(
+ new app_list::SearchBoxView(main_view_, view_delegate)),
minimized_background_(new views::View()),
drag_indicator_(new views::View()),
gesture_delegate_(gesture_delegate),
@@ -141,13 +144,16 @@ class HomeCardView : public views::WidgetDelegateView,
background_->SetFillsBoundsOpaquely(false);
AddChildView(background_);
- // Ideally AppListMainView should be used here and have AthenaStartPageView
- // as its child view, so that custom pages and apps grid are available in
- // the home card.
- // TODO(mukai): make it so after the detailed UI has been fixed.
- main_view_->AddObserver(this);
+ main_view_->SetPaintToLayer(true);
+ main_view_->SetFillsBoundsOpaquely(false);
+ main_view_->layer()->SetMasksToBounds(true);
AddChildView(main_view_);
+ search_box_view_->SetPaintToLayer(true);
+ search_box_view_->SetFillsBoundsOpaquely(false);
+ search_box_view_->layer()->SetMasksToBounds(true);
+ AddChildView(search_box_view_);
+
minimized_background_->set_background(
views::Background::CreateSolidBackground(
SkColorSetA(SK_ColorBLACK, 256 * kMinimizedHomeOpacity)));
@@ -162,17 +168,30 @@ class HomeCardView : public views::WidgetDelegateView,
AddChildView(drag_indicator_);
}
- ~HomeCardView() override { main_view_->RemoveObserver(this); }
+ void Init() {
+ main_view_->Init(GetWidget()->GetNativeView(),
+ -1, /* inital apps page: -1 means default */
+ search_box_view_);
+ }
void SetStateProgress(HomeCard::State from_state,
HomeCard::State to_state,
float progress) {
// TODO(mukai): not clear the focus, but simply close the virtual keyboard.
GetFocusManager()->ClearFocus();
- if (from_state == HomeCard::VISIBLE_CENTERED)
- main_view_->SetLayoutState(1.0f - progress);
- else if (to_state == HomeCard::VISIBLE_CENTERED)
- main_view_->SetLayoutState(progress);
+
+ gfx::Rect from_main_bounds = GetMainViewBounds(from_state);
+ gfx::Rect to_main_bounds = GetMainViewBounds(to_state);
+ if (from_main_bounds != to_main_bounds) {
+ DCHECK_EQ(from_main_bounds.size().ToString(),
+ to_main_bounds.size().ToString());
+ gfx::Rect main_bounds = gfx::Tween::RectValueBetween(
+ progress, from_main_bounds, to_main_bounds);
+ main_view_->SetBoundsRect(main_bounds);
+ main_bounds.set_height(
+ search_box_view_->GetHeightForWidth(main_bounds.width()));
+ search_box_view_->SetBoundsRect(main_bounds);
+ }
float background_opacity = 1.0f;
if (from_state == HomeCard::VISIBLE_MINIMIZED ||
@@ -207,7 +226,8 @@ class HomeCardView : public views::WidgetDelegateView,
}
void SetStateWithAnimation(HomeCard::State state,
- gfx::Tween::Type tween_type) {
+ gfx::Tween::Type tween_type,
+ const base::Closure& on_animation_ended) {
float minimized_opacity =
(state == HomeCard::VISIBLE_MINIMIZED) ? 1.0f : 0.0f;
// |minimized_background_| needs to be visible before scheduling animation.
@@ -241,20 +261,27 @@ class HomeCardView : public views::WidgetDelegateView,
background_->layer()->SetOpacity(background_opacity);
}
- if (state == HomeCard::VISIBLE_CENTERED)
- main_view_->RequestFocusOnSearchBox();
- else
- GetWidget()->GetFocusManager()->ClearFocus();
-
{
ui::ScopedLayerAnimationSettings settings(
drag_indicator_->layer()->GetAnimator());
- settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
+ settings.SetTweenType(tween_type);
drag_indicator_->SetBoundsRect(GetDragIndicatorBounds(state));
}
- main_view_->SetLayoutStateWithAnimation(
- (state == HomeCard::VISIBLE_CENTERED) ? 1.0f : 0.0f, tween_type);
+ {
+ ui::ScopedLayerAnimationSettings settings(
+ main_view_->layer()->GetAnimator());
+ settings.SetTweenType(tween_type);
+ settings.AddObserver(
+ new ui::ClosureAnimationObserver(on_animation_ended));
+ gfx::Rect main_bounds = GetMainViewBounds(state);
+ main_view_->SetBoundsRect(main_bounds);
+ main_bounds.set_height(
+ search_box_view_->GetHeightForWidth(main_bounds.width()));
+ search_box_view_->SetBoundsRect(main_bounds);
+ }
+
+ main_view_->UpdateSearchBoxVisibility();
}
void ClearGesture() {
@@ -282,6 +309,23 @@ class HomeCardView : public views::WidgetDelegateView,
return false;
}
+ void Layout() override {
+ const gfx::Rect contents_bounds = GetContentsBounds();
+ background_->SetBoundsRect(contents_bounds);
+ minimized_background_->SetBoundsRect(contents_bounds);
+ const gfx::Rect drag_indicator_bounds =
+ GetDragIndicatorBounds(HomeCard::Get()->GetState());
+ drag_indicator_->SetBoundsRect(drag_indicator_bounds);
+
+ gfx::Rect main_bounds(GetMainViewBounds(HomeCard::Get()->GetState()));
+ main_view_->SetBoundsRect(main_bounds);
+
+ main_bounds.set_height(
+ search_box_view_->GetHeightForWidth(main_bounds.width()));
+ search_box_view_->SetBoundsRect(main_bounds);
+ }
+
+ private:
gfx::Rect GetDragIndicatorBounds(HomeCard::State state) {
gfx::Rect drag_indicator_bounds(
GetContentsBounds().CenterPoint().x() - kHomeCardDragIndicatorWidth / 2,
@@ -293,13 +337,19 @@ class HomeCardView : public views::WidgetDelegateView,
return drag_indicator_bounds;
}
- void Layout() override {
- gfx::Rect contents_bounds = GetContentsBounds();
- background_->SetBoundsRect(contents_bounds);
- main_view_->SetBoundsRect(contents_bounds);
- minimized_background_->SetBoundsRect(contents_bounds);
- drag_indicator_->SetBoundsRect(
- GetDragIndicatorBounds(HomeCard::Get()->GetState()));
+ gfx::Rect GetMainViewBounds(HomeCard::State state) {
+ const gfx::Rect contents_bounds = GetContentsBounds();
+ const int main_width = main_view_->GetPreferredSize().width();
+ gfx::Rect main_bounds(
+ contents_bounds.CenterPoint().x() - main_width / 2,
+ GetDragIndicatorBounds(state).bottom() + kIndicatorOffset,
+ main_width,
+ contents_bounds.height());
+ // This is a bit hacky but slightly shifting up the main_view to fit
+ // the search box and app icons in the home card.
+ if (state != HomeCard::VISIBLE_CENTERED)
+ main_bounds.set_y(kAppListOffset);
+ return main_bounds;
}
private:
@@ -311,14 +361,9 @@ class HomeCardView : public views::WidgetDelegateView,
// views::WidgetDelegate:
views::View* GetContentsView() override { return this; }
- // AthenaStartPageView::Observer:
- void OnLayoutStateChanged(float new_state) override {
- if (new_state == 1.0f)
- HomeCard::Get()->SetState(HomeCard::VISIBLE_CENTERED);
- }
-
views::View* background_;
- AthenaStartPageView* main_view_;
+ app_list::AppListMainView* main_view_;
+ app_list::SearchBoxView* search_box_view_;
views::View* minimized_background_;
views::View* drag_indicator_;
HomeCard::State state_;
@@ -376,7 +421,12 @@ void HomeCardImpl::Init() {
widget_params.delegate = home_card_view_;
widget_params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
home_card_widget_->Init(widget_params);
+ // AppListMainView in home card may move outside of home card layer partially
+ // in an transition animation. This flag is set to clip the parts outside of
+ // home card.
+ home_card_widget_->GetNativeWindow()->layer()->SetMasksToBounds(true);
+ home_card_view_->Init();
SetState(VISIBLE_MINIMIZED);
home_card_view_->Layout();
@@ -388,6 +438,10 @@ aura::Window* HomeCardImpl::GetHomeCardWindowForTest() const {
return home_card_widget_ ? home_card_widget_->GetNativeWindow() : nullptr;
}
+void HomeCardImpl::ResetQuery() {
+ view_delegate_->GetModel()->search_box()->SetText(base::string16());
+}
+
void HomeCardImpl::InstallAccelerators() {
const AcceleratorData accelerator_data[] = {
{TRIGGER_ON_PRESS, ui::VKEY_L, ui::EF_CONTROL_DOWN,
@@ -413,7 +467,13 @@ void HomeCardImpl::SetState(HomeCard::State state) {
home_card_widget_->ShowInactive();
else
home_card_widget_->Show();
- home_card_view_->SetStateWithAnimation(state, gfx::Tween::EASE_IN_OUT);
+
+ // Query should be reset on state change to reset the main_view. Also it's
+ // not possible to invoke ResetQuery() here, it causes a crash on search.
+ home_card_view_->SetStateWithAnimation(
+ state,
+ gfx::Tween::EASE_IN_OUT,
+ base::Bind(&HomeCardImpl::ResetQuery, base::Unretained(this)));
layout_manager_->Layout(true, gfx::Tween::EASE_IN_OUT);
}
}
@@ -469,7 +529,10 @@ void HomeCardImpl::OnGestureEnded(State final_state, bool is_fling) {
// EASE_OUT is better.
gfx::Tween::Type tween_type =
is_fling ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN_OUT;
- home_card_view_->SetStateWithAnimation(state_, tween_type);
+ home_card_view_->SetStateWithAnimation(
+ state_,
+ tween_type,
+ base::Bind(&HomeCardImpl::ResetQuery, base::Unretained(this)));
layout_manager_->Layout(true, tween_type);
}
}
diff --git a/athena/home/home_card_impl.h b/athena/home/home_card_impl.h
index f330b104e8..a35c31b50d 100644
--- a/athena/home/home_card_impl.h
+++ b/athena/home/home_card_impl.h
@@ -12,6 +12,10 @@
#include "athena/input/public/accelerator_manager.h"
#include "athena/wm/public/window_manager_observer.h"
+namespace app_list {
+class AppListViewDelegate;
+}
+
namespace aura {
class Window;
}
@@ -30,7 +34,6 @@ class Widget;
namespace athena {
class AppModelBuilder;
-class AppListViewDelegate;
class HomeCardLayoutManager;
class HomeCardView;
@@ -53,6 +56,8 @@ class ATHENA_EXPORT HomeCardImpl : public HomeCard,
};
void InstallAccelerators();
+ void ResetQuery();
+
// Overridden from HomeCard:
void SetState(HomeCard::State state) override;
State GetState() override;
@@ -86,7 +91,7 @@ class ATHENA_EXPORT HomeCardImpl : public HomeCard,
views::Widget* home_card_widget_;
HomeCardView* home_card_view_;
- scoped_ptr<AppListViewDelegate> view_delegate_;
+ scoped_ptr<app_list::AppListViewDelegate> view_delegate_;
HomeCardLayoutManager* layout_manager_;
DISALLOW_COPY_AND_ASSIGN(HomeCardImpl);
diff --git a/athena/home/home_card_unittest.cc b/athena/home/home_card_unittest.cc
index abbdbdfebf..8afa0ae2b1 100644
--- a/athena/home/home_card_unittest.cc
+++ b/athena/home/home_card_unittest.cc
@@ -28,12 +28,6 @@ aura::Window* GetHomeCardWindow() {
GetHomeCardWindowForTest();
}
-// Returns true if the keyboard focus is on the search box.
-bool IsSearchBoxFocused(aura::Window* home_card) {
- return views::Widget::GetWidgetForNativeWindow(home_card)->
- GetContentsView()->GetViewByID(kHomeCardSearchBoxId)->HasFocus();
-}
-
typedef test::AthenaTestBase HomeCardTest;
TEST_F(HomeCardTest, BasicTransition) {
@@ -265,35 +259,6 @@ TEST_F(HomeCardTest, GesturesToFullDirectly) {
EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
}
-TEST_F(HomeCardTest, KeyboardFocus) {
- ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
- aura::Window* home_card = GetHomeCardWindow();
- ASSERT_FALSE(IsSearchBoxFocused(home_card));
-
- WindowManager::Get()->EnterOverview();
- ASSERT_FALSE(IsSearchBoxFocused(home_card));
-
- ui::test::EventGenerator generator(root_window());
- gfx::Rect screen_rect(root_window()->bounds());
-
- const int bottom = screen_rect.bottom();
- const int x = screen_rect.x() + 1;
-
- generator.GestureScrollSequence(gfx::Point(x, bottom - 40),
- gfx::Point(x, 10),
- base::TimeDelta::FromSeconds(1),
- 10);
- EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
- EXPECT_TRUE(IsSearchBoxFocused(home_card));
-
- generator.GestureScrollSequence(gfx::Point(x, 10),
- gfx::Point(x, bottom - 100),
- base::TimeDelta::FromSeconds(1),
- 10);
- EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
- EXPECT_FALSE(IsSearchBoxFocused(home_card));
-}
-
TEST_F(HomeCardTest, DontMinimizeWithModalWindow) {
aura::Window* home_card = GetHomeCardWindow();
@@ -313,10 +278,7 @@ TEST_F(HomeCardTest, DontMinimizeWithModalWindow) {
modal.reset();
EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
-
- // TODO(oshima): The focus should be set to home card. Flip the
- // condition once crbug.com/424750 is fixed.a
- EXPECT_FALSE(wm::IsActiveWindow(home_card));
+ EXPECT_TRUE(wm::IsActiveWindow(home_card));
}
} // namespace athena
diff --git a/athena/main/DEPS b/athena/main/DEPS
index d0ff633099..2724d27414 100644
--- a/athena/main/DEPS
+++ b/athena/main/DEPS
@@ -31,7 +31,7 @@ include_rules = [
]
specific_include_rules = {
- "athena_main\.cc": [
+ "athena_main_delegate.*": [
"+content/public/app",
"+extensions/browser/app_window",
"+extensions/shell/app",
diff --git a/athena/main/athena_frame_view.h b/athena/main/athena_frame_view.h
index c385ed93ff..b3829a8685 100644
--- a/athena/main/athena_frame_view.h
+++ b/athena/main/athena_frame_view.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef ATHENA_COMMON_ATHENA_FRAME_VIEW_H_
-#define ATHENA_COMMON_ATHENA_FRAME_VIEW_H_
+#ifndef ATHENA_MAIN_ATHENA_FRAME_VIEW_H_
+#define ATHENA_MAIN_ATHENA_FRAME_VIEW_H_
#include "ui/views/window/non_client_view.h"
@@ -54,4 +54,4 @@ class AthenaFrameView : public views::NonClientFrameView {
} // namespace athena
-#endif // ATHENA_COMMON_ATHENA_FRAME_VIEW_H_
+#endif // ATHENA_MAIN_ATHENA_FRAME_VIEW_H_
diff --git a/athena/main/athena_main.cc b/athena/main/athena_main.cc
index 98fe171c84..1eab12834d 100644
--- a/athena/main/athena_main.cc
+++ b/athena/main/athena_main.cc
@@ -2,196 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "athena/activity/public/activity_factory.h"
-#include "athena/activity/public/activity_manager.h"
-#include "athena/content/public/web_contents_view_delegate_creator.h"
-#include "athena/env/public/athena_env.h"
-#include "athena/extensions/public/extensions_delegate.h"
-#include "athena/main/athena_content_client.h"
-#include "athena/main/athena_renderer_pdf_helper.h"
-#include "athena/main/public/athena_launcher.h"
-#include "athena/screen/public/screen_manager.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "components/pdf/renderer/ppb_pdf_impl.h"
+#include "athena/main/athena_main_delegate.h"
#include "content/public/app/content_main.h"
-#include "content/public/browser/browser_thread.h"
-#include "extensions/browser/app_window/app_window.h"
-#include "extensions/browser/app_window/app_window_client.h"
-#include "extensions/shell/app/shell_main_delegate.h"
-#include "extensions/shell/browser/desktop_controller.h"
-#include "extensions/shell/browser/shell_app_delegate.h"
-#include "extensions/shell/browser/shell_browser_main_delegate.h"
-#include "extensions/shell/browser/shell_content_browser_client.h"
-#include "extensions/shell/browser/shell_extension_system.h"
-#include "extensions/shell/browser/shell_native_app_window.h"
-#include "extensions/shell/common/shell_content_client.h"
-#include "extensions/shell/common/switches.h"
-#include "extensions/shell/renderer/shell_content_renderer_client.h"
-#include "ppapi/c/private/ppb_pdf.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/wm/core/visibility_controller.h"
-
-namespace {
-
-// We want to load the sample calculator app by default, for a while. Expecting
-// to run athena_main at src/
-const char kDefaultAppPath[] =
- "chrome/common/extensions/docs/examples/apps/calculator/app";
-
-} // namespace
-
-class AthenaDesktopController : public extensions::DesktopController {
- public:
- AthenaDesktopController() {}
- ~AthenaDesktopController() override {}
-
- private:
- // extensions::DesktopController:
- virtual aura::WindowTreeHost* GetHost() override {
- return athena::AthenaEnv::Get()->GetHost();
- }
-
- // Creates a new app window and adds it to the desktop. The desktop maintains
- // ownership of the window.
- // TODO(jamescook|oshima): Is this function needed?
- virtual extensions::AppWindow* CreateAppWindow(
- content::BrowserContext* context,
- const extensions::Extension* extension) override {
- NOTIMPLEMENTED();
- return nullptr;
- }
-
- // Adds the window to the desktop.
- virtual void AddAppWindow(aura::Window* window) override {
- NOTIMPLEMENTED();
- }
-
- virtual void RemoveAppWindow(extensions::AppWindow* window) override {}
-
- // Closes and destroys the app windows.
- virtual void CloseAppWindows() override {}
-
- DISALLOW_COPY_AND_ASSIGN(AthenaDesktopController);
-};
-
-class AthenaBrowserMainDelegate : public extensions::ShellBrowserMainDelegate {
- public:
- AthenaBrowserMainDelegate() {}
- ~AthenaBrowserMainDelegate() override {}
-
- // extensions::ShellBrowserMainDelegate:
- virtual void Start(content::BrowserContext* context) override {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-
- base::FilePath app_dir = base::FilePath::FromUTF8Unsafe(
- command_line->HasSwitch(extensions::switches::kAppShellAppPath)
- ? command_line->GetSwitchValueNative(
- extensions::switches::kAppShellAppPath)
- : kDefaultAppPath);
-
- base::FilePath app_absolute_dir = base::MakeAbsoluteFilePath(app_dir);
- if (base::DirectoryExists(app_absolute_dir)) {
- extensions::ShellExtensionSystem* extension_system =
- static_cast<extensions::ShellExtensionSystem*>(
- extensions::ExtensionSystem::Get(context));
- extension_system->LoadApp(app_absolute_dir);
- }
-
- athena::StartAthenaEnv(content::BrowserThread::GetBlockingPool()->
- GetTaskRunnerWithShutdownBehavior(
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
- athena::CreateVirtualKeyboardWithContext(context);
- athena::StartAthenaSessionWithContext(context);
- }
-
- virtual void Shutdown() override {
- athena::AthenaEnv::Get()->OnTerminating();
- athena::ShutdownAthena();
- }
-
- virtual extensions::DesktopController* CreateDesktopController() override {
- return new AthenaDesktopController();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AthenaBrowserMainDelegate);
-};
-
-class AthenaContentBrowserClient
- : public extensions::ShellContentBrowserClient {
- public:
- AthenaContentBrowserClient()
- : extensions::ShellContentBrowserClient(new AthenaBrowserMainDelegate()) {
- }
- ~AthenaContentBrowserClient() override {}
-
- // content::ContentBrowserClient:
- virtual content::WebContentsViewDelegate* GetWebContentsViewDelegate(
- content::WebContents* web_contents) override {
- return athena::CreateWebContentsViewDelegate(web_contents);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AthenaContentBrowserClient);
-};
-
-class AthenaContentRendererClient
- : public extensions::ShellContentRendererClient {
- public:
- AthenaContentRendererClient() {}
- ~AthenaContentRendererClient() override {}
-
- // content::ContentRendererClient:
- virtual void RenderFrameCreated(content::RenderFrame* render_frame) override {
- new athena::AthenaRendererPDFHelper(render_frame);
- extensions::ShellContentRendererClient::RenderFrameCreated(render_frame);
- }
-
- virtual const void* CreatePPAPIInterface(
- const std::string& interface_name) override {
- if (interface_name == PPB_PDF_INTERFACE)
- return pdf::PPB_PDF_Impl::GetInterface();
- return extensions::ShellContentRendererClient::CreatePPAPIInterface(
- interface_name);
- }
-};
-
-class AthenaMainDelegate : public extensions::ShellMainDelegate {
- public:
- AthenaMainDelegate() {}
- ~AthenaMainDelegate() override {}
-
- private:
- // extensions::ShellMainDelegate:
- virtual content::ContentClient* CreateContentClient() override {
- return new athena::AthenaContentClient();
- }
- virtual content::ContentBrowserClient* CreateShellContentBrowserClient()
- override {
- return new AthenaContentBrowserClient();
- }
-
- virtual content::ContentRendererClient* CreateShellContentRendererClient()
- override {
- return new AthenaContentRendererClient();
- }
-
- virtual void InitializeResourceBundle() override {
- base::FilePath pak_dir;
- PathService::Get(base::DIR_MODULE, &pak_dir);
- base::FilePath pak_file =
- pak_dir.Append(FILE_PATH_LITERAL("athena_resources.pak"));
- ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
- }
-
- DISALLOW_COPY_AND_ASSIGN(AthenaMainDelegate);
-};
int main(int argc, const char** argv) {
- AthenaMainDelegate delegate;
+ athena::AthenaMainDelegate delegate;
content::ContentMainParams params(&delegate);
params.argc = argc;
diff --git a/athena/main/athena_main.gyp b/athena/main/athena_main.gyp
index c829ad6db4..a14df3701f 100644
--- a/athena/main/athena_main.gyp
+++ b/athena/main/athena_main.gyp
@@ -39,6 +39,8 @@
'athena_frame_view.cc',
'athena_frame_view.h',
'athena_launcher.cc',
+ 'athena_main_delegate.cc',
+ 'athena_main_delegate.h',
'athena_renderer_pdf_helper.cc',
'athena_renderer_pdf_helper.h',
'athena_views_delegate.cc',
diff --git a/athena/main/athena_main_delegate.cc b/athena/main/athena_main_delegate.cc
new file mode 100644
index 0000000000..59c6c42dbd
--- /dev/null
+++ b/athena/main/athena_main_delegate.cc
@@ -0,0 +1,175 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/main/athena_main_delegate.h"
+
+#include "athena/content/public/web_contents_view_delegate_creator.h"
+#include "athena/env/public/athena_env.h"
+#include "athena/main/athena_content_client.h"
+#include "athena/main/athena_renderer_pdf_helper.h"
+#include "athena/main/public/athena_launcher.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "components/pdf/renderer/ppb_pdf_impl.h"
+#include "content/public/app/content_main.h"
+#include "content/public/browser/browser_thread.h"
+#include "extensions/shell/browser/desktop_controller.h"
+#include "extensions/shell/browser/shell_browser_main_delegate.h"
+#include "extensions/shell/browser/shell_content_browser_client.h"
+#include "extensions/shell/browser/shell_extension_system.h"
+#include "extensions/shell/common/shell_content_client.h"
+#include "extensions/shell/common/switches.h"
+#include "extensions/shell/renderer/shell_content_renderer_client.h"
+#include "ppapi/c/private/ppb_pdf.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace athena {
+namespace {
+
+// We want to load the sample calculator app by default, for a while. Expecting
+// to run athena_main at src/
+const char kDefaultAppPath[] =
+ "chrome/common/extensions/docs/examples/apps/calculator/app";
+
+class AthenaDesktopController : public extensions::DesktopController {
+ public:
+ AthenaDesktopController() {}
+ ~AthenaDesktopController() override {}
+
+ private:
+ // extensions::DesktopController:
+ virtual aura::WindowTreeHost* GetHost() override {
+ return athena::AthenaEnv::Get()->GetHost();
+ }
+
+ // Creates a new app window and adds it to the desktop. The desktop maintains
+ // ownership of the window.
+ // TODO(jamescook|oshima): Is this function needed?
+ virtual extensions::AppWindow* CreateAppWindow(
+ content::BrowserContext* context,
+ const extensions::Extension* extension) override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ // Adds the window to the desktop.
+ virtual void AddAppWindow(aura::Window* window) override { NOTIMPLEMENTED(); }
+
+ virtual void RemoveAppWindow(extensions::AppWindow* window) override {}
+
+ // Closes and destroys the app windows.
+ virtual void CloseAppWindows() override {}
+
+ DISALLOW_COPY_AND_ASSIGN(AthenaDesktopController);
+};
+
+class AthenaBrowserMainDelegate : public extensions::ShellBrowserMainDelegate {
+ public:
+ AthenaBrowserMainDelegate() {}
+ ~AthenaBrowserMainDelegate() override {}
+
+ // extensions::ShellBrowserMainDelegate:
+ virtual void Start(content::BrowserContext* context) override {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+
+ base::FilePath app_dir = base::FilePath::FromUTF8Unsafe(
+ command_line->HasSwitch(extensions::switches::kAppShellAppPath)
+ ? command_line->GetSwitchValueNative(
+ extensions::switches::kAppShellAppPath)
+ : kDefaultAppPath);
+
+ base::FilePath app_absolute_dir = base::MakeAbsoluteFilePath(app_dir);
+ if (base::DirectoryExists(app_absolute_dir)) {
+ extensions::ShellExtensionSystem* extension_system =
+ static_cast<extensions::ShellExtensionSystem*>(
+ extensions::ExtensionSystem::Get(context));
+ extension_system->LoadApp(app_absolute_dir);
+ }
+
+ athena::StartAthenaEnv(
+ content::BrowserThread::GetBlockingPool()
+ ->GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
+ athena::CreateVirtualKeyboardWithContext(context);
+ athena::StartAthenaSessionWithContext(context);
+ }
+
+ virtual void Shutdown() override {
+ athena::AthenaEnv::Get()->OnTerminating();
+ athena::ShutdownAthena();
+ }
+
+ virtual extensions::DesktopController* CreateDesktopController() override {
+ return new AthenaDesktopController();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AthenaBrowserMainDelegate);
+};
+
+class AthenaContentBrowserClient
+ : public extensions::ShellContentBrowserClient {
+ public:
+ AthenaContentBrowserClient()
+ : extensions::ShellContentBrowserClient(new AthenaBrowserMainDelegate()) {
+ }
+ ~AthenaContentBrowserClient() override {}
+
+ // content::ContentBrowserClient:
+ virtual content::WebContentsViewDelegate* GetWebContentsViewDelegate(
+ content::WebContents* web_contents) override {
+ return athena::CreateWebContentsViewDelegate(web_contents);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AthenaContentBrowserClient);
+};
+
+class AthenaContentRendererClient
+ : public extensions::ShellContentRendererClient {
+ public:
+ AthenaContentRendererClient() {}
+ ~AthenaContentRendererClient() override {}
+
+ // content::ContentRendererClient:
+ virtual void RenderFrameCreated(content::RenderFrame* render_frame) override {
+ new athena::AthenaRendererPDFHelper(render_frame);
+ extensions::ShellContentRendererClient::RenderFrameCreated(render_frame);
+ }
+
+ virtual const void* CreatePPAPIInterface(
+ const std::string& interface_name) override {
+ if (interface_name == PPB_PDF_INTERFACE)
+ return pdf::PPB_PDF_Impl::GetInterface();
+ return extensions::ShellContentRendererClient::CreatePPAPIInterface(
+ interface_name);
+ }
+};
+
+} // namespace
+
+content::ContentClient* AthenaMainDelegate::CreateContentClient() {
+ return new athena::AthenaContentClient();
+}
+
+content::ContentBrowserClient*
+AthenaMainDelegate::CreateShellContentBrowserClient() {
+ return new AthenaContentBrowserClient();
+}
+
+content::ContentRendererClient*
+AthenaMainDelegate::CreateShellContentRendererClient() {
+ return new AthenaContentRendererClient();
+}
+
+void AthenaMainDelegate::InitializeResourceBundle() {
+ base::FilePath pak_dir;
+ PathService::Get(base::DIR_MODULE, &pak_dir);
+ base::FilePath pak_file =
+ pak_dir.Append(FILE_PATH_LITERAL("athena_resources.pak"));
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
+}
+
+} // namespace athena
diff --git a/athena/main/athena_main_delegate.h b/athena/main/athena_main_delegate.h
new file mode 100644
index 0000000000..14ce0812e4
--- /dev/null
+++ b/athena/main/athena_main_delegate.h
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_MAIN_ATHENA_MAIN_DELEGATE_H_
+#define ATHENA_MAIN_ATHENA_MAIN_DELEGATE_H_
+
+#include "extensions/shell/app/shell_main_delegate.h"
+
+namespace athena {
+
+class AthenaMainDelegate : public extensions::ShellMainDelegate {
+ public:
+ AthenaMainDelegate() {}
+ ~AthenaMainDelegate() override {}
+
+ private:
+ // extensions::ShellMainDelegate:
+ content::ContentClient* CreateContentClient() override;
+ content::ContentBrowserClient* CreateShellContentBrowserClient() override;
+ content::ContentRendererClient* CreateShellContentRendererClient() override;
+ void InitializeResourceBundle() override;
+
+ DISALLOW_COPY_AND_ASSIGN(AthenaMainDelegate);
+};
+
+} // namespace
+
+#endif // ATHENA_MAIN_ATHENA_MAIN_DELEGATE_H_
diff --git a/athena/screen/modal_window_controller.cc b/athena/screen/modal_window_controller.cc
index 90357e9ce4..140b2c9aba 100644
--- a/athena/screen/modal_window_controller.cc
+++ b/athena/screen/modal_window_controller.cc
@@ -111,6 +111,12 @@ void ModalWindowController::UpdateDimming(aura::Window* ignore) {
// invisible, but don't delete it until next event execution
// because the call stack may still have and use the pointer.
modal_container_->RemoveObserver(this);
+
+ // Hide the window before removing it, so the focus manager which will run
+ // in RemoveChild handler can know that this container is no longer
+ // available.
+ modal_container_->Hide();
+
modal_container_->parent()->RemoveChild(modal_container_);
base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE, modal_container_);
modal_container_ = nullptr;
diff --git a/athena/screen/screen_manager_impl.cc b/athena/screen/screen_manager_impl.cc
index 471df3b29d..20a4bd5d33 100644
--- a/athena/screen/screen_manager_impl.cc
+++ b/athena/screen/screen_manager_impl.cc
@@ -51,7 +51,7 @@ struct HigherPriorityFinder {
bool BlockEvents(aura::Window* container) {
ScreenManager::ContainerParams* params =
container->GetProperty(kContainerParamsKey);
- return params && params->block_events;
+ return params && params->block_events && container->IsVisible();
}
bool DefaultContainer(aura::Window* container) {
@@ -109,11 +109,47 @@ class AthenaFocusRules : public wm::BaseFocusRules {
return BaseFocusRules::CanActivateWindow(window);
}
+ aura::Window* GetTopmostWindowToActivateInContainer(
+ aura::Window* container,
+ aura::Window* ignore) const {
+ for (aura::Window::Windows::const_reverse_iterator i =
+ container->children().rbegin();
+ i != container->children().rend();
+ ++i) {
+ if (*i != ignore && CanActivateWindow(*i))
+ return *i;
+ }
+ return NULL;
+ }
+
virtual aura::Window* GetNextActivatableWindow(
aura::Window* ignore) const override {
- aura::Window* next = wm::BaseFocusRules::GetNextActivatableWindow(ignore);
- // TODO(oshima): Search from activatable containers if |next| is nullptr.
- // crbug.com/424750.
+ const aura::Window::Windows& containers =
+ ignore->GetRootWindow()->children();
+ auto starting_container_iter = containers.begin();
+ for (auto container_iter = containers.begin();
+ container_iter != containers.end();
+ container_iter++) {
+ if ((*container_iter)->Contains(ignore)) {
+ starting_container_iter = container_iter;
+ break;
+ }
+ }
+
+ // Find next window from the front containers.
+ aura::Window* next = nullptr;
+ for (auto container_iter = starting_container_iter;
+ !next && container_iter != containers.end();
+ container_iter++) {
+ next = GetTopmostWindowToActivateInContainer(*container_iter, ignore);
+ }
+
+ // Find next window from the back containers.
+ auto container_iter = starting_container_iter;
+ while (!next && container_iter != containers.begin()) {
+ container_iter--;
+ next = GetTopmostWindowToActivateInContainer(*container_iter, ignore);
+ }
return next;
}
diff --git a/athena/screen/screen_manager_unittest.cc b/athena/screen/screen_manager_unittest.cc
index dd634ba44a..15588d34e4 100644
--- a/athena/screen/screen_manager_unittest.cc
+++ b/athena/screen/screen_manager_unittest.cc
@@ -15,7 +15,8 @@
#include "ui/events/test/event_generator.h"
#include "ui/wm/core/window_util.h"
-typedef athena::test::AthenaTestBase ScreenManagerTest;
+using ScreenManagerTest = athena::test::AthenaTestBase;
+using AthenaFocusRuleTest = athena::test::AthenaTestBase;
namespace athena {
namespace {
@@ -163,6 +164,91 @@ TEST_F(ScreenManagerTest, DefaultContainer) {
parent->AddChild(original_default);
}
+TEST_F(AthenaFocusRuleTest, FocusTravarsalFromSameContainer) {
+ ScreenManager::ContainerParams params("contaier", kTestZOrderPriority);
+ params.can_activate_children = true;
+ scoped_ptr<aura::Window>
+ container(ScreenManager::Get()->CreateContainer(params));
+
+ scoped_ptr<aura::Window> w1(CreateWindow(
+ container.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+ wm::ActivateWindow(w1.get());
+ EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
+
+ scoped_ptr<aura::Window> w2(CreateWindow(
+ container.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+ EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
+
+ container->RemoveChild(w1.get());
+ EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
+}
+
+TEST_F(AthenaFocusRuleTest, FocusTravarsalFromOtherContainer) {
+ ScreenManager::ContainerParams params2("contaier2", kTestZOrderPriority + 1);
+ params2.can_activate_children = true;
+ scoped_ptr<aura::Window>
+ container2(ScreenManager::Get()->CreateContainer(params2));
+ scoped_ptr<aura::Window> w2(CreateWindow(
+ container2.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+ wm::ActivateWindow(w2.get());
+ EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
+
+ ScreenManager::ContainerParams params1("contaier1", kTestZOrderPriority);
+ params1.can_activate_children = true;
+ scoped_ptr<aura::Window>
+ container1(ScreenManager::Get()->CreateContainer(params1));
+ ScreenManager::ContainerParams params3("contaier3", kTestZOrderPriority + 2);
+ params3.can_activate_children = true;
+ scoped_ptr<aura::Window>
+ container3(ScreenManager::Get()->CreateContainer(params3));
+ scoped_ptr<aura::Window> w1(CreateWindow(
+ container1.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+ scoped_ptr<aura::Window> w3(CreateWindow(
+ container3.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+
+ EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
+
+ container2->RemoveChild(w2.get());
+ // Focus moves to a window in the front contaier.
+ EXPECT_TRUE(wm::IsActiveWindow(w3.get()));
+
+ container3->RemoveChild(w3.get());
+ // Focus moves to a window in the back contaier.
+ EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
+}
+
+TEST_F(AthenaFocusRuleTest, FocusTravarsalFromEventBlockedContainer) {
+ ScreenManager::ContainerParams params1("contaier1", kTestZOrderPriority + 1);
+ params1.can_activate_children = true;
+ scoped_ptr<aura::Window>
+ container1(ScreenManager::Get()->CreateContainer(params1));
+
+ ScreenManager::ContainerParams params2("contaier2", kTestZOrderPriority + 2);
+ params2.can_activate_children = true;
+ params2.block_events = true;
+ scoped_ptr<aura::Window>
+ container2(ScreenManager::Get()->CreateContainer(params2));
+
+ scoped_ptr<aura::Window> w1(CreateWindow(
+ container1.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+ scoped_ptr<aura::Window> w2(CreateWindow(
+ container2.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
+
+ wm::ActivateWindow(w2.get());
+ EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
+
+ // Confirm that w1 can't get the focus.
+ wm::ActivateWindow(w1.get());
+ EXPECT_FALSE(wm::IsActiveWindow(w1.get()));
+ EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
+
+ container2->Hide();
+ w2.reset();
+ container2.reset();
+
+ EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
+}
+
namespace {
class ScreenManagerTargeterTest
diff --git a/athena/test/base/DEPS b/athena/test/base/DEPS
new file mode 100644
index 0000000000..abfd99b469
--- /dev/null
+++ b/athena/test/base/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+athena/main",
+ "+content/public",
+ "+extensions/browser",
+ "+extensions/shell",
+]
diff --git a/athena/test/base/athena_browser_test.cc b/athena/test/base/athena_browser_test.cc
new file mode 100644
index 0000000000..1348647e1a
--- /dev/null
+++ b/athena/test/base/athena_browser_test.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/test/base/athena_browser_test.h"
+
+#include "athena/activity/public/activity_manager.h"
+#include "athena/content/public/web_contents_view_delegate_creator.h"
+#include "athena/env/public/athena_env.h"
+#include "athena/main/athena_content_client.h"
+#include "athena/main/athena_renderer_pdf_helper.h"
+#include "athena/main/public/athena_launcher.h"
+#include "athena/test/base/test_util.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
+#include "extensions/shell/browser/shell_content_browser_client.h"
+
+namespace athena {
+namespace test {
+
+AthenaBrowserTest::AthenaBrowserTest() {
+}
+
+AthenaBrowserTest::~AthenaBrowserTest() {
+}
+
+content::BrowserContext* AthenaBrowserTest::GetBrowserContext() {
+ return extensions::ShellContentBrowserClient::Get()->GetBrowserContext();
+}
+
+void AthenaBrowserTest::SetUpCommandLine(base::CommandLine* command_line) {
+ command_line->AppendSwitchASCII(switches::kTestType, "athena");
+ // The NaCl sandbox won't work in our browser tests.
+ command_line->AppendSwitch(switches::kNoSandbox);
+ content::BrowserTestBase::SetUpCommandLine(command_line);
+}
+
+void AthenaBrowserTest::SetUpOnMainThread() {
+ content::BrowserContext* context = GetBrowserContext();
+ athena::StartAthenaEnv(content::BrowserThread::GetBlockingPool()
+ ->GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
+ athena::CreateVirtualKeyboardWithContext(context);
+ athena::StartAthenaSessionWithContext(context);
+
+ // Set the memory pressure to low and turning off undeterministic resource
+ // observer events.
+ test_util::SendTestMemoryPressureEvent(ResourceManager::MEMORY_PRESSURE_LOW);
+}
+
+void AthenaBrowserTest::RunTestOnMainThreadLoop() {
+ base::MessageLoopForUI::current()->RunUntilIdle();
+ SetUpOnMainThread();
+ RunTestOnMainThread();
+ TearDownOnMainThread();
+}
+
+} // namespace test
+} // namespace athena
diff --git a/athena/test/base/athena_browser_test.h b/athena/test/base/athena_browser_test.h
new file mode 100644
index 0000000000..4ed6d21b76
--- /dev/null
+++ b/athena/test/base/athena_browser_test.h
@@ -0,0 +1,45 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_TEST_BASE_ATHENA_BROWSER_TEST_H_
+#define ATHENA_TEST_BASE_ATHENA_BROWSER_TEST_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_base.h"
+
+namespace base {
+class CommandLine;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace athena {
+namespace test {
+
+// Base class for athena browser tests.
+class AthenaBrowserTest : public content::BrowserTestBase {
+ public:
+ AthenaBrowserTest();
+ ~AthenaBrowserTest() override;
+
+ protected:
+ // Returns the browser context used by the test.
+ content::BrowserContext* GetBrowserContext();
+
+ private:
+ // content::BrowserTestBase implementation.
+ void SetUpCommandLine(base::CommandLine* command_line) override;
+ void SetUpOnMainThread() override;
+ void RunTestOnMainThreadLoop() override;
+
+ DISALLOW_COPY_AND_ASSIGN(AthenaBrowserTest);
+};
+
+} // namespace test
+} // namespace athena
+
+#endif // ATHENA_TEST_BASE_ATHENA_BROWSER_TEST_H_
diff --git a/athena/test/base/athena_browser_test_main.cc b/athena/test/base/athena_browser_test_main.cc
new file mode 100644
index 0000000000..a6258fe9f3
--- /dev/null
+++ b/athena/test/base/athena_browser_test_main.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+
+#include "athena/test/base/athena_test_launcher_delegate.h"
+#include "base/sys_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+int main(int argc, char** argv) {
+ int default_jobs = std::max(1, base::SysInfo::NumberOfProcessors() / 2);
+ athena::test::AthenaTestLauncherDelegate launcher_delegate;
+ return content::LaunchTests(&launcher_delegate, default_jobs, argc, argv);
+}
diff --git a/athena/test/base/athena_test_launcher_delegate.cc b/athena/test/base/athena_test_launcher_delegate.cc
new file mode 100644
index 0000000000..0e800c9509
--- /dev/null
+++ b/athena/test/base/athena_test_launcher_delegate.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "athena/test/base/athena_test_launcher_delegate.h"
+
+#include "athena/main/athena_main_delegate.h"
+#include "base/test/test_suite.h"
+
+namespace athena {
+namespace test {
+
+int AthenaTestLauncherDelegate::RunTestSuite(int argc, char** argv) {
+ return base::TestSuite(argc, argv).Run();
+}
+
+bool AthenaTestLauncherDelegate::AdjustChildProcessCommandLine(
+ base::CommandLine* command_line,
+ const base::FilePath& temp_data_dir) {
+ return true;
+}
+
+content::ContentMainDelegate*
+AthenaTestLauncherDelegate::CreateContentMainDelegate() {
+ return new AthenaMainDelegate();
+}
+
+} // namespace test
+} // namespace extensions
diff --git a/athena/test/base/athena_test_launcher_delegate.h b/athena/test/base/athena_test_launcher_delegate.h
new file mode 100644
index 0000000000..c3d621fefa
--- /dev/null
+++ b/athena/test/base/athena_test_launcher_delegate.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ATHENA_TEST_BASE_ATHENA_TEST_LAUNCHER_DELEGATE_H_
+#define ATHENA_TEST_BASE_ATHENA_TEST_LAUNCHER_DELEGATE_H_
+
+#include "content/public/test/test_launcher.h"
+
+namespace athena {
+namespace test {
+
+class AthenaTestLauncherDelegate : public content::TestLauncherDelegate {
+ public:
+ int RunTestSuite(int argc, char** argv) override;
+ bool AdjustChildProcessCommandLine(
+ base::CommandLine* command_line,
+ const base::FilePath& temp_data_dir) override;
+ content::ContentMainDelegate* CreateContentMainDelegate() override;
+};
+
+} // namespace test
+} // namespace athena
+
+#endif // ATHENA_TEST_BASE_ATHENA_TEST_LAUNCHER_DELEGATE_H_
diff --git a/athena/test/chrome/test_util.cc b/athena/test/base/test_util.cc
index c7af61989d..7e88e1070d 100644
--- a/athena/test/chrome/test_util.cc
+++ b/athena/test/base/test_util.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
#include "athena/activity/public/activity.h"
#include "athena/activity/public/activity_factory.h"
#include "athena/resource_manager/public/resource_manager.h"
-#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/notification_types.h"
@@ -38,9 +37,5 @@ void WaitUntilIdle() {
base::MessageLoopForUI::current()->RunUntilIdle();
}
-content::BrowserContext* GetBrowserContext() {
- return ProfileManager::GetActiveUserProfile();
-}
-
} // namespace test_util
} // namespace athena
diff --git a/athena/test/chrome/test_util.h b/athena/test/base/test_util.h
index 067548a315..1b2430f7a9 100644
--- a/athena/test/chrome/test_util.h
+++ b/athena/test/base/test_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef ATHENA_TEST_CHROME_TEST_UTIL_H_
-#define ATHENA_TEST_CHROME_TEST_UTIL_H_
+#ifndef ATHENA_TEST_BASE_TEST_UTIL_H_
+#define ATHENA_TEST_BASE_TEST_UTIL_H_
#include "athena/resource_manager/public/resource_manager.h"
#include "base/strings/string16.h"
@@ -30,12 +30,8 @@ Activity* CreateTestWebActivity(content::BrowserContext* context,
// Wait until the system is idle.
void WaitUntilIdle();
-// Returns a |BrowserContext| which can be used by tests.
-content::BrowserContext* GetBrowserContext();
-
} // namespace test_util
} // namespace athena
-#endif // ATHENA_TEST_CHROME_TEST_UTIL_H_
-
+#endif // ATHENA_TEST_BASE_TEST_UTIL_H_
diff --git a/athena/test/chrome/DEPS b/athena/test/chrome/DEPS
index 3fd16abaa0..76f3b440b4 100644
--- a/athena/test/chrome/DEPS
+++ b/athena/test/chrome/DEPS
@@ -3,6 +3,4 @@ include_rules = [
"+chrome/browser/profiles",
"+chrome/test/base",
"+content/public",
- "+extensions/browser",
]
-
diff --git a/athena/test/chrome/athena_app_browsertest.cc b/athena/test/chrome/athena_app_browser_test.cc
index 5b2ddeb85d..4ade37aa12 100644
--- a/athena/test/chrome/athena_app_browsertest.cc
+++ b/athena/test/chrome/athena_app_browser_test.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "athena/test/chrome/athena_app_browsertest.h"
+#include "athena/test/chrome/athena_app_browser_test.h"
#include "athena/extensions/public/extensions_delegate.h"
#include "athena/test/base/activity_lifetime_tracker.h"
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_utils.h"
@@ -34,7 +35,7 @@ Activity* AthenaAppBrowserTest::CreateTestAppActivity(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
- ExtensionsDelegate::Get(test_util::GetBrowserContext())->LaunchApp(app_id);
+ ExtensionsDelegate::Get(GetBrowserContext())->LaunchApp(app_id);
observer.Wait();
return tracker.GetNewActivityAndReset();
@@ -58,4 +59,8 @@ void AthenaAppBrowserTest::SetUpOnMainThread() {
test_util::SendTestMemoryPressureEvent(ResourceManager::MEMORY_PRESSURE_LOW);
}
+content::BrowserContext* AthenaAppBrowserTest::GetBrowserContext() {
+ return ProfileManager::GetActiveUserProfile();
+}
+
} // namespace athena
diff --git a/athena/test/chrome/athena_app_browsertest.h b/athena/test/chrome/athena_app_browser_test.h
index 8aa9f2771b..87ae3c9b11 100644
--- a/athena/test/chrome/athena_app_browsertest.h
+++ b/athena/test/chrome/athena_app_browser_test.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef ATHENA_TEST_CHROME_ATHENA_APP_BROWSERTEST_H_
-#define ATHENA_TEST_CHROME_ATHENA_APP_BROWSERTEST_H_
+#ifndef ATHENA_TEST_CHROME_ATHENA_APP_BROWSER_TEST_H_
+#define ATHENA_TEST_CHROME_ATHENA_APP_BROWSER_TEST_H_
#include "chrome/browser/apps/app_browsertest_util.h"
@@ -32,6 +32,9 @@ class AthenaAppBrowserTest : public extensions::PlatformAppBrowserTest {
// BrowserTestBase:
void SetUpOnMainThread() override;
+ // Returns the browser context used by the test.
+ content::BrowserContext* GetBrowserContext();
+
private:
// Our created app id - after it got created and installed.
std::string app_id_;
@@ -41,5 +44,4 @@ class AthenaAppBrowserTest : public extensions::PlatformAppBrowserTest {
} // namespace athena
-#endif // ATHENA_TEST_CHROME_ATHENA_APP_BROWSERTEST_H_
-
+#endif // ATHENA_TEST_CHROME_ATHENA_APP_BROWSER_TEST_H_
diff --git a/athena/test/chrome/athena_browsertest.cc b/athena/test/chrome/athena_chrome_browser_test.cc
index c9e8965e7a..c619b0aad9 100644
--- a/athena/test/chrome/athena_browsertest.cc
+++ b/athena/test/chrome/athena_chrome_browser_test.cc
@@ -2,30 +2,36 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "athena/test/chrome/athena_browsertest.h"
+#include "athena/test/chrome/athena_chrome_browser_test.h"
-#include "athena/test/chrome/test_util.h"
+#include "athena/test/base/test_util.h"
#include "base/command_line.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/common/content_switches.h"
namespace athena {
-AthenaBrowserTest::AthenaBrowserTest() {
+AthenaChromeBrowserTest::AthenaChromeBrowserTest() {
}
-AthenaBrowserTest::~AthenaBrowserTest() {
+AthenaChromeBrowserTest::~AthenaChromeBrowserTest() {
}
-void AthenaBrowserTest::SetUpCommandLine(base::CommandLine* command_line) {
+void AthenaChromeBrowserTest::SetUpCommandLine(
+ base::CommandLine* command_line) {
// The NaCl sandbox won't work in our browser tests.
command_line->AppendSwitch(switches::kNoSandbox);
InProcessBrowserTest::SetUpCommandLine(command_line);
}
-void AthenaBrowserTest::SetUpOnMainThread() {
+void AthenaChromeBrowserTest::SetUpOnMainThread() {
// Set the memory pressure to low and turning off undeterministic resource
// observer events.
test_util::SendTestMemoryPressureEvent(ResourceManager::MEMORY_PRESSURE_LOW);
}
+content::BrowserContext* AthenaChromeBrowserTest::GetBrowserContext() {
+ return ProfileManager::GetActiveUserProfile();
+}
+
} // namespace athena
diff --git a/athena/test/chrome/athena_browsertest.h b/athena/test/chrome/athena_chrome_browser_test.h
index 85917e1e51..a16844a1c0 100644
--- a/athena/test/chrome/athena_browsertest.h
+++ b/athena/test/chrome/athena_chrome_browser_test.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef ATHENA_TEST_CHROME_ATHENA_BROWSERTEST_H_
-#define ATHENA_TEST_CHROME_ATHENA_BROWSERTEST_H_
+#ifndef ATHENA_TEST_CHROME_ATHENA_CHROME_BROWSER_TEST_H_
+#define ATHENA_TEST_CHROME_ATHENA_CHROME_BROWSER_TEST_H_
#include "chrome/test/base/in_process_browser_test.h"
@@ -11,27 +11,33 @@ namespace base {
class CommandLine;
}
+namespace content {
+class BrowserContext;
+}
+
namespace athena {
// Base class for athena tests which allows to use WebActivities.
//
// Note: To avoid asynchronous resource manager events, the memory pressure
// callback gets turned off at the beginning to a low memory pressure.
-class AthenaBrowserTest : public InProcessBrowserTest {
+class AthenaChromeBrowserTest : public InProcessBrowserTest {
public:
- AthenaBrowserTest();
- ~AthenaBrowserTest() override;
+ AthenaChromeBrowserTest();
+ ~AthenaChromeBrowserTest() override;
protected:
// BrowserTestBase:
void SetUpCommandLine(base::CommandLine* command_line) override;
void SetUpOnMainThread() override;
+ // Returns the browser context used by the test.
+ content::BrowserContext* GetBrowserContext();
+
private:
- DISALLOW_COPY_AND_ASSIGN(AthenaBrowserTest);
+ DISALLOW_COPY_AND_ASSIGN(AthenaChromeBrowserTest);
};
} // namespace athena
-#endif // ATHENA_TEST_CHROME_ATHENA_BROWSERTEST_H_
-
+#endif // ATHENA_TEST_CHROME_ATHENA_CHROME_BROWSER_TEST_H_