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/android/tab_model/tab_model.h" 6 7 #include "base/logging.h" 8 #include "chrome/browser/browser_process.h" 9 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/search_engines/search_terms_data.h" 12 #include "chrome/browser/sync/glue/synced_window_delegate_android.h" 13 #include "chrome/browser/ui/toolbar/toolbar_model_impl.h" 14 #include "content/public/browser/notification_service.h" 15 16 using content::NotificationService; 17 18 TabModel::TabModel(Profile* profile) 19 : profile_(profile), 20 synced_window_delegate_( 21 new browser_sync::SyncedWindowDelegateAndroid(this)), 22 toolbar_model_(new ToolbarModelImpl(this)) { 23 24 if (profile) { 25 // A normal Profile creates an OTR profile if it does not exist when 26 // GetOffTheRecordProfile() is called, so we guard it with 27 // HasOffTheRecordProfile(). An OTR profile returns itself when you call 28 // GetOffTheRecordProfile(). 29 is_off_the_record_ = (profile->HasOffTheRecordProfile() && 30 profile == profile->GetOffTheRecordProfile()); 31 32 // A profile can be destroyed, for example in the case of closing all 33 // incognito tabs. We therefore must listen for when this happens, and 34 // remove our pointer to the profile accordingly. 35 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 36 content::Source<Profile>(profile_)); 37 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 38 content::NotificationService::AllSources()); 39 } else { 40 is_off_the_record_ = false; 41 } 42 } 43 44 TabModel::TabModel() 45 : profile_(NULL), 46 is_off_the_record_(false), 47 synced_window_delegate_( 48 new browser_sync::SyncedWindowDelegateAndroid(this)) { 49 } 50 51 TabModel::~TabModel() { 52 } 53 54 content::WebContents* TabModel::GetActiveWebContents() const { 55 if (GetTabCount() == 0 || GetActiveIndex() < 0 || 56 GetActiveIndex() > GetTabCount()) 57 return NULL; 58 return GetWebContentsAt(GetActiveIndex()); 59 } 60 61 Profile* TabModel::GetProfile() const { 62 return profile_; 63 } 64 65 bool TabModel::IsOffTheRecord() const { 66 return is_off_the_record_; 67 } 68 69 browser_sync::SyncedWindowDelegate* TabModel::GetSyncedWindowDelegate() const { 70 return synced_window_delegate_.get(); 71 } 72 73 SessionID::id_type TabModel::GetSessionId() const { 74 return session_id_.id(); 75 } 76 77 void TabModel::BroadcastSessionRestoreComplete() { 78 if (profile_) { 79 NotificationService::current()->Notify( 80 chrome::NOTIFICATION_SESSION_RESTORE_COMPLETE, 81 content::Source<Profile>(profile_), 82 NotificationService::NoDetails()); 83 } else { 84 // TODO(nyquist): Uncomment this once downstream Android uses new 85 // constructor that takes a Profile* argument. See crbug.com/159704. 86 // NOTREACHED(); 87 } 88 } 89 90 ToolbarModel* TabModel::GetToolbarModel() { 91 return toolbar_model_.get(); 92 } 93 94 ToolbarModel::SecurityLevel TabModel::GetSecurityLevelForCurrentTab() { 95 return toolbar_model_->GetSecurityLevel(false); 96 } 97 98 string16 TabModel::GetSearchTermsForCurrentTab() { 99 return toolbar_model_->GetText(true); 100 } 101 102 std::string TabModel::GetQueryExtractionParam() { 103 if (!profile_) 104 return std::string(); 105 UIThreadSearchTermsData search_terms_data(profile_); 106 return search_terms_data.InstantExtendedEnabledParam(); 107 } 108 109 string16 TabModel::GetCorpusNameForCurrentTab() { 110 return toolbar_model_->GetCorpusNameForMobile(); 111 } 112 113 void TabModel::Observe( 114 int type, 115 const content::NotificationSource& source, 116 const content::NotificationDetails& details) { 117 switch (type) { 118 case chrome::NOTIFICATION_PROFILE_DESTROYED: 119 // Our profile just got destroyed, so we delete our pointer to it. 120 profile_ = NULL; 121 break; 122 case chrome::NOTIFICATION_PROFILE_CREATED: 123 // Our incognito tab model out lives the profile, so we need to recapture 124 // the pointer if ours was previously deleted. 125 // NOTIFICATION_PROFILE_DESTROYED is not sent for every destruction, so 126 // we overwrite the pointer regardless of whether it's NULL. 127 if (is_off_the_record_) { 128 Profile* profile = content::Source<Profile>(source).ptr(); 129 if (profile && profile->IsOffTheRecord()) 130 profile_ = profile; 131 } 132 break; 133 default: 134 NOTREACHED(); 135 } 136 } 137