Home | History | Annotate | Download | only in screensaver
      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 
     20 using content::BrowserThread;
     21 
     22 namespace {
     23 
     24 ash::ScreensaverView* g_instance = NULL;
     25 
     26 // Do not restart the screensaver again if it has
     27 // terminated kMaxTerminations times already.
     28 const int kMaxTerminations = 3;
     29 
     30 }  // namespace
     31 
     32 namespace ash {
     33 
     34 void ShowScreensaver(const GURL& url) { ScreensaverView::ShowScreensaver(url); }
     35 
     36 void CloseScreensaver() { ScreensaverView::CloseScreensaver(); }
     37 
     38 bool IsScreensaverShown() { return ScreensaverView::IsScreensaverShown(); }
     39 
     40 // static
     41 void ScreensaverView::ShowScreensaver(const GURL& url) {
     42   if (!g_instance) {
     43     g_instance = new ScreensaverView(url);
     44     g_instance->Show();
     45   }
     46 }
     47 
     48 // static
     49 void ScreensaverView::CloseScreensaver() {
     50   if (g_instance) {
     51     g_instance->Close();
     52     g_instance = NULL;
     53   }
     54 }
     55 
     56 // static
     57 bool ScreensaverView::IsScreensaverShown() {
     58   return g_instance && g_instance->IsScreensaverShowingURL(g_instance->url_);
     59 }
     60 
     61 bool 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.
     69 views::View* ScreensaverView::GetContentsView() {
     70   return this;
     71 }
     72 
     73 ////////////////////////////////////////////////////////////////////////////////
     74 // ScreensaverView, content::WebContentsObserver implementation.
     75 void 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.
     94 ScreensaverView::ScreensaverView(const GURL& url)
     95     : url_(url),
     96       termination_count_(0),
     97       screensaver_webview_(NULL),
     98       container_window_(NULL) {
     99 }
    100 
    101 ScreensaverView::~ScreensaverView() {
    102 }
    103 
    104 void 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 
    112 void ScreensaverView::Close() {
    113   DCHECK(GetWidget());
    114   GetWidget()->Close();
    115 }
    116 
    117 void 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 
    129 void ScreensaverView::LoadScreensaver() {
    130   screensaver_webview_->GetWebContents()->GetController().LoadURL(
    131         url_,
    132         content::Referrer(),
    133         ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
    134         std::string());
    135 }
    136 
    137 void 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
    157 ScreensaverView* ScreensaverView::GetInstance() {
    158   return g_instance;
    159 }
    160 
    161 }  // namespace ash
    162