1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ash/screensaver/screensaver_view.h" 6 7#include "ash/shell.h" 8#include "ash/shell_delegate.h" 9#include "base/bind.h" 10#include "base/logging.h" 11#include "content/public/browser/browser_context.h" 12#include "content/public/browser/browser_thread.h" 13#include "content/public/browser/web_contents.h" 14#include "ui/aura/window_event_dispatcher.h" 15#include "ui/gfx/screen.h" 16#include "ui/views/controls/webview/webview.h" 17#include "ui/views/layout/fill_layout.h" 18#include "ui/views/widget/widget.h" 19 20using content::BrowserThread; 21 22namespace { 23 24ash::ScreensaverView* g_instance = NULL; 25 26// Do not restart the screensaver again if it has 27// terminated kMaxTerminations times already. 28const int kMaxTerminations = 3; 29 30} // namespace 31 32namespace ash { 33 34void ShowScreensaver(const GURL& url) { ScreensaverView::ShowScreensaver(url); } 35 36void CloseScreensaver() { ScreensaverView::CloseScreensaver(); } 37 38bool IsScreensaverShown() { return ScreensaverView::IsScreensaverShown(); } 39 40// static 41void ScreensaverView::ShowScreensaver(const GURL& url) { 42 if (!g_instance) { 43 g_instance = new ScreensaverView(url); 44 g_instance->Show(); 45 } 46} 47 48// static 49void ScreensaverView::CloseScreensaver() { 50 if (g_instance) { 51 g_instance->Close(); 52 g_instance = NULL; 53 } 54} 55 56// static 57bool ScreensaverView::IsScreensaverShown() { 58 return g_instance && g_instance->IsScreensaverShowingURL(g_instance->url_); 59} 60 61bool ScreensaverView::IsScreensaverShowingURL(const GURL& url) { 62 return screensaver_webview_ && 63 screensaver_webview_->web_contents() && 64 (screensaver_webview_->web_contents()->GetURL() == url); 65} 66 67//////////////////////////////////////////////////////////////////////////////// 68// ScreensaverView, views::WidgetDelegateView implementation. 69views::View* ScreensaverView::GetContentsView() { 70 return this; 71} 72 73//////////////////////////////////////////////////////////////////////////////// 74// ScreensaverView, content::WebContentsObserver implementation. 75void ScreensaverView::RenderProcessGone( 76 base::TerminationStatus status) { 77 LOG(ERROR) << "Screensaver terminated with status " << status; 78 termination_count_++; 79 80 if (termination_count_ < kMaxTerminations) { 81 LOG(ERROR) << termination_count_ 82 << " terminations is under the threshold of " 83 << kMaxTerminations 84 << "; reloading Screensaver."; 85 LoadScreensaver(); 86 } else { 87 LOG(ERROR) << "Exceeded termination threshold, closing Screensaver."; 88 ScreensaverView::CloseScreensaver(); 89 } 90} 91 92//////////////////////////////////////////////////////////////////////////////// 93// ScreensaverView private methods. 94ScreensaverView::ScreensaverView(const GURL& url) 95 : url_(url), 96 termination_count_(0), 97 screensaver_webview_(NULL), 98 container_window_(NULL) { 99} 100 101ScreensaverView::~ScreensaverView() { 102} 103 104void ScreensaverView::Show() { 105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 106 // Add the WebView to our view. 107 AddChildWebContents(); 108 // Show the window. 109 ShowWindow(); 110} 111 112void ScreensaverView::Close() { 113 DCHECK(GetWidget()); 114 GetWidget()->Close(); 115} 116 117void ScreensaverView::AddChildWebContents() { 118 content::BrowserContext* context = 119 Shell::GetInstance()->delegate()->GetActiveBrowserContext(); 120 screensaver_webview_ = new views::WebView(context); 121 SetLayoutManager(new views::FillLayout); 122 AddChildView(screensaver_webview_); 123 124 LoadScreensaver(); 125 content::WebContentsObserver::Observe( 126 screensaver_webview_->GetWebContents()); 127} 128 129void ScreensaverView::LoadScreensaver() { 130 screensaver_webview_->GetWebContents()->GetController().LoadURL( 131 url_, 132 content::Referrer(), 133 content::PAGE_TRANSITION_AUTO_TOPLEVEL, 134 std::string()); 135} 136 137void ScreensaverView::ShowWindow() { 138 aura::Window* root_window = ash::Shell::GetPrimaryRootWindow(); 139 gfx::Rect screen_rect = 140 Shell::GetScreen()->GetDisplayNearestWindow(root_window).bounds(); 141 142 // We want to be the fullscreen topmost child of the root window. 143 // There should be nothing ever really that should show up on top of us. 144 container_window_ = new views::Widget(); 145 views::Widget::InitParams params( 146 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 147 params.delegate = this; 148 params.parent = root_window; 149 container_window_->Init(params); 150 151 container_window_->StackAtTop(); 152 container_window_->SetBounds(screen_rect); 153 container_window_->Show(); 154} 155 156// static 157ScreensaverView* ScreensaverView::GetInstance() { 158 return g_instance; 159} 160 161} // namespace ash 162