Home | History | Annotate | Download | only in startup
      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 "chrome/browser/ui/startup/session_crashed_infobar_delegate.h"
      6 
      7 #include "chrome/browser/chrome_notification_types.h"
      8 #include "chrome/browser/profiles/profile.h"
      9 #include "chrome/browser/search/search.h"
     10 #include "chrome/browser/sessions/session_restore.h"
     11 #include "chrome/browser/ui/browser.h"
     12 #include "chrome/browser/ui/browser_finder.h"
     13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     14 #include "chrome/common/url_constants.h"
     15 #include "content/public/browser/dom_storage_context.h"
     16 #include "content/public/browser/notification_service.h"
     17 #include "content/public/browser/storage_partition.h"
     18 #include "grit/chromium_strings.h"
     19 #include "grit/generated_resources.h"
     20 #include "grit/theme_resources.h"
     21 #include "ui/base/l10n/l10n_util.h"
     22 
     23 
     24 // static
     25 void SessionCrashedInfoBarDelegate::Create(Browser* browser) {
     26   // Assume that if the user is launching incognito they were previously running
     27   // incognito so that we have nothing to restore from.
     28   // Also, in ChromeBot tests, there might be a race.  This code appears to be
     29   // called during shutdown when there is no active WebContents.
     30   Profile* profile = browser->profile();
     31   content::WebContents* web_contents =
     32       browser->tab_strip_model()->GetActiveWebContents();
     33   if (profile->IsOffTheRecord() || !web_contents)
     34     return;
     35 
     36   InfoBarService* infobar_service =
     37       InfoBarService::FromWebContents(web_contents);
     38   infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
     39       new SessionCrashedInfoBarDelegate(infobar_service, profile)));
     40 }
     41 
     42 SessionCrashedInfoBarDelegate::SessionCrashedInfoBarDelegate(
     43     InfoBarService* infobar_service,
     44     Profile* profile)
     45     : ConfirmInfoBarDelegate(infobar_service),
     46       accepted_(false),
     47       removed_notification_received_(false),
     48       profile_(profile) {
     49   // TODO(pkasting,marja): Once InfoBars own they delegates, this is not needed
     50   // any more. Then we can rely on delegates getting destroyed, and we can
     51   // initiate the session storage scavenging only in the destructor. (Currently,
     52   // info bars are leaked if they get closed while they're in background tabs.)
     53   registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
     54                  content::NotificationService::AllSources());
     55 }
     56 
     57 SessionCrashedInfoBarDelegate::~SessionCrashedInfoBarDelegate() {
     58   // If the info bar wasn't accepted, it was either dismissed or expired. In
     59   // that case, session restore won't happen.
     60   if (!accepted_ && !removed_notification_received_) {
     61     content::BrowserContext::GetDefaultStoragePartition(profile_)->
     62         GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
     63   }
     64 }
     65 
     66 int SessionCrashedInfoBarDelegate::GetIconID() const {
     67   return IDR_INFOBAR_RESTORE_SESSION;
     68 }
     69 
     70 string16 SessionCrashedInfoBarDelegate::GetMessageText() const {
     71   return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE);
     72 }
     73 
     74 int SessionCrashedInfoBarDelegate::GetButtons() const {
     75   return BUTTON_OK;
     76 }
     77 
     78 string16 SessionCrashedInfoBarDelegate::GetButtonLabel(
     79     InfoBarButton button) const {
     80   DCHECK_EQ(BUTTON_OK, button);
     81   return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON);
     82 }
     83 
     84 bool SessionCrashedInfoBarDelegate::Accept() {
     85   uint32 behavior = 0;
     86   Browser* browser =
     87       chrome::FindBrowserWithWebContents(owner()->web_contents());
     88   if (browser->tab_strip_model()->count() == 1) {
     89     const content::WebContents* active_tab =
     90         browser->tab_strip_model()->GetWebContentsAt(0);
     91     if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
     92         chrome::IsInstantNTP(active_tab)) {
     93       // There is only one tab and its the new tab page, make session restore
     94       // clobber it.
     95       behavior = SessionRestore::CLOBBER_CURRENT_TAB;
     96     }
     97   }
     98   SessionRestore::RestoreSession(browser->profile(), browser,
     99                                  browser->host_desktop_type(), behavior,
    100                                  std::vector<GURL>());
    101   accepted_ = true;
    102   return true;
    103 }
    104 
    105 void SessionCrashedInfoBarDelegate::Observe(
    106     int type,
    107     const content::NotificationSource& source,
    108     const content::NotificationDetails& details) {
    109   DCHECK(type == chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED);
    110   if (content::Details<std::pair<InfoBarDelegate*, bool> >(details)->first !=
    111       this)
    112     return;
    113   if (!accepted_) {
    114     content::BrowserContext::GetDefaultStoragePartition(profile_)->
    115         GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
    116     removed_notification_received_ = true;
    117   }
    118 }
    119