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 ShowScreensaver(const GURL & url)34void ShowScreensaver(const GURL& url) { ScreensaverView::ShowScreensaver(url); } 35 CloseScreensaver()36void CloseScreensaver() { ScreensaverView::CloseScreensaver(); } 37 IsScreensaverShown()38bool IsScreensaverShown() { return ScreensaverView::IsScreensaverShown(); } 39 40 // static ShowScreensaver(const GURL & url)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 CloseScreensaver()49void ScreensaverView::CloseScreensaver() { 50 if (g_instance) { 51 g_instance->Close(); 52 g_instance = NULL; 53 } 54 } 55 56 // static IsScreensaverShown()57bool ScreensaverView::IsScreensaverShown() { 58 return g_instance && g_instance->IsScreensaverShowingURL(g_instance->url_); 59 } 60 IsScreensaverShowingURL(const GURL & url)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. GetContentsView()69views::View* ScreensaverView::GetContentsView() { 70 return this; 71 } 72 73 //////////////////////////////////////////////////////////////////////////////// 74 // ScreensaverView, content::WebContentsObserver implementation. RenderProcessGone(base::TerminationStatus status)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. ScreensaverView(const GURL & url)94ScreensaverView::ScreensaverView(const GURL& url) 95 : url_(url), 96 termination_count_(0), 97 screensaver_webview_(NULL), 98 container_window_(NULL) { 99 } 100 ~ScreensaverView()101ScreensaverView::~ScreensaverView() { 102 } 103 Show()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 Close()112void ScreensaverView::Close() { 113 DCHECK(GetWidget()); 114 GetWidget()->Close(); 115 } 116 AddChildWebContents()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 LoadScreensaver()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 ShowWindow()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 GetInstance()157ScreensaverView* ScreensaverView::GetInstance() { 158 return g_instance; 159 } 160 161 } // namespace ash 162