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/root_window.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::internal::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) {
     35   internal::ScreensaverView::ShowScreensaver(url);
     36 }
     37 
     38 void CloseScreensaver() {
     39   internal::ScreensaverView::CloseScreensaver();
     40 }
     41 
     42 bool IsScreensaverShown() {
     43   return internal::ScreensaverView::IsScreensaverShown();
     44 }
     45 
     46 namespace internal {
     47 
     48 // static
     49 void ScreensaverView::ShowScreensaver(const GURL& url) {
     50   if (!g_instance) {
     51     g_instance = new ScreensaverView(url);
     52     g_instance->Show();
     53   }
     54 }
     55 
     56 // static
     57 void ScreensaverView::CloseScreensaver() {
     58   if (g_instance) {
     59     g_instance->Close();
     60     g_instance = NULL;
     61   }
     62 }
     63 
     64 // static
     65 bool ScreensaverView::IsScreensaverShown() {
     66   return g_instance && g_instance->IsScreensaverShowingURL(g_instance->url_);
     67 }
     68 
     69 bool ScreensaverView::IsScreensaverShowingURL(const GURL& url) {
     70   return screensaver_webview_ &&
     71       screensaver_webview_->web_contents() &&
     72       (screensaver_webview_->web_contents()->GetURL() == url);
     73 }
     74 
     75 ////////////////////////////////////////////////////////////////////////////////
     76 // ScreensaverView, views::WidgetDelegateView implementation.
     77 views::View* ScreensaverView::GetContentsView() {
     78   return this;
     79 }
     80 
     81 ////////////////////////////////////////////////////////////////////////////////
     82 // ScreensaverView, content::WebContentsObserver implementation.
     83 void ScreensaverView::RenderProcessGone(
     84     base::TerminationStatus status) {
     85   LOG(ERROR) << "Screensaver terminated with status " << status;
     86   termination_count_++;
     87 
     88   if (termination_count_ < kMaxTerminations) {
     89     LOG(ERROR) << termination_count_
     90                << " terminations is under the threshold of "
     91                << kMaxTerminations
     92                << "; reloading Screensaver.";
     93     LoadScreensaver();
     94   } else {
     95     LOG(ERROR) << "Exceeded termination threshold, closing Screensaver.";
     96     ScreensaverView::CloseScreensaver();
     97   }
     98 }
     99 
    100 ////////////////////////////////////////////////////////////////////////////////
    101 // ScreensaverView private methods.
    102 ScreensaverView::ScreensaverView(const GURL& url)
    103     : url_(url),
    104       termination_count_(0),
    105       screensaver_webview_(NULL),
    106       container_window_(NULL) {
    107 }
    108 
    109 ScreensaverView::~ScreensaverView() {
    110 }
    111 
    112 void ScreensaverView::Show() {
    113   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    114   // Add the WebView to our view.
    115   AddChildWebContents();
    116   // Show the window.
    117   ShowWindow();
    118 }
    119 
    120 void ScreensaverView::Close() {
    121   DCHECK(GetWidget());
    122   GetWidget()->Close();
    123 }
    124 
    125 void ScreensaverView::AddChildWebContents() {
    126   content::BrowserContext* context =
    127       Shell::GetInstance()->delegate()->GetActiveBrowserContext();
    128   screensaver_webview_ = new views::WebView(context);
    129   SetLayoutManager(new views::FillLayout);
    130   AddChildView(screensaver_webview_);
    131 
    132   LoadScreensaver();
    133   content::WebContentsObserver::Observe(
    134       screensaver_webview_->GetWebContents());
    135 }
    136 
    137 void ScreensaverView::LoadScreensaver() {
    138   screensaver_webview_->GetWebContents()->GetController().LoadURL(
    139         url_,
    140         content::Referrer(),
    141         content::PAGE_TRANSITION_AUTO_TOPLEVEL,
    142         std::string());
    143 }
    144 
    145 void ScreensaverView::ShowWindow() {
    146   aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
    147   gfx::Rect screen_rect =
    148       Shell::GetScreen()->GetDisplayNearestWindow(root_window).bounds();
    149 
    150   // We want to be the fullscreen topmost child of the root window.
    151   // There should be nothing ever really that should show up on top of us.
    152   container_window_ = new views::Widget();
    153   views::Widget::InitParams params(
    154       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    155   params.delegate = this;
    156   params.parent = root_window;
    157   container_window_->Init(params);
    158 
    159   container_window_->StackAtTop();
    160   container_window_->SetBounds(screen_rect);
    161   container_window_->Show();
    162 }
    163 
    164 // static
    165 ScreensaverView* ScreensaverView::GetInstance() {
    166   return g_instance;
    167 }
    168 
    169 }  // namespace internal
    170 }  // namespace ash
    171