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