OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/ui/search/instant_controller.h" | 5 #include "chrome/browser/ui/search/instant_controller.h" |
6 | 6 |
7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 } | 705 } |
706 | 706 |
707 void InstantController::OmniboxNavigateToURL() { | 707 void InstantController::OmniboxNavigateToURL() { |
708 if (!extended_enabled_) | 708 if (!extended_enabled_) |
709 return; | 709 return; |
710 RecordNavigationHistogram(UsingLocalPage(), false); | 710 RecordNavigationHistogram(UsingLocalPage(), false); |
711 if (instant_tab_) | 711 if (instant_tab_) |
712 instant_tab_->Submit(string16()); | 712 instant_tab_->Submit(string16()); |
713 } | 713 } |
714 | 714 |
| 715 void InstantController::InstantPageLoadFailed(content::WebContents* contents) { |
| 716 if (!chrome::ShouldPreferRemoteNTPOnStartup() || !extended_enabled_) { |
| 717 // We only need to fall back on errors if we're showing the online page |
| 718 // at startup, as otherwise we fall back correctly when trying to show |
| 719 // a page that hasn't yet indicated that it supports the InstantExtended |
| 720 // API. |
| 721 return; |
| 722 } |
| 723 |
| 724 if (IsContentsFrom(instant_tab(), contents)) { |
| 725 // Verify we're not already on a local page and that the URL precisely |
| 726 // equals the instant_url (minus the query params, as those will be filled |
| 727 // in by template values). This check is necessary to make sure we don't |
| 728 // inadvertently redirect to the local NTP if someone, say, reloads a SRP |
| 729 // while offline, as a committed results page still counts as an instant |
| 730 // url. We also check to make sure there's no forward history, as if |
| 731 // someone hits the back button a lot when offline and returns to a NTP |
| 732 // we don't want to redirect and nuke their forward history stack. |
| 733 const GURL& current_url = contents->GetURL(); |
| 734 if (instant_tab_->IsLocal() || |
| 735 !chrome::MatchesOriginAndPath(GURL(GetInstantURL()), current_url) || |
| 736 !current_url.ref().empty() || |
| 737 contents->GetController().CanGoForward()) |
| 738 return; |
| 739 LOG_INSTANT_DEBUG_EVENT(this, "InstantPageLoadFailed: instant_tab"); |
| 740 RedirectToLocalNTP(contents); |
| 741 } else if (IsContentsFrom(ntp(), contents)) { |
| 742 LOG_INSTANT_DEBUG_EVENT(this, "InstantPageLoadFailed: ntp"); |
| 743 bool is_local = ntp_->IsLocal(); |
| 744 DeletePageSoon(ntp_.Pass()); |
| 745 if (!is_local) |
| 746 ResetNTP(GetLocalInstantURL()); |
| 747 } else if (IsContentsFrom(overlay(), contents)) { |
| 748 LOG_INSTANT_DEBUG_EVENT(this, "InstantPageLoadFailed: overlay"); |
| 749 bool is_local = overlay_->IsLocal(); |
| 750 DeletePageSoon(overlay_.Pass()); |
| 751 if (!is_local) |
| 752 ResetOverlay(GetLocalInstantURL()); |
| 753 } |
| 754 } |
| 755 |
715 content::WebContents* InstantController::GetOverlayContents() const { | 756 content::WebContents* InstantController::GetOverlayContents() const { |
716 return overlay_ ? overlay_->contents() : NULL; | 757 return overlay_ ? overlay_->contents() : NULL; |
717 } | 758 } |
718 | 759 |
719 bool InstantController::IsOverlayingSearchResults() const { | 760 bool InstantController::IsOverlayingSearchResults() const { |
720 return model_.mode().is_search_suggestions() && IsFullHeight(model_) && | 761 return model_.mode().is_search_suggestions() && IsFullHeight(model_) && |
721 (last_match_was_search_ || | 762 (last_match_was_search_ || |
722 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); | 763 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); |
723 } | 764 } |
724 | 765 |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 bool supports_instant) { | 1170 bool supports_instant) { |
1130 if (IsContentsFrom(instant_tab(), contents)) { | 1171 if (IsContentsFrom(instant_tab(), contents)) { |
1131 if (!supports_instant) | 1172 if (!supports_instant) |
1132 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); | 1173 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); |
1133 | 1174 |
1134 content::NotificationService::current()->Notify( | 1175 content::NotificationService::current()->Notify( |
1135 chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED, | 1176 chrome::NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED, |
1136 content::Source<InstantController>(this), | 1177 content::Source<InstantController>(this), |
1137 content::NotificationService::NoDetails()); | 1178 content::NotificationService::NoDetails()); |
1138 } else if (IsContentsFrom(ntp(), contents)) { | 1179 } else if (IsContentsFrom(ntp(), contents)) { |
1139 if (!supports_instant) | 1180 if (!supports_instant) { |
| 1181 bool is_local = ntp_->IsLocal(); |
1140 DeletePageSoon(ntp_.Pass()); | 1182 DeletePageSoon(ntp_.Pass()); |
| 1183 // Preload a local NTP in place of the broken online one. |
| 1184 if (!is_local) |
| 1185 ResetNTP(GetLocalInstantURL()); |
| 1186 } |
1141 | 1187 |
1142 content::NotificationService::current()->Notify( | 1188 content::NotificationService::current()->Notify( |
1143 chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED, | 1189 chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED, |
1144 content::Source<InstantController>(this), | 1190 content::Source<InstantController>(this), |
1145 content::NotificationService::NoDetails()); | 1191 content::NotificationService::NoDetails()); |
1146 | 1192 |
1147 } else if (IsContentsFrom(overlay(), contents)) { | 1193 } else if (IsContentsFrom(overlay(), contents)) { |
1148 if (!supports_instant) { | 1194 if (!supports_instant) { |
1149 HideInternal(); | 1195 HideInternal(); |
| 1196 bool is_local = overlay_->IsLocal(); |
1150 DeletePageSoon(overlay_.Pass()); | 1197 DeletePageSoon(overlay_.Pass()); |
| 1198 // Preload a local overlay in place of the broken online one. |
| 1199 if (!is_local && extended_enabled_) |
| 1200 ResetOverlay(GetLocalInstantURL()); |
1151 } | 1201 } |
1152 | 1202 |
1153 content::NotificationService::current()->Notify( | 1203 content::NotificationService::current()->Notify( |
1154 chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED, | 1204 chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED, |
1155 content::Source<InstantController>(this), | 1205 content::Source<InstantController>(this), |
1156 content::NotificationService::NoDetails()); | 1206 content::NotificationService::NoDetails()); |
1157 } | 1207 } |
1158 } | 1208 } |
1159 | 1209 |
1160 void InstantController::InstantPageRenderViewGone( | 1210 void InstantController::InstantPageRenderViewGone( |
1161 const content::WebContents* contents) { | 1211 const content::WebContents* contents) { |
1162 if (IsContentsFrom(overlay(), contents)) { | 1212 if (IsContentsFrom(overlay(), contents)) { |
1163 HideInternal(); | 1213 HideInternal(); |
1164 DeletePageSoon(overlay_.Pass()); | 1214 DeletePageSoon(overlay_.Pass()); |
1165 } else if (IsContentsFrom(ntp(), contents)) { | 1215 } else if (IsContentsFrom(ntp(), contents)) { |
1166 DeletePageSoon(ntp_.Pass()); | 1216 DeletePageSoon(ntp_.Pass()); |
1167 } else { | 1217 } else { |
1168 NOTREACHED(); | 1218 NOTREACHED(); |
1169 } | 1219 } |
1170 } | 1220 } |
1171 | 1221 |
1172 void InstantController::InstantPageAboutToNavigateMainFrame( | 1222 void InstantController::InstantPageAboutToNavigateMainFrame( |
1173 const content::WebContents* contents, | 1223 const content::WebContents* contents, |
1174 const GURL& url) { | 1224 const GURL& url) { |
1175 DCHECK(IsContentsFrom(overlay(), contents)); | 1225 if (IsContentsFrom(overlay(), contents)) { |
| 1226 // If the page does not yet support Instant, we allow redirects and other |
| 1227 // navigations to go through since the Instant URL can redirect - e.g. to |
| 1228 // country specific pages. |
| 1229 if (!overlay_->supports_instant()) |
| 1230 return; |
1176 | 1231 |
1177 // If the page does not yet support Instant, we allow redirects and other | 1232 GURL instant_url(overlay_->instant_url()); |
1178 // navigations to go through since the Instant URL can redirect - e.g. to | |
1179 // country specific pages. | |
1180 if (!overlay_->supports_instant()) | |
1181 return; | |
1182 | 1233 |
1183 GURL instant_url(overlay_->instant_url()); | 1234 // If we are navigating to the Instant URL, do nothing. |
| 1235 if (url == instant_url) |
| 1236 return; |
1184 | 1237 |
1185 // If we are navigating to the Instant URL, do nothing. | 1238 // Commit the navigation if either: |
1186 if (url == instant_url) | 1239 // - The page is in NTP mode (so it could only navigate on a user click) or |
1187 return; | 1240 // - The page is not in NTP mode and we are navigating to a URL with a |
1188 | 1241 // different host or path than the Instant URL. This enables the instant |
1189 // Commit the navigation if either: | 1242 // page when it is showing search results to change the query parameters |
1190 // - The page is in NTP mode (so it could only navigate on a user click) or | 1243 // and fragments of the URL without it navigating. |
1191 // - The page is not in NTP mode and we are navigating to a URL with a | 1244 if (model_.mode().is_ntp() || |
1192 // different host or path than the Instant URL. This enables the instant | 1245 (url.host() != instant_url.host() || |
1193 // page when it is showing search results to change the query parameters | 1246 url.path() != instant_url.path())) { |
1194 // and fragments of the URL without it navigating. | 1247 CommitIfPossible(INSTANT_COMMIT_NAVIGATED); |
1195 if (model_.mode().is_ntp() || | 1248 } |
1196 (url.host() != instant_url.host() || url.path() != instant_url.path())) { | 1249 } else if (IsContentsFrom(instant_tab(), contents)) { |
1197 CommitIfPossible(INSTANT_COMMIT_NAVIGATED); | 1250 // The Instant tab navigated. Send it the data it needs to display |
| 1251 // properly. |
| 1252 UpdateInfoForInstantTab(); |
| 1253 } else { |
| 1254 NOTREACHED(); |
1198 } | 1255 } |
1199 } | 1256 } |
1200 | 1257 |
1201 void InstantController::SetSuggestions( | 1258 void InstantController::SetSuggestions( |
1202 const content::WebContents* contents, | 1259 const content::WebContents* contents, |
1203 const std::vector<InstantSuggestion>& suggestions) { | 1260 const std::vector<InstantSuggestion>& suggestions) { |
1204 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); | 1261 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); |
1205 | 1262 |
1206 // Ignore if the message is from an unexpected source. | 1263 // Ignore if the message is from an unexpected source. |
1207 if (IsContentsFrom(ntp(), contents)) | 1264 if (IsContentsFrom(ntp(), contents)) |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 | 1502 |
1446 void InstantController::ResetInstantTab() { | 1503 void InstantController::ResetInstantTab() { |
1447 // Do not wire up the InstantTab in Incognito, to prevent it from sending data | 1504 // Do not wire up the InstantTab in Incognito, to prevent it from sending data |
1448 // to the page. | 1505 // to the page. |
1449 if (!search_mode_.is_origin_default() && | 1506 if (!search_mode_.is_origin_default() && |
1450 !browser_->profile()->IsOffTheRecord()) { | 1507 !browser_->profile()->IsOffTheRecord()) { |
1451 content::WebContents* active_tab = browser_->GetActiveWebContents(); | 1508 content::WebContents* active_tab = browser_->GetActiveWebContents(); |
1452 if (!instant_tab_ || active_tab != instant_tab_->contents()) { | 1509 if (!instant_tab_ || active_tab != instant_tab_->contents()) { |
1453 instant_tab_.reset(new InstantTab(this)); | 1510 instant_tab_.reset(new InstantTab(this)); |
1454 instant_tab_->Init(active_tab); | 1511 instant_tab_->Init(active_tab); |
1455 // Update theme info for this tab. | 1512 UpdateInfoForInstantTab(); |
1456 browser_->UpdateThemeInfo(); | |
1457 instant_tab_->SetDisplayInstantResults(instant_enabled_); | |
1458 instant_tab_->SetOmniboxBounds(omnibox_bounds_); | |
1459 instant_tab_->InitializeFonts(); | |
1460 StartListeningToMostVisitedChanges(); | |
1461 instant_tab_->KeyCaptureChanged( | |
1462 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); | |
1463 } | 1513 } |
1464 | 1514 |
1465 // Hide the |overlay_| since we are now using |instant_tab_| instead. | 1515 // Hide the |overlay_| since we are now using |instant_tab_| instead. |
1466 HideOverlay(); | 1516 HideOverlay(); |
1467 } else { | 1517 } else { |
1468 instant_tab_.reset(); | 1518 instant_tab_.reset(); |
1469 } | 1519 } |
1470 } | 1520 } |
1471 | 1521 |
| 1522 void InstantController::UpdateInfoForInstantTab() { |
| 1523 if (instant_tab_) { |
| 1524 browser_->UpdateThemeInfo(); |
| 1525 instant_tab_->SetDisplayInstantResults(instant_enabled_); |
| 1526 instant_tab_->SetOmniboxBounds(omnibox_bounds_); |
| 1527 instant_tab_->InitializeFonts(); |
| 1528 StartListeningToMostVisitedChanges(); |
| 1529 instant_tab_->KeyCaptureChanged( |
| 1530 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); |
| 1531 } |
| 1532 } |
| 1533 |
1472 void InstantController::HideOverlay() { | 1534 void InstantController::HideOverlay() { |
1473 HideInternal(); | 1535 HideInternal(); |
1474 ReloadOverlayIfStale(); | 1536 ReloadOverlayIfStale(); |
1475 } | 1537 } |
1476 | 1538 |
1477 void InstantController::HideInternal() { | 1539 void InstantController::HideInternal() { |
1478 LOG_INSTANT_DEBUG_EVENT(this, "Hide"); | 1540 LOG_INSTANT_DEBUG_EVENT(this, "Hide"); |
1479 | 1541 |
1480 // If GetOverlayContents() returns NULL, either we're already in the desired | 1542 // If GetOverlayContents() returns NULL, either we're already in the desired |
1481 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't | 1543 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1685 } | 1747 } |
1686 } | 1748 } |
1687 | 1749 |
1688 return false; | 1750 return false; |
1689 } | 1751 } |
1690 | 1752 |
1691 bool InstantController::UsingLocalPage() const { | 1753 bool InstantController::UsingLocalPage() const { |
1692 return (instant_tab_ && instant_tab_->IsLocal()) || | 1754 return (instant_tab_ && instant_tab_->IsLocal()) || |
1693 (!instant_tab_ && overlay_ && overlay_->IsLocal()); | 1755 (!instant_tab_ && overlay_ && overlay_->IsLocal()); |
1694 } | 1756 } |
| 1757 |
| 1758 void InstantController::RedirectToLocalNTP(content::WebContents* contents) { |
| 1759 contents->GetController().LoadURL( |
| 1760 chrome::GetLocalInstantURL(browser_->profile()), |
| 1761 content::Referrer(), |
| 1762 content::PAGE_TRANSITION_SERVER_REDIRECT, |
| 1763 std::string()); // No extra headers. |
| 1764 // TODO(dcblack): Remove extraneous history entry caused by 404s. |
| 1765 // Note that the base case of a 204 being returned doesn't push a history |
| 1766 // entry. |
| 1767 } |
OLD | NEW |