Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/instant/instant_controller.h" | 5 #include "chrome/browser/instant/instant_controller.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/i18n/case_conversion.h" | 8 #include "base/i18n/case_conversion.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 #include "net/base/escape.h" | 35 #include "net/base/escape.h" |
| 36 #include "unicode/normalizer2.h" | 36 #include "unicode/normalizer2.h" |
| 37 #include "unicode/unistr.h" | 37 #include "unicode/unistr.h" |
| 38 | 38 |
| 39 #if defined(TOOLKIT_VIEWS) | 39 #if defined(TOOLKIT_VIEWS) |
| 40 #include "ui/views/widget/widget.h" | 40 #include "ui/views/widget/widget.h" |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 | 44 |
| 45 // An artificial delay (in milliseconds) we introduce before telling the Instant | 45 // An artificial delay (in milliseconds) we introduce before telling the Instant |
|
samarth
2012/11/16 22:08:26
I suspect this was necessary because the height of
melevin
2012/11/16 22:34:43
We'll have to test once the JavaScript is wired.
| |
| 46 // page about the new omnibox bounds, in cases where the bounds shrink. This is | 46 // page about the new omnibox bounds, in cases where the bounds shrink. This is |
| 47 // to avoid the page jumping up/down very fast in response to bounds changes. | 47 // to avoid the page jumping up/down very fast in response to bounds changes. |
| 48 const int kUpdateBoundsDelayMS = 1000; | 48 const int kUpdateBoundsDelayMS = 1000; |
| 49 | 49 |
| 50 // The maximum number of times we'll load a non-Instant-supporting search engine | 50 // The maximum number of times we'll load a non-Instant-supporting search engine |
| 51 // before we give up and blacklist it for the rest of the browsing session. | 51 // before we give up and blacklist it for the rest of the browsing session. |
| 52 const int kMaxInstantSupportFailures = 10; | 52 const int kMaxInstantSupportFailures = 10; |
| 53 | 53 |
| 54 // If an Instant page has not been used in these many milliseconds, it is | 54 // If an Instant page has not been used in these many milliseconds, it is |
| 55 // reloaded so that the page does not become stale. | 55 // reloaded so that the page does not become stale. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 browser_->SetInstantSuggestion(last_suggestion_); | 252 browser_->SetInstantSuggestion(last_suggestion_); |
| 253 | 253 |
| 254 // Though we may have handled a URL match above, we return false here, so that | 254 // Though we may have handled a URL match above, we return false here, so that |
| 255 // omnibox prerendering can kick in. TODO(sreeram): Remove this (and always | 255 // omnibox prerendering can kick in. TODO(sreeram): Remove this (and always |
| 256 // return true) once we are able to commit URLs as well. | 256 // return true) once we are able to commit URLs as well. |
| 257 return last_match_was_search_; | 257 return last_match_was_search_; |
| 258 } | 258 } |
| 259 | 259 |
| 260 // TODO(tonyg): This method only fires when the omnibox bounds change. It also | 260 // TODO(tonyg): This method only fires when the omnibox bounds change. It also |
| 261 // needs to fire when the preview bounds change (e.g.: open/close info bar). | 261 // needs to fire when the preview bounds change (e.g.: open/close info bar). |
| 262 void InstantController::SetOmniboxBounds(const gfx::Rect& bounds) { | 262 void InstantController::SetPopupBounds(const gfx::Rect& bounds) { |
| 263 if (omnibox_bounds_ == bounds) | 263 if (popup_bounds_ == bounds) |
| 264 return; | 264 return; |
| 265 | 265 |
| 266 omnibox_bounds_ = bounds; | 266 popup_bounds_ = bounds; |
| 267 if (omnibox_bounds_.height() > last_omnibox_bounds_.height()) { | 267 if (popup_bounds_.height() > last_popup_bounds_.height()) { |
| 268 update_bounds_timer_.Stop(); | 268 update_bounds_timer_.Stop(); |
| 269 SendBoundsToPage(); | 269 SendBoundsToPage(); |
| 270 } else if (!update_bounds_timer_.IsRunning()) { | 270 } else if (!update_bounds_timer_.IsRunning()) { |
| 271 update_bounds_timer_.Start(FROM_HERE, | 271 update_bounds_timer_.Start(FROM_HERE, |
| 272 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, | 272 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, |
| 273 &InstantController::SendBoundsToPage); | 273 &InstantController::SendBoundsToPage); |
| 274 } | 274 } |
| 275 } | 275 } |
| 276 | 276 |
| 277 void InstantController::SetMarginSize(int start, int end) { | |
| 278 if ((start_margin_ == start && end_margin_ == end) || | |
| 279 model_.preview_state() == InstantModel::NOT_READY || | |
| 280 !GetPreviewContents() || loader_->IsPointerDownFromActivate()) | |
| 281 return; | |
| 282 | |
| 283 start_margin_ = start; | |
| 284 end_margin_ = end; | |
| 285 loader_->SetMarginSize(start_margin_, end_margin_); | |
| 286 } | |
| 287 | |
| 277 void InstantController::HandleAutocompleteResults( | 288 void InstantController::HandleAutocompleteResults( |
| 278 const std::vector<AutocompleteProvider*>& providers) { | 289 const std::vector<AutocompleteProvider*>& providers) { |
| 279 if (mode_ != EXTENDED || !GetPreviewContents()) | 290 if (mode_ != EXTENDED || !GetPreviewContents()) |
| 280 return; | 291 return; |
| 281 | 292 |
| 282 std::vector<InstantAutocompleteResult> results; | 293 std::vector<InstantAutocompleteResult> results; |
| 283 for (ACProviders::const_iterator provider = providers.begin(); | 294 for (ACProviders::const_iterator provider = providers.begin(); |
| 284 provider != providers.end(); ++provider) { | 295 provider != providers.end(); ++provider) { |
| 285 for (ACMatches::const_iterator match = (*provider)->matches().begin(); | 296 for (ACMatches::const_iterator match = (*provider)->matches().begin(); |
| 286 match != (*provider)->matches().end(); ++match) { | 297 match != (*provider)->matches().end(); ++match) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 // correctly after the commit is done. | 333 // correctly after the commit is done. |
| 323 if (GetPreviewContents()) | 334 if (GetPreviewContents()) |
| 324 model_.SetPreviewState(InstantModel::NOT_READY, 0, INSTANT_SIZE_PERCENT); | 335 model_.SetPreviewState(InstantModel::NOT_READY, 0, INSTANT_SIZE_PERCENT); |
| 325 | 336 |
| 326 if (GetPreviewContents() && !last_full_text_.empty()) { | 337 if (GetPreviewContents() && !last_full_text_.empty()) { |
| 327 // Send a blank query to ask the preview to clear out old results. | 338 // Send a blank query to ask the preview to clear out old results. |
| 328 last_full_text_.clear(); | 339 last_full_text_.clear(); |
| 329 last_user_text_.clear(); | 340 last_user_text_.clear(); |
| 330 loader_->Update(last_full_text_, true); | 341 loader_->Update(last_full_text_, true); |
| 331 } | 342 } |
| 343 | |
| 344 // Clear the margins so they are set when the preview is shown again. | |
|
samarth
2012/11/16 22:08:26
Why is this necessary?
melevin
2012/11/16 22:34:43
When the SearchBox object is created it does not h
samarth
2012/11/19 21:42:44
Take a look at ResetLoader. Whenever we load a new
melevin
2012/11/20 22:32:20
I only see the instant URL being communicated to t
samarth
2012/11/20 22:47:37
I meant something like https://cs.corp.google.com/
| |
| 345 start_margin_ = 0; | |
| 346 end_margin_ = 0; | |
| 332 } | 347 } |
| 333 | 348 |
| 334 bool InstantController::IsCurrent() const { | 349 bool InstantController::IsCurrent() const { |
| 335 return model_.preview_state() == InstantModel::QUERY_RESULTS && | 350 return model_.preview_state() == InstantModel::QUERY_RESULTS && |
| 336 GetPreviewContents() && | 351 GetPreviewContents() && |
| 337 loader_->supports_instant() && last_match_was_search_; | 352 loader_->supports_instant() && last_match_was_search_; |
| 338 } | 353 } |
| 339 | 354 |
| 340 void InstantController::CommitCurrentPreview(InstantCommitType type) { | 355 void InstantController::CommitCurrentPreview(InstantCommitType type) { |
| 341 TabContents* preview = loader_->ReleasePreviewContents(type, last_full_text_); | 356 TabContents* preview = loader_->ReleasePreviewContents(type, last_full_text_); |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 709 if (!stale_loader_timer_.IsRunning()) | 724 if (!stale_loader_timer_.IsRunning()) |
| 710 OnStaleLoader(); | 725 OnStaleLoader(); |
| 711 } | 726 } |
| 712 | 727 |
| 713 void InstantController::DeleteLoader() { | 728 void InstantController::DeleteLoader() { |
| 714 last_full_text_.clear(); | 729 last_full_text_.clear(); |
| 715 last_user_text_.clear(); | 730 last_user_text_.clear(); |
| 716 last_verbatim_ = false; | 731 last_verbatim_ = false; |
| 717 last_suggestion_ = InstantSuggestion(); | 732 last_suggestion_ = InstantSuggestion(); |
| 718 last_match_was_search_ = false; | 733 last_match_was_search_ = false; |
| 719 last_omnibox_bounds_ = gfx::Rect(); | 734 last_popup_bounds_ = gfx::Rect(); |
| 720 url_for_history_ = GURL(); | 735 url_for_history_ = GURL(); |
| 721 if (GetPreviewContents()) | 736 if (GetPreviewContents()) |
| 722 model_.SetPreviewState(InstantModel::NOT_READY, 0, INSTANT_SIZE_PERCENT); | 737 model_.SetPreviewState(InstantModel::NOT_READY, 0, INSTANT_SIZE_PERCENT); |
| 723 | 738 |
| 724 // Schedule the deletion for later, since we may have gotten here from a call | 739 // Schedule the deletion for later, since we may have gotten here from a call |
| 725 // within a |loader_| method (i.e., it's still on the stack). If we deleted | 740 // within a |loader_| method (i.e., it's still on the stack). If we deleted |
| 726 // the loader immediately, things would still be fine so long as the caller | 741 // the loader immediately, things would still be fine so long as the caller |
| 727 // doesn't access any instance members after we return, but why rely on that? | 742 // doesn't access any instance members after we return, but why rely on that? |
| 728 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | 743 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
| 729 } | 744 } |
| 730 | 745 |
| 731 void InstantController::Show(InstantShownReason reason, | 746 void InstantController::Show(InstantShownReason reason, |
| 732 int height, | 747 int height, |
| 733 InstantSizeUnits units) { | 748 InstantSizeUnits units) { |
| 734 // Must be on NTP to show NTP content. | 749 // Must be on NTP to show NTP content. |
| 735 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !active_tab_is_ntp_) | 750 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !active_tab_is_ntp_) |
| 736 return; | 751 return; |
| 737 | 752 |
| 738 // Must have updated omnibox after most recent Hide() to show suggestions. | 753 // Must have updated omnibox after most recent Hide() to show suggestions. |
| 739 if (reason == INSTANT_SHOWN_QUERY_SUGGESTIONS && | 754 if (reason == INSTANT_SHOWN_QUERY_SUGGESTIONS && |
| 740 model_.preview_state() == InstantModel::NOT_READY) | 755 model_.preview_state() == InstantModel::NOT_READY) |
| 741 return; | 756 return; |
| 742 | 757 |
| 743 model_.SetPreviewState(GetNewPreviewState(reason), height, units); | 758 model_.SetPreviewState(GetNewPreviewState(reason), height, units); |
| 744 } | 759 } |
| 745 | 760 |
| 746 void InstantController::SendBoundsToPage() { | 761 void InstantController::SendBoundsToPage() { |
| 747 if (last_omnibox_bounds_ == omnibox_bounds_ || | 762 if (last_popup_bounds_ == popup_bounds_ || |
| 748 model_.preview_state() == InstantModel::NOT_READY || | 763 model_.preview_state() == InstantModel::NOT_READY || |
| 749 !GetPreviewContents() || loader_->IsPointerDownFromActivate()) | 764 !GetPreviewContents() || loader_->IsPointerDownFromActivate()) |
| 750 return; | 765 return; |
| 751 | 766 |
| 752 last_omnibox_bounds_ = omnibox_bounds_; | 767 last_popup_bounds_ = popup_bounds_; |
| 753 gfx::Rect preview_bounds = browser_->GetInstantBounds(); | 768 gfx::Rect preview_bounds = browser_->GetInstantBounds(); |
| 754 gfx::Rect intersection = gfx::IntersectRects(omnibox_bounds_, preview_bounds); | 769 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds); |
| 755 | 770 |
| 756 // Translate into window coordinates. | 771 // Translate into window coordinates. |
| 757 if (!intersection.IsEmpty()) { | 772 if (!intersection.IsEmpty()) { |
| 758 intersection.Offset(-preview_bounds.origin().x(), | 773 intersection.Offset(-preview_bounds.origin().x(), |
| 759 -preview_bounds.origin().y()); | 774 -preview_bounds.origin().y()); |
| 760 } | 775 } |
| 761 | 776 |
| 762 // In the current Chrome UI, these must always be true so they sanity check | 777 // In the current Chrome UI, these must always be true so they sanity check |
| 763 // the above operations. In a future UI, these may be removed or adjusted. | 778 // the above operations. In a future UI, these may be removed or adjusted. |
| 764 // There is no point in sanity-checking |intersection.y()| because the omnibox | 779 // There is no point in sanity-checking |intersection.y()| because the omnibox |
| 765 // can be placed anywhere vertically relative to the preview (for example, in | 780 // can be placed anywhere vertically relative to the preview (for example, in |
| 766 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds). | 781 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds). |
| 767 DCHECK_LE(0, intersection.x()); | 782 DCHECK_LE(0, intersection.x()); |
| 768 DCHECK_LE(0, intersection.width()); | 783 DCHECK_LE(0, intersection.width()); |
| 769 DCHECK_LE(0, intersection.height()); | 784 DCHECK_LE(0, intersection.height()); |
| 770 | 785 |
| 771 loader_->SetOmniboxBounds(intersection); | 786 loader_->SetPopupBounds(intersection); |
| 772 } | 787 } |
| 773 | 788 |
| 774 bool InstantController::GetInstantURL(const TemplateURL* template_url, | 789 bool InstantController::GetInstantURL(const TemplateURL* template_url, |
| 775 const GURL& tab_url, | 790 const GURL& tab_url, |
| 776 std::string* instant_url) const { | 791 std::string* instant_url) const { |
| 777 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 792 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 778 if (command_line->HasSwitch(switches::kInstantURL)) { | 793 if (command_line->HasSwitch(switches::kInstantURL)) { |
| 779 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL); | 794 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL); |
| 780 return template_url != NULL; | 795 return template_url != NULL; |
| 781 } | 796 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 816 } | 831 } |
| 817 | 832 |
| 818 std::map<std::string, int>::const_iterator iter = | 833 std::map<std::string, int>::const_iterator iter = |
| 819 blacklisted_urls_.find(*instant_url); | 834 blacklisted_urls_.find(*instant_url); |
| 820 if (iter != blacklisted_urls_.end() && | 835 if (iter != blacklisted_urls_.end() && |
| 821 iter->second > kMaxInstantSupportFailures) | 836 iter->second > kMaxInstantSupportFailures) |
| 822 return false; | 837 return false; |
| 823 | 838 |
| 824 return true; | 839 return true; |
| 825 } | 840 } |
| OLD | NEW |