| // 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 "content/public/browser/web_contents.h" |
| #include "ui/aura/window_event_dispatcher.h" |
| #include "ui/gfx/screen.h" |
| #include "ui/views/controls/webview/webview.h" |
| #include "ui/views/layout/fill_layout.h" |
| #include "ui/views/widget/widget.h" |
| |
| using content::BrowserThread; |
| |
| namespace { |
| |
| ash::ScreensaverView* g_instance = NULL; |
| |
| // Do not restart the screensaver again if it has |
| // terminated kMaxTerminations times already. |
| const int kMaxTerminations = 3; |
| |
| } // namespace |
| |
| namespace ash { |
| |
| void ShowScreensaver(const GURL& url) { ScreensaverView::ShowScreensaver(url); } |
| |
| void CloseScreensaver() { ScreensaverView::CloseScreensaver(); } |
| |
| bool IsScreensaverShown() { return ScreensaverView::IsScreensaverShown(); } |
| |
| // 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; |
| } |
| } |
| |
| // static |
| bool ScreensaverView::IsScreensaverShown() { |
| return g_instance && g_instance->IsScreensaverShowingURL(g_instance->url_); |
| } |
| |
| bool ScreensaverView::IsScreensaverShowingURL(const GURL& url) { |
| return screensaver_webview_ && |
| screensaver_webview_->web_contents() && |
| (screensaver_webview_->web_contents()->GetURL() == url); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // ScreensaverView, views::WidgetDelegateView implementation. |
| views::View* ScreensaverView::GetContentsView() { |
| return this; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // ScreensaverView, content::WebContentsObserver implementation. |
| void ScreensaverView::RenderProcessGone( |
| base::TerminationStatus status) { |
| LOG(ERROR) << "Screensaver terminated with status " << status; |
| termination_count_++; |
| |
| if (termination_count_ < kMaxTerminations) { |
| LOG(ERROR) << termination_count_ |
| << " terminations is under the threshold of " |
| << kMaxTerminations |
| << "; reloading Screensaver."; |
| LoadScreensaver(); |
| } else { |
| LOG(ERROR) << "Exceeded termination threshold, closing Screensaver."; |
| ScreensaverView::CloseScreensaver(); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // ScreensaverView private methods. |
| ScreensaverView::ScreensaverView(const GURL& url) |
| : url_(url), |
| termination_count_(0), |
| 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()->GetActiveBrowserContext(); |
| 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_AUTO_TOPLEVEL, |
| std::string()); |
| } |
| |
| void ScreensaverView::ShowWindow() { |
| aura::Window* root_window = ash::Shell::GetPrimaryRootWindow(); |
| gfx::Rect screen_rect = |
| Shell::GetScreen()->GetDisplayNearestWindow(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 ash |