| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/toolbar_model.h" | 5 #include "chrome/browser/toolbar_model.h" |
| 6 | 6 |
| 7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "chrome/browser/browser.h" | 8 #include "chrome/browser/browser.h" |
| 9 #include "chrome/browser/cert_store.h" | 9 #include "chrome/browser/cert_store.h" |
| 10 #include "chrome/browser/pref_service.h" | 10 #include "chrome/browser/pref_service.h" |
| 11 #include "chrome/browser/profile.h" | 11 #include "chrome/browser/profile.h" |
| 12 #include "chrome/browser/ssl/ssl_error_info.h" | 12 #include "chrome/browser/ssl/ssl_error_info.h" |
| 13 #include "chrome/browser/tab_contents/navigation_controller.h" | 13 #include "chrome/browser/tab_contents/navigation_controller.h" |
| 14 #include "chrome/browser/tab_contents/navigation_entry.h" | 14 #include "chrome/browser/tab_contents/navigation_entry.h" |
| 15 #include "chrome/browser/tab_contents/tab_contents.h" | 15 #include "chrome/browser/tab_contents/tab_contents.h" |
| 16 #include "chrome/common/pref_names.h" | 16 #include "chrome/common/pref_names.h" |
| 17 #include "chrome/common/url_constants.h" | 17 #include "chrome/common/url_constants.h" |
| 18 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
| 19 #include "grit/theme_resources.h" |
| 19 #include "net/base/cert_status_flags.h" | 20 #include "net/base/cert_status_flags.h" |
| 20 #include "net/base/net_util.h" | 21 #include "net/base/net_util.h" |
| 21 | 22 |
| 22 ToolbarModel::ToolbarModel(Browser* browser) | 23 ToolbarModel::ToolbarModel(Browser* browser) |
| 23 : browser_(browser), | 24 : browser_(browser), |
| 24 input_in_progress_(false) { | 25 input_in_progress_(false) { |
| 25 } | 26 } |
| 26 | 27 |
| 27 ToolbarModel::~ToolbarModel() { | 28 ToolbarModel::~ToolbarModel() { |
| 28 } | 29 } |
| 29 | 30 |
| 30 // ToolbarModel Implementation. | 31 // ToolbarModel Implementation. |
| 31 std::wstring ToolbarModel::GetText() const { | 32 std::wstring ToolbarModel::GetText() const { |
| 32 GURL url(chrome::kAboutBlankURL); | 33 GURL url(chrome::kAboutBlankURL); |
| 33 std::wstring languages; // Empty if we don't have a |navigation_controller|. | 34 std::wstring languages; // Empty if we don't have a |navigation_controller|. |
| 34 | 35 |
| 35 NavigationController* navigation_controller = GetNavigationController(); | 36 NavigationController* navigation_controller = GetNavigationController(); |
| 36 if (navigation_controller) { | 37 if (navigation_controller) { |
| 37 languages = navigation_controller->profile()->GetPrefs()->GetString( | 38 languages = navigation_controller->profile()->GetPrefs()->GetString( |
| 38 prefs::kAcceptLanguages); | 39 prefs::kAcceptLanguages); |
| 39 NavigationEntry* entry = navigation_controller->GetActiveEntry(); | 40 NavigationEntry* entry = navigation_controller->GetActiveEntry(); |
| 40 // We may not have a navigation entry yet | |
| 41 if (!navigation_controller->tab_contents()->ShouldDisplayURL()) { | 41 if (!navigation_controller->tab_contents()->ShouldDisplayURL()) { |
| 42 // Explicitly hide the URL for this tab. | 42 // Explicitly hide the URL for this tab. |
| 43 url = GURL(); | 43 url = GURL(); |
| 44 } else if (entry) { | 44 } else if (entry) { |
| 45 url = entry->virtual_url(); | 45 url = entry->virtual_url(); |
| 46 } | 46 } |
| 47 } | 47 } |
| 48 return net::FormatUrl(url, languages, true, UnescapeRule::NORMAL, NULL, NULL, | 48 return net::FormatUrl(url, languages, true, UnescapeRule::NORMAL, NULL, NULL, |
| 49 NULL); | 49 NULL); |
| 50 } | 50 } |
| 51 | 51 |
| 52 ToolbarModel::SecurityLevel ToolbarModel::GetSecurityLevel() const { | 52 ToolbarModel::SecurityLevel ToolbarModel::GetSecurityLevel() const { |
| 53 if (input_in_progress_) // When editing, assume no security style. | 53 if (input_in_progress_) // When editing, assume no security style. |
| 54 return ToolbarModel::NORMAL; | 54 return NONE; |
| 55 | 55 |
| 56 NavigationController* navigation_controller = GetNavigationController(); | 56 NavigationController* navigation_controller = GetNavigationController(); |
| 57 if (!navigation_controller) // We might not have a controller on init. | 57 if (!navigation_controller) // We might not have a controller on init. |
| 58 return ToolbarModel::NORMAL; | 58 return NONE; |
| 59 | 59 |
| 60 NavigationEntry* entry = navigation_controller->GetActiveEntry(); | 60 NavigationEntry* entry = navigation_controller->GetActiveEntry(); |
| 61 if (!entry) | 61 if (!entry) |
| 62 return ToolbarModel::NORMAL; | 62 return NONE; |
| 63 | 63 |
| 64 switch (entry->ssl().security_style()) { | 64 const NavigationEntry::SSLStatus& ssl = entry->ssl(); |
| 65 case SECURITY_STYLE_AUTHENTICATED: | 65 switch (ssl.security_style()) { |
| 66 if (entry->ssl().has_mixed_content()) | |
| 67 return ToolbarModel::NORMAL; | |
| 68 return ToolbarModel::SECURE; | |
| 69 case SECURITY_STYLE_AUTHENTICATION_BROKEN: | |
| 70 return ToolbarModel::INSECURE; | |
| 71 case SECURITY_STYLE_UNKNOWN: | 66 case SECURITY_STYLE_UNKNOWN: |
| 72 case SECURITY_STYLE_UNAUTHENTICATED: | 67 case SECURITY_STYLE_UNAUTHENTICATED: |
| 73 return ToolbarModel::NORMAL; | 68 return NONE; |
| 69 |
| 70 case SECURITY_STYLE_AUTHENTICATION_BROKEN: |
| 71 return SECURITY_ERROR; |
| 72 |
| 73 case SECURITY_STYLE_AUTHENTICATED: |
| 74 if (ssl.has_mixed_content()) |
| 75 return SECURITY_WARNING; |
| 76 if ((ssl.cert_status() & net::CERT_STATUS_IS_EV) && |
| 77 CertStore::GetSharedInstance()->RetrieveCert(ssl.cert_id(), NULL)) |
| 78 return EV_SECURE; |
| 79 return SECURE; |
| 80 |
| 74 default: | 81 default: |
| 75 NOTREACHED(); | 82 NOTREACHED(); |
| 76 return ToolbarModel::NORMAL; | 83 return NONE; |
| 77 } | 84 } |
| 78 } | 85 } |
| 79 | 86 |
| 80 ToolbarModel::SecurityLevel ToolbarModel::GetSchemeSecurityLevel() const { | 87 int ToolbarModel::GetSecurityIcon() const { |
| 81 // For now, in sync with the security level. | 88 static int icon_ids[NUM_SECURITY_LEVELS] = { |
| 82 return GetSecurityLevel(); | 89 0, |
| 83 } | 90 IDR_EV_SECURE, |
| 84 | 91 IDR_SECURE, |
| 85 ToolbarModel::Icon ToolbarModel::GetIcon() const { | 92 IDR_SECURITY_WARNING, |
| 86 if (input_in_progress_) | 93 IDR_SECURITY_ERROR, |
| 87 return ToolbarModel::NO_ICON; | 94 }; |
| 88 | 95 DCHECK(arraysize(icon_ids) == NUM_SECURITY_LEVELS); |
| 89 NavigationController* navigation_controller = GetNavigationController(); | 96 return icon_ids[GetSecurityLevel()]; |
| 90 if (!navigation_controller) // We might not have a controller on init. | |
| 91 return ToolbarModel::NO_ICON; | |
| 92 | |
| 93 NavigationEntry* entry = navigation_controller->GetActiveEntry(); | |
| 94 if (!entry) | |
| 95 return ToolbarModel::NO_ICON; | |
| 96 | |
| 97 const NavigationEntry::SSLStatus& ssl = entry->ssl(); | |
| 98 switch (ssl.security_style()) { | |
| 99 case SECURITY_STYLE_AUTHENTICATED: | |
| 100 if (ssl.has_mixed_content()) | |
| 101 return ToolbarModel::WARNING_ICON; | |
| 102 return ToolbarModel::LOCK_ICON; | |
| 103 case SECURITY_STYLE_AUTHENTICATION_BROKEN: | |
| 104 return ToolbarModel::WARNING_ICON; | |
| 105 case SECURITY_STYLE_UNKNOWN: | |
| 106 case SECURITY_STYLE_UNAUTHENTICATED: | |
| 107 return ToolbarModel::NO_ICON; | |
| 108 default: | |
| 109 NOTREACHED(); | |
| 110 return ToolbarModel::NO_ICON; | |
| 111 } | |
| 112 } | 97 } |
| 113 | 98 |
| 114 void ToolbarModel::GetIconHoverText(std::wstring* text) const { | 99 void ToolbarModel::GetIconHoverText(std::wstring* text) const { |
| 115 DCHECK(text); | 100 DCHECK(text); |
| 101 text->clear(); |
| 116 | 102 |
| 117 NavigationController* navigation_controller = GetNavigationController(); | 103 switch (GetSecurityLevel()) { |
| 118 // We don't expect to be called during initialization, so the controller | 104 case NONE: |
| 119 // should never be NULL. | 105 // There's no security icon, and thus no hover text. |
| 120 DCHECK(navigation_controller); | 106 return; |
| 121 NavigationEntry* entry = navigation_controller->GetActiveEntry(); | |
| 122 DCHECK(entry); | |
| 123 | 107 |
| 108 case EV_SECURE: |
| 109 case SECURE: { |
| 110 // Note: Navigation controller and active entry are guaranteed non-NULL or |
| 111 // the security level would be NONE. |
| 112 GURL url(GetNavigationController()->GetActiveEntry()->url()); |
| 113 DCHECK(url.has_host()); |
| 114 *text = l10n_util::GetStringF(IDS_SECURE_CONNECTION, |
| 115 UTF8ToWide(url.host())); |
| 116 return; |
| 117 } |
| 124 | 118 |
| 125 const NavigationEntry::SSLStatus& ssl = entry->ssl(); | 119 case SECURITY_WARNING: |
| 126 switch (ssl.security_style()) { | 120 *text = SSLErrorInfo::CreateError(SSLErrorInfo::MIXED_CONTENTS, NULL, |
| 127 case SECURITY_STYLE_AUTHENTICATED: { | 121 GURL()).short_description(); |
| 128 if (ssl.has_mixed_content()) { | 122 return; |
| 129 SSLErrorInfo error_info = SSLErrorInfo::CreateError( | 123 |
| 130 SSLErrorInfo::MIXED_CONTENTS, NULL, GURL()); | 124 case SECURITY_ERROR: |
| 131 text->assign(error_info.short_description()); | 125 // See note above. |
| 132 } else { | 126 CreateErrorText(GetNavigationController()->GetActiveEntry(), text); |
| 133 DCHECK(entry->url().has_host()); | 127 // If the authentication is broken, we should always have at least one |
| 134 text->assign(l10n_util::GetStringF(IDS_SECURE_CONNECTION, | 128 // error. |
| 135 UTF8ToWide(entry->url().host()))); | 129 DCHECK(!text->empty()); |
| 136 } | 130 return; |
| 137 break; | 131 |
| 138 } | |
| 139 case SECURITY_STYLE_AUTHENTICATION_BROKEN: { | |
| 140 CreateErrorText(entry, text); | |
| 141 if (text->empty()) { | |
| 142 // If the authentication is broken, we should always have at least one | |
| 143 // error. | |
| 144 NOTREACHED(); | |
| 145 return; | |
| 146 } | |
| 147 break; | |
| 148 } | |
| 149 default: | 132 default: |
| 150 // Don't show the info bubble in any other cases. | 133 NOTREACHED(); |
| 151 text->clear(); | 134 return; |
| 152 break; | |
| 153 } | 135 } |
| 154 } | 136 } |
| 155 | 137 |
| 156 ToolbarModel::InfoTextType ToolbarModel::GetInfoText( | 138 std::wstring ToolbarModel::GetSecurityInfoText() const { |
| 157 std::wstring* text, | 139 switch (GetSecurityLevel()) { |
| 158 std::wstring* tooltip) const { | 140 case NONE: |
| 159 DCHECK(text && tooltip); | 141 case SECURE: |
| 160 text->clear(); | 142 case SECURITY_WARNING: |
| 161 tooltip->clear(); | 143 return std::wstring(); |
| 162 | 144 |
| 163 if (input_in_progress_) | 145 case EV_SECURE: { |
| 164 return INFO_NO_INFO; | 146 scoped_refptr<net::X509Certificate> cert; |
| 147 // See note in GetIconHoverText(). |
| 148 CertStore::GetSharedInstance()->RetrieveCert( |
| 149 GetNavigationController()->GetActiveEntry()->ssl().cert_id(), |
| 150 &cert); |
| 151 return SSLManager::GetEVCertName(*cert); |
| 152 } |
| 165 | 153 |
| 166 NavigationController* navigation_controller = GetNavigationController(); | 154 case SECURITY_ERROR: |
| 167 if (!navigation_controller) // We might not have a controller on init. | 155 return l10n_util::GetString(IDS_SECURITY_BROKEN); |
| 168 return INFO_NO_INFO; | |
| 169 | 156 |
| 170 NavigationEntry* entry = navigation_controller->GetActiveEntry(); | 157 default: |
| 171 const NavigationEntry::SSLStatus& ssl = entry->ssl(); | 158 NOTREACHED(); |
| 172 if (!entry || ssl.has_mixed_content() || | 159 return std::wstring(); |
| 173 net::IsCertStatusError(ssl.cert_status()) || | |
| 174 ((ssl.cert_status() & net::CERT_STATUS_IS_EV) == 0)) | |
| 175 return INFO_NO_INFO; | |
| 176 | |
| 177 scoped_refptr<net::X509Certificate> cert; | |
| 178 CertStore::GetSharedInstance()->RetrieveCert(ssl.cert_id(), &cert); | |
| 179 if (!cert.get()) { | |
| 180 NOTREACHED(); | |
| 181 return INFO_NO_INFO; | |
| 182 } | 160 } |
| 183 | |
| 184 SSLManager::GetEVCertNames(*cert, text, tooltip); | |
| 185 return INFO_EV_TEXT; | |
| 186 } | 161 } |
| 187 | 162 |
| 188 NavigationController* ToolbarModel::GetNavigationController() const { | 163 NavigationController* ToolbarModel::GetNavigationController() const { |
| 189 // This |current_tab| can be NULL during the initialization of the | 164 // This |current_tab| can be NULL during the initialization of the |
| 190 // toolbar during window creation (i.e. before any tabs have been added | 165 // toolbar during window creation (i.e. before any tabs have been added |
| 191 // to the window). | 166 // to the window). |
| 192 TabContents* current_tab = browser_->GetSelectedTabContents(); | 167 TabContents* current_tab = browser_->GetSelectedTabContents(); |
| 193 return current_tab ? ¤t_tab->controller() : NULL; | 168 return current_tab ? ¤t_tab->controller() : NULL; |
| 194 } | 169 } |
| 195 | 170 |
| 196 void ToolbarModel::CreateErrorText(NavigationEntry* entry, | 171 void ToolbarModel::CreateErrorText(NavigationEntry* entry, |
| 197 std::wstring* text) const { | 172 std::wstring* text) const { |
| 198 const NavigationEntry::SSLStatus& ssl = entry->ssl(); | 173 const NavigationEntry::SSLStatus& ssl = entry->ssl(); |
| 199 std::vector<SSLErrorInfo> errors; | 174 std::vector<SSLErrorInfo> errors; |
| 200 SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id(), | 175 SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id(), ssl.cert_status(), |
| 201 ssl.cert_status(), | 176 entry->url(), &errors); |
| 202 entry->url(), | |
| 203 &errors); | |
| 204 if (ssl.has_mixed_content()) { | 177 if (ssl.has_mixed_content()) { |
| 205 errors.push_back(SSLErrorInfo::CreateError(SSLErrorInfo::MIXED_CONTENTS, | 178 errors.push_back(SSLErrorInfo::CreateError(SSLErrorInfo::MIXED_CONTENTS, |
| 206 NULL, GURL())); | 179 NULL, GURL())); |
| 207 } | 180 } |
| 208 if (ssl.has_unsafe_content()) { | 181 if (ssl.has_unsafe_content()) { |
| 209 errors.push_back(SSLErrorInfo::CreateError(SSLErrorInfo::UNSAFE_CONTENTS, | 182 errors.push_back(SSLErrorInfo::CreateError(SSLErrorInfo::UNSAFE_CONTENTS, |
| 210 NULL, GURL())); | 183 NULL, GURL())); |
| 211 } | 184 } |
| 212 | 185 |
| 213 int error_count = static_cast<int>(errors.size()); | 186 if (errors.empty()) { |
| 214 if (error_count == 0) { | 187 text->clear(); |
| 215 text->assign(L""); | 188 } else if (errors.size() == 1) { |
| 216 } else if (error_count == 1) { | 189 *text = errors[0].short_description(); |
| 217 text->assign(errors[0].short_description()); | |
| 218 } else { | 190 } else { |
| 219 // Multiple errors. | 191 // Multiple errors. |
| 220 text->assign(l10n_util::GetString(IDS_SEVERAL_SSL_ERRORS)); | 192 *text = l10n_util::GetString(IDS_SEVERAL_SSL_ERRORS); |
| 221 text->append(L"\n"); | 193 for (size_t i = 0; i < errors.size(); ++i) { |
| 222 for (int i = 0; i < error_count; ++i) { | 194 text->append(L"\n"); |
| 223 text->append(errors[i].short_description()); | 195 text->append(errors[i].short_description()); |
| 224 if (i != error_count - 1) | |
| 225 text->append(L"\n"); | |
| 226 } | 196 } |
| 227 } | 197 } |
| 228 } | 198 } |
| OLD | NEW |