diff options
Diffstat (limited to 'ash/screensaver')
-rw-r--r-- | ash/screensaver/DEPS | 3 | ||||
-rw-r--r-- | ash/screensaver/screensaver_view.cc | 140 | ||||
-rw-r--r-- | ash/screensaver/screensaver_view.h | 86 | ||||
-rw-r--r-- | ash/screensaver/screensaver_view_unittest.cc | 93 |
4 files changed, 322 insertions, 0 deletions
diff --git a/ash/screensaver/DEPS b/ash/screensaver/DEPS new file mode 100644 index 0000000..1c35d9c --- /dev/null +++ b/ash/screensaver/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+content/public/browser", +] diff --git a/ash/screensaver/screensaver_view.cc b/ash/screensaver/screensaver_view.cc new file mode 100644 index 0000000..858ae9c --- /dev/null +++ b/ash/screensaver/screensaver_view.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2012 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 "ash/screensaver/screensaver_view.h" + +#include "ash/shell.h" +#include "ash/shell_delegate.h" +#include "base/bind.h" +#include "base/logging.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "ui/gfx/screen.h" +#include "ui/aura/root_window.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/widget/widget.h" + +using content::BrowserThread; + +namespace { + +ash::internal::ScreensaverView* g_instance = NULL; + +} // namespace + +namespace ash { + +void ShowScreensaver(const GURL& url) { + internal::ScreensaverView::ShowScreensaver(url); +} + +void CloseScreensaver() { + internal::ScreensaverView::CloseScreensaver(); +} + +namespace internal { + +// static +void ScreensaverView::ShowScreensaver(const GURL& url) { + if (!g_instance) { + g_instance = new ScreensaverView(url); + g_instance->Show(); + } +} + +// static +void ScreensaverView::CloseScreensaver() { + if (g_instance) { + g_instance->Close(); + g_instance = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ScreensaverView, views::WidgetDelegateView implementation. +views::View* ScreensaverView::GetContentsView() { + return this; +} + +//////////////////////////////////////////////////////////////////////////////// +// ScreensaverView, content::WebContentsObserver implementation. +void ScreensaverView::RenderViewGone( + base::TerminationStatus status) { + LOG(ERROR) << "Screensaver terminated with status " << status + << ", reloading."; + // Reload the screensaver url into the webcontents. + LoadScreensaver(); +} + +//////////////////////////////////////////////////////////////////////////////// +// ScreensaverView private methods. +ScreensaverView::ScreensaverView(const GURL& url) + : url_(url), + screensaver_webview_(NULL), + container_window_(NULL) { +} + +ScreensaverView::~ScreensaverView() { +} + +void ScreensaverView::Show() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // Add the WebView to our view. + AddChildWebContents(); + // Show the window. + ShowWindow(); +} + +void ScreensaverView::Close() { + DCHECK(GetWidget()); + GetWidget()->Close(); +} + +void ScreensaverView::AddChildWebContents() { + content::BrowserContext* context = + Shell::GetInstance()->delegate()->GetCurrentBrowserContext(); + screensaver_webview_ = new views::WebView(context); + SetLayoutManager(new views::FillLayout); + AddChildView(screensaver_webview_); + + LoadScreensaver(); + content::WebContentsObserver::Observe( + screensaver_webview_->GetWebContents()); +} + +void ScreensaverView::LoadScreensaver() { + screensaver_webview_->GetWebContents()->GetController().LoadURL( + url_, + content::Referrer(), + content::PAGE_TRANSITION_START_PAGE, + std::string()); +} + +void ScreensaverView::ShowWindow() { + aura::RootWindow* root_window = ash::Shell::GetRootWindow(); + gfx::Rect screen_rect = + gfx::Screen::GetMonitorNearestWindow(root_window).bounds(); + + // We want to be the fullscreen topmost child of the root window. + // There should be nothing ever really that should show up on top of us. + container_window_ = new views::Widget(); + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.delegate = this; + params.parent = root_window; + container_window_->Init(params); + + container_window_->StackAtTop(); + container_window_->SetBounds(screen_rect); + container_window_->Show(); +} + +// static +ScreensaverView* ScreensaverView::GetInstance() { + return g_instance; +} + +} // namespace internal +} // namespace ash diff --git a/ash/screensaver/screensaver_view.h b/ash/screensaver/screensaver_view.h new file mode 100644 index 0000000..0835f9b --- /dev/null +++ b/ash/screensaver/screensaver_view.h @@ -0,0 +1,86 @@ +// Copyright (c) 2012 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 ASH_SCREENSAVER_SCREENSAVER_VIEW_H_ +#define ASH_SCREENSAVER_SCREENSAVER_VIEW_H_ +#pragma once + +#include "base/callback.h" +#include "content/public/browser/web_contents_observer.h" +#include "googleurl/src/gurl.h" +#include "ui/views/widget/widget_delegate.h" + +namespace content { +class BrowserContent; +} + +namespace views { +class WebView; +} + +namespace ash { + +namespace test { +class ScreensaverViewTest; +} + +void ShowScreensaver(const GURL& url); +void CloseScreensaver(); + +typedef + base::Callback<views::WebView*(content::BrowserContext*)> WebViewFactory; + +namespace internal { + +// Shows a URL as a screensaver. The screensaver window is fullscreen, +// always on top of every other window and will reload the URL if the +// renderer crashes for any reason. +class ScreensaverView : public views::WidgetDelegateView, + public content::WebContentsObserver { + public: + static void ShowScreensaver(const GURL& url); + static void CloseScreensaver(); + + private: + friend class test::ScreensaverViewTest; + + explicit ScreensaverView(const GURL& url); + virtual ~ScreensaverView(); + + // views::WidgetDelegate overrides. + virtual views::View* GetContentsView() OVERRIDE; + + // content::WebContentsObserver overrides. + virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE; + + void Show(); + void Close(); + + // Creates and adds web contents to our view. + void AddChildWebContents(); + // Load the screensaver in the WebView's webcontent. If the webcontents + // don't exist, they'll be created by WebView. + void LoadScreensaver(); + // Creates and shows a frameless full screen window containing our view. + void ShowWindow(); + + // For testing purposes. + static ScreensaverView* GetInstance(); + + // URL to show in the screensaver. + GURL url_; + + // Host for the extension that implements this dialog. + views::WebView* screensaver_webview_; + + // Window that holds the screensaver webview. + views::Widget* container_window_; + + DISALLOW_COPY_AND_ASSIGN(ScreensaverView); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_SCREENSAVER_SCREENSAVER_VIEW_H_ diff --git a/ash/screensaver/screensaver_view_unittest.cc b/ash/screensaver/screensaver_view_unittest.cc new file mode 100644 index 0000000..47a19e2 --- /dev/null +++ b/ash/screensaver/screensaver_view_unittest.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2012 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 "ash/screensaver/screensaver_view.h" + +#include "ash/test/ash_test_base.h" +#include "base/bind.h" +#include "content/public/browser/browser_context.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/test/test_views_delegate.h" +#include "ui/views/test/webview_test_helper.h" + +namespace ash { +namespace test { + +class ScreensaverViewTest : public ash::test::AshTestBase { + public: + ScreensaverViewTest() { + url_ = GURL("http://www.google.com"); + views_delegate_.reset(new views::TestViewsDelegate); + webview_test_helper_.reset(new views::WebViewTestHelper(message_loop())); + } + + virtual ~ScreensaverViewTest() {} + + virtual void SetUp() OVERRIDE { + AshTestBase::SetUp(); + RunAllPendingInMessageLoop(); + } + + virtual void TearDown() OVERRIDE { + AshTestBase::TearDown(); + } + + void ExpectOpenScreensaver() { + internal::ScreensaverView* screensaver = + internal::ScreensaverView::GetInstance(); + EXPECT_TRUE(screensaver != NULL); + if (!screensaver) return; + + EXPECT_TRUE(screensaver->screensaver_webview_ != NULL); + if (!screensaver->screensaver_webview_) return; + + EXPECT_TRUE(screensaver->screensaver_webview_->web_contents() != NULL); + if (!screensaver->screensaver_webview_->web_contents()) return; + + EXPECT_EQ(screensaver->screensaver_webview_->web_contents()->GetURL(), + url_); + } + + void ExpectClosedScreensaver() { + EXPECT_TRUE(internal::ScreensaverView::GetInstance() == NULL); + } + + protected: + GURL url_; + + private: + scoped_ptr<views::TestViewsDelegate> views_delegate_; + scoped_ptr<views::WebViewTestHelper> webview_test_helper_; + + DISALLOW_COPY_AND_ASSIGN(ScreensaverViewTest); +}; + +TEST_F(ScreensaverViewTest, ShowScreensaverAndClose) { + ash::ShowScreensaver(url_); + RunAllPendingInMessageLoop(); + ExpectOpenScreensaver(); + + ash::CloseScreensaver(); + ExpectClosedScreensaver(); +} + +TEST_F(ScreensaverViewTest, OutOfOrderMultipleShowAndClose) { + ash::CloseScreensaver(); + ExpectClosedScreensaver(); + + ash::ShowScreensaver(url_); + ExpectOpenScreensaver(); + RunAllPendingInMessageLoop(); + ash::ShowScreensaver(url_); + ExpectOpenScreensaver(); + RunAllPendingInMessageLoop(); + + ash::CloseScreensaver(); + ExpectClosedScreensaver(); + ash::CloseScreensaver(); + ExpectClosedScreensaver(); +} + +} // namespace test +} // namespace ash |