Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: chrome/browser/instant/instant_controller.cc

Issue 11824050: InstantExtended: Committed NTP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test failures. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/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/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
11 #include "base/utf_string_conversions.h" 11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/autocomplete/autocomplete_provider.h" 12 #include "chrome/browser/autocomplete/autocomplete_provider.h"
13 #include "chrome/browser/google/google_util.h" 13 #include "chrome/browser/google/google_util.h"
14 #include "chrome/browser/history/history_service.h" 14 #include "chrome/browser/history/history_service.h"
15 #include "chrome/browser/history/history_service_factory.h" 15 #include "chrome/browser/history/history_service_factory.h"
16 #include "chrome/browser/history/history_tab_helper.h" 16 #include "chrome/browser/history/history_tab_helper.h"
17 #include "chrome/browser/instant/instant_loader.h" 17 #include "chrome/browser/instant/instant_ntp.h"
18 #include "chrome/browser/instant/instant_overlay.h"
18 #include "chrome/browser/instant/instant_tab.h" 19 #include "chrome/browser/instant/instant_tab.h"
19 #include "chrome/browser/platform_util.h" 20 #include "chrome/browser/platform_util.h"
20 #include "chrome/browser/search_engines/template_url_service.h" 21 #include "chrome/browser/search_engines/template_url_service.h"
21 #include "chrome/browser/search_engines/template_url_service_factory.h" 22 #include "chrome/browser/search_engines/template_url_service_factory.h"
22 #include "chrome/browser/ui/browser_instant_controller.h" 23 #include "chrome/browser/ui/browser_instant_controller.h"
23 #include "chrome/browser/ui/search/search_tab_helper.h" 24 #include "chrome/browser/ui/search/search_tab_helper.h"
24 #include "chrome/common/chrome_notification_types.h" 25 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/url_constants.h"
26 #include "content/public/browser/navigation_entry.h" 28 #include "content/public/browser/navigation_entry.h"
27 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/render_widget_host_view.h" 30 #include "content/public/browser/render_widget_host_view.h"
29 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
30 #include "net/base/escape.h" 32 #include "net/base/escape.h"
31 #include "third_party/icu/public/common/unicode/normalizer2.h" 33 #include "third_party/icu/public/common/unicode/normalizer2.h"
32 34
33 #if defined(TOOLKIT_VIEWS) 35 #if defined(TOOLKIT_VIEWS)
34 #include "ui/views/widget/widget.h" 36 #include "ui/views/widget/widget.h"
35 #endif 37 #endif
36 38
37 namespace { 39 namespace {
38 40
39 // An artificial delay (in milliseconds) we introduce before telling the Instant 41 // An artificial delay (in milliseconds) we introduce before telling the Instant
40 // page about the new omnibox bounds, in cases where the bounds shrink. This is 42 // page about the new omnibox bounds, in cases where the bounds shrink. This is
41 // to avoid the page jumping up/down very fast in response to bounds changes. 43 // to avoid the page jumping up/down very fast in response to bounds changes.
42 const int kUpdateBoundsDelayMS = 1000; 44 const int kUpdateBoundsDelayMS = 1000;
43 45
44 // The maximum number of times we'll load a non-Instant-supporting search engine 46 // The maximum number of times we'll load a non-Instant-supporting search engine
45 // before we give up and blacklist it for the rest of the browsing session. 47 // before we give up and blacklist it for the rest of the browsing session.
46 const int kMaxInstantSupportFailures = 10; 48 const int kMaxInstantSupportFailures = 10;
47 49
48 // If an Instant page has not been used in these many milliseconds, it is
49 // reloaded so that the page does not become stale.
50 const int kStaleLoaderTimeoutMS = 3 * 3600 * 1000;
51
52 // For reporting events of interest. 50 // For reporting events of interest.
53 enum InstantControllerEvent { 51 enum InstantControllerEvent {
54 INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0, 52 INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0,
55 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST = 1, 53 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST = 1,
56 INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST = 2, 54 INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST = 2,
57 INSTANT_CONTROLLER_EVENT_MAX = 3, 55 INSTANT_CONTROLLER_EVENT_MAX = 3,
58 }; 56 };
59 57
60 void RecordEventHistogram(InstantControllerEvent event) { 58 void RecordEventHistogram(InstantControllerEvent event) {
61 UMA_HISTOGRAM_ENUMERATION("Instant.InstantControllerEvent", 59 UMA_HISTOGRAM_ENUMERATION("Instant.InstantControllerEvent",
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 return true; 151 return true;
154 } 152 }
155 153
156 return false; 154 return false;
157 } 155 }
158 156
159 bool IsFullHeight(const InstantModel& model) { 157 bool IsFullHeight(const InstantModel& model) {
160 return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT; 158 return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT;
161 } 159 }
162 160
161 bool IsContentsFrom(const InstantPage* page,
162 const content::WebContents* contents) {
163 return page && (page->contents() == contents);
164 }
165
163 } // namespace 166 } // namespace
164 167
165 // static 168 // static
166 const char* InstantController::kLocalOmniboxPopupURL = 169 const char* InstantController::kLocalOmniboxPopupURL =
167 "chrome://local-omnibox-popup/local-omnibox-popup.html"; 170 "chrome://local-omnibox-popup/local-omnibox-popup.html";
168 171
169 InstantController::InstantController(chrome::BrowserInstantController* browser, 172 InstantController::InstantController(chrome::BrowserInstantController* browser,
170 bool extended_enabled, 173 bool extended_enabled,
171 bool use_local_preview_only) 174 bool use_local_preview_only)
172 : browser_(browser), 175 : browser_(browser),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 is_keyword_search)); 214 is_keyword_search));
212 215
213 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. 216 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions.
214 // http://crbug.com/153932. Note, this early escape is happens prior to the 217 // http://crbug.com/153932. Note, this early escape is happens prior to the
215 // DCHECKs below because |user_text| and |full_text| have different semantics 218 // DCHECKs below because |user_text| and |full_text| have different semantics
216 // when keyword search is in effect. 219 // when keyword search is in effect.
217 if (is_keyword_search) { 220 if (is_keyword_search) {
218 if (instant_tab_) 221 if (instant_tab_)
219 instant_tab_->Update(string16(), 0, 0, true); 222 instant_tab_->Update(string16(), 0, 0, true);
220 else 223 else
221 HideLoader(); 224 HideOverlay();
222 last_match_was_search_ = false; 225 last_match_was_search_ = false;
223 return false; 226 return false;
224 } 227 }
225 228
226 // If the popup is open, the user has to be typing. 229 // If the popup is open, the user has to be typing.
227 DCHECK(!omnibox_popup_is_open || user_input_in_progress); 230 DCHECK(!omnibox_popup_is_open || user_input_in_progress);
228 231
229 // If the popup is closed, there should be no inline autocompletion. 232 // If the popup is closed, there should be no inline autocompletion.
230 DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text) 233 DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text)
231 << user_text << "|" << full_text; 234 << user_text << "|" << full_text;
232 235
233 // If there's no text in the omnibox, the user can't have typed any. 236 // If there's no text in the omnibox, the user can't have typed any.
234 DCHECK(!full_text.empty() || user_text.empty()) << user_text; 237 DCHECK(!full_text.empty() || user_text.empty()) << user_text;
235 238
236 // If the user isn't typing, and the popup is closed, there can't be any 239 // If the user isn't typing, and the popup is closed, there can't be any
237 // user-typed text. 240 // user-typed text.
238 DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty()) 241 DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty())
239 << user_text; 242 << user_text;
240 243
241 // The preview is being clicked and will commit soon. Don't change anything. 244 // The preview is being clicked and will commit soon. Don't change anything.
242 // TODO(sreeram): Add a browser test for this. 245 // TODO(sreeram): Add a browser test for this.
243 if (loader_ && loader_->is_pointer_down_from_activate()) 246 if (overlay_ && overlay_->is_pointer_down_from_activate())
244 return false; 247 return false;
245 248
246 // In non-extended mode, SearchModeChanged() is never called, so fake it. The 249 // In non-extended mode, SearchModeChanged() is never called, so fake it. The
247 // mode is set to "disallow suggestions" here, so that if one of the early 250 // mode is set to "disallow suggestions" here, so that if one of the early
248 // "return false" conditions is hit, suggestions will be disallowed. If the 251 // "return false" conditions is hit, suggestions will be disallowed. If the
249 // query is sent to the loader, the mode is set to "allow" further below. 252 // query is sent to the overlay, the mode is set to "allow" further below.
250 if (!extended_enabled_) 253 if (!extended_enabled_)
251 search_mode_.mode = chrome::search::Mode::MODE_DEFAULT; 254 search_mode_.mode = chrome::search::Mode::MODE_DEFAULT;
252 255
253 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && 256 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) &&
254 !user_text.empty(); 257 !user_text.empty();
255 258
256 // In non extended mode, Instant is disabled for URLs and keyword mode. 259 // In non extended mode, Instant is disabled for URLs and keyword mode.
257 if (!extended_enabled_ && 260 if (!extended_enabled_ &&
258 (!last_match_was_search_ || 261 (!last_match_was_search_ ||
259 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) { 262 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) {
260 HideLoader(); 263 HideOverlay();
261 return false; 264 return false;
262 } 265 }
263 266
264 // If we have an |instant_tab_| use it, else ensure we have a loader that is 267 // If we have an |instant_tab_| use it, else ensure we have a overlay that is
265 // current or is using local preview. 268 // current or is using local preview.
266 if (!instant_tab_ && !(loader_ && loader_->IsUsingLocalPreview()) && 269 if (!instant_tab_ && !(overlay_ && overlay_->IsUsingLocalPreview()) &&
267 !EnsureLoaderIsCurrent(false)) { 270 !EnsureOverlayIsCurrent(false)) {
268 HideLoader(); 271 HideOverlay();
269 return false; 272 return false;
270 } 273 }
271 274
272 if (extended_enabled_) { 275 if (extended_enabled_) {
273 if (!omnibox_popup_is_open) { 276 if (!omnibox_popup_is_open) {
274 if (!user_input_in_progress) { 277 if (!user_input_in_progress) {
275 // If the user isn't typing and the omnibox popup is closed, it means a 278 // If the user isn't typing and the omnibox popup is closed, it means a
276 // regular navigation, tab-switch or the user hitting Escape. 279 // regular navigation, tab-switch or the user hitting Escape.
277 if (instant_tab_) { 280 if (instant_tab_) {
278 // The user is on a search results page. It may be showing results for 281 // The user is on a search results page. It may be showing results for
279 // a partial query the user typed before they hit Escape. Send the 282 // a partial query the user typed before they hit Escape. Send the
280 // omnibox text to the page to restore the original results. 283 // omnibox text to the page to restore the original results.
281 // 284 //
282 // In a tab switch, |instant_tab_| won't have updated yet, so it may 285 // In a tab switch, |instant_tab_| won't have updated yet, so it may
283 // be pointing to the previous tab (which was a search results page). 286 // be pointing to the previous tab (which was a search results page).
284 // Ensure we don't send the omnibox text to a random webpage (the new 287 // Ensure we don't send the omnibox text to a random webpage (the new
285 // tab), by comparing the old and new WebContents. 288 // tab), by comparing the old and new WebContents.
286 if (escape_pressed && 289 if (escape_pressed &&
287 instant_tab_->contents() == browser_->GetActiveWebContents()) { 290 instant_tab_->contents() == browser_->GetActiveWebContents()) {
288 instant_tab_->Submit(full_text); 291 instant_tab_->Submit(full_text);
289 } 292 }
290 } else if (!full_text.empty()) { 293 } else if (!full_text.empty()) {
291 // If |full_text| is empty, the user is on the NTP. The preview may 294 // If |full_text| is empty, the user is on the NTP. The preview may
292 // be showing custom NTP content; hide only if that's not the case. 295 // be showing custom NTP content; hide only if that's not the case.
293 HideLoader(); 296 HideOverlay();
294 } 297 }
295 } else if (full_text.empty()) { 298 } else if (full_text.empty()) {
296 // The user is typing, and backspaced away all omnibox text. Clear 299 // The user is typing, and backspaced away all omnibox text. Clear
297 // |last_omnibox_text_| so that we don't attempt to set suggestions. 300 // |last_omnibox_text_| so that we don't attempt to set suggestions.
298 last_omnibox_text_.clear(); 301 last_omnibox_text_.clear();
299 last_suggestion_ = InstantSuggestion(); 302 last_suggestion_ = InstantSuggestion();
300 if (instant_tab_) { 303 if (instant_tab_) {
301 // On a search results page, tell it to clear old results. 304 // On a search results page, tell it to clear old results.
302 instant_tab_->Update(string16(), 0, 0, true); 305 instant_tab_->Update(string16(), 0, 0, true);
303 } else if (search_mode_.is_origin_ntp()) { 306 } else if (search_mode_.is_origin_ntp()) {
304 // On the NTP, tell the preview to clear old results. Don't hide the 307 // On the NTP, tell the preview to clear old results. Don't hide the
305 // preview so it can show a blank page or logo if it wants. 308 // preview so it can show a blank page or logo if it wants.
306 loader_->Update(string16(), 0, 0, true); 309 overlay_->Update(string16(), 0, 0, true);
307 } else { 310 } else {
308 HideLoader(); 311 HideOverlay();
309 } 312 }
310 } else { 313 } else {
311 // The user switched to a tab with partial text already in the omnibox. 314 // The user switched to a tab with partial text already in the omnibox.
312 HideLoader(); 315 HideOverlay();
313 316
314 // The new tab may or may not be a search results page; we don't know 317 // The new tab may or may not be a search results page; we don't know
315 // since SearchModeChanged() hasn't been called yet. If it later turns 318 // since SearchModeChanged() hasn't been called yet. If it later turns
316 // out to be, we should store |full_text| now, so that if the user hits 319 // out to be, we should store |full_text| now, so that if the user hits
317 // Enter, we'll send the correct query to instant_tab_->Submit(). If the 320 // Enter, we'll send the correct query to instant_tab_->Submit(). If the
318 // partial text is not a query (|last_match_was_search_| is false), we 321 // partial text is not a query (|last_match_was_search_| is false), we
319 // won't Submit(), so no need to worry about that. 322 // won't Submit(), so no need to worry about that.
320 last_omnibox_text_ = full_text; 323 last_omnibox_text_ = full_text;
321 last_suggestion_ = InstantSuggestion(); 324 last_suggestion_ = InstantSuggestion();
322 } 325 }
323 return false; 326 return false;
324 } else if (full_text.empty()) { 327 } else if (full_text.empty()) {
325 // The user typed a solitary "?". Same as the backspace case above. 328 // The user typed a solitary "?". Same as the backspace case above.
326 last_omnibox_text_.clear(); 329 last_omnibox_text_.clear();
327 last_suggestion_ = InstantSuggestion(); 330 last_suggestion_ = InstantSuggestion();
328 if (instant_tab_) 331 if (instant_tab_)
329 instant_tab_->Update(string16(), 0, 0, true); 332 instant_tab_->Update(string16(), 0, 0, true);
330 else if (search_mode_.is_origin_ntp()) 333 else if (search_mode_.is_origin_ntp())
331 loader_->Update(string16(), 0, 0, true); 334 overlay_->Update(string16(), 0, 0, true);
332 else 335 else
333 HideLoader(); 336 HideOverlay();
334 return false; 337 return false;
335 } 338 }
336 } else if (!omnibox_popup_is_open || full_text.empty()) { 339 } else if (!omnibox_popup_is_open || full_text.empty()) {
337 // In the non-extended case, hide the preview as long as the user isn't 340 // In the non-extended case, hide the preview as long as the user isn't
338 // actively typing a non-empty query. 341 // actively typing a non-empty query.
339 HideLoader(); 342 HideOverlay();
340 return false; 343 return false;
341 } 344 }
342 345
343 last_omnibox_text_has_inline_autocompletion_ = user_text != full_text; 346 last_omnibox_text_has_inline_autocompletion_ = user_text != full_text;
344 347
345 // If the user continues typing the same query as the suggested text is 348 // If the user continues typing the same query as the suggested text is
346 // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER). 349 // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER).
347 bool reused_suggestion = false; 350 bool reused_suggestion = false;
348 if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER && 351 if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER &&
349 !last_omnibox_text_has_inline_autocompletion_) { 352 !last_omnibox_text_has_inline_autocompletion_) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 384
382 if (instant_tab_) { 385 if (instant_tab_) {
383 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); 386 instant_tab_->Update(user_text, selection_start, selection_end, verbatim);
384 } else { 387 } else {
385 if (first_interaction_time_.is_null()) 388 if (first_interaction_time_.is_null())
386 first_interaction_time_ = base::Time::Now(); 389 first_interaction_time_ = base::Time::Now();
387 allow_preview_to_show_search_suggestions_ = true; 390 allow_preview_to_show_search_suggestions_ = true;
388 391
389 // For extended mode, if the loader is not ready at this point, switch over 392 // For extended mode, if the loader is not ready at this point, switch over
390 // to a backup loader. 393 // to a backup loader.
391 if (extended_enabled_ && !loader_->supports_instant() && 394 if (extended_enabled_ && !overlay_->supports_instant() &&
392 !loader_->IsUsingLocalPreview() && browser_->GetActiveWebContents()) { 395 !overlay_->IsUsingLocalPreview() && browser_->GetActiveWebContents()) {
393 CreateLoader(kLocalOmniboxPopupURL, browser_->GetActiveWebContents()); 396 CreateOverlay(kLocalOmniboxPopupURL, browser_->GetActiveWebContents());
394 } 397 }
395 398
396 loader_->Update(extended_enabled_ ? user_text : full_text, 399 overlay_->Update(extended_enabled_ ? user_text : full_text,
397 selection_start, selection_end, verbatim); 400 selection_start, selection_end, verbatim);
398 } 401 }
399 402
400 content::NotificationService::current()->Notify( 403 content::NotificationService::current()->Notify(
401 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, 404 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
402 content::Source<InstantController>(this), 405 content::Source<InstantController>(this),
403 content::NotificationService::NoDetails()); 406 content::NotificationService::NoDetails());
404 407
405 // We don't have new suggestions yet, but we can either reuse the existing 408 // We don't have new suggestions yet, but we can either reuse the existing
406 // suggestion or reset the existing "gray text". 409 // suggestion or reset the existing "gray text".
407 browser_->SetInstantSuggestion(last_suggestion_); 410 browser_->SetInstantSuggestion(last_suggestion_);
408 411
409 return true; 412 return true;
410 } 413 }
411 414
415 scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() {
416 if (!extended_enabled || !ntp_)
417 return scoped_ptr<content::WebContents>(NULL);
418
419 LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents");
420
421 scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents();
422 ntp_.reset();
423 ResetNTP();
424 return ntp_contents.Pass();
425 }
426
412 // TODO(tonyg): This method only fires when the omnibox bounds change. It also 427 // TODO(tonyg): This method only fires when the omnibox bounds change. It also
413 // needs to fire when the preview bounds change (e.g.: open/close info bar). 428 // needs to fire when the preview bounds change (e.g.: open/close info bar).
414 void InstantController::SetPopupBounds(const gfx::Rect& bounds) { 429 void InstantController::SetPopupBounds(const gfx::Rect& bounds) {
415 if (!extended_enabled_ && !instant_enabled_) 430 if (!extended_enabled_ && !instant_enabled_)
416 return; 431 return;
417 432
418 if (popup_bounds_ == bounds) 433 if (popup_bounds_ == bounds)
419 return; 434 return;
420 435
421 popup_bounds_ = bounds; 436 popup_bounds_ = bounds;
422 if (popup_bounds_.height() > last_popup_bounds_.height()) { 437 if (popup_bounds_.height() > last_popup_bounds_.height()) {
423 update_bounds_timer_.Stop(); 438 update_bounds_timer_.Stop();
424 SendPopupBoundsToPage(); 439 SendPopupBoundsToPage();
425 } else if (!update_bounds_timer_.IsRunning()) { 440 } else if (!update_bounds_timer_.IsRunning()) {
426 update_bounds_timer_.Start(FROM_HERE, 441 update_bounds_timer_.Start(FROM_HERE,
427 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, 442 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this,
428 &InstantController::SendPopupBoundsToPage); 443 &InstantController::SendPopupBoundsToPage);
429 } 444 }
430 } 445 }
431 446
432 void InstantController::SetMarginSize(int start, int end) { 447 void InstantController::SetMarginSize(int start, int end) {
433 if (!extended_enabled_ || (start_margin_ == start && end_margin_ == end)) 448 if (!extended_enabled_ || (start_margin_ == start && end_margin_ == end))
434 return; 449 return;
435 450
436 start_margin_ = start; 451 start_margin_ = start;
437 end_margin_ = end; 452 end_margin_ = end;
438 if (loader_) 453 if (overlay_)
439 loader_->SetMarginSize(start_margin_, end_margin_); 454 overlay_->SetMarginSize(start_margin_, end_margin_);
455 if (ntp_)
456 ntp_->SetMarginSize(start_margin_, end_margin_);
440 if (instant_tab_) 457 if (instant_tab_)
441 instant_tab_->SetMarginSize(start_margin_, end_margin_); 458 instant_tab_->SetMarginSize(start_margin_, end_margin_);
442 } 459 }
443 460
444 void InstantController::HandleAutocompleteResults( 461 void InstantController::HandleAutocompleteResults(
445 const std::vector<AutocompleteProvider*>& providers) { 462 const std::vector<AutocompleteProvider*>& providers) {
446 if (!extended_enabled_) 463 if (!extended_enabled_)
447 return; 464 return;
448 465
449 if (!instant_tab_ && !loader_) 466 if (!instant_tab_ && !overlay_)
450 return; 467 return;
451 468
452 DVLOG(1) << "AutocompleteResults:"; 469 DVLOG(1) << "AutocompleteResults:";
453 std::vector<InstantAutocompleteResult> results; 470 std::vector<InstantAutocompleteResult> results;
454 for (ACProviders::const_iterator provider = providers.begin(); 471 for (ACProviders::const_iterator provider = providers.begin();
455 provider != providers.end(); ++provider) { 472 provider != providers.end(); ++provider) {
456 for (ACMatches::const_iterator match = (*provider)->matches().begin(); 473 for (ACMatches::const_iterator match = (*provider)->matches().begin();
457 match != (*provider)->matches().end(); ++match) { 474 match != (*provider)->matches().end(); ++match) {
458 InstantAutocompleteResult result; 475 InstantAutocompleteResult result;
459 result.provider = UTF8ToUTF16((*provider)->GetName()); 476 result.provider = UTF8ToUTF16((*provider)->GetName());
460 result.type = UTF8ToUTF16(AutocompleteMatch::TypeToString(match->type)); 477 result.type = UTF8ToUTF16(AutocompleteMatch::TypeToString(match->type));
461 result.description = match->description; 478 result.description = match->description;
462 result.destination_url = UTF8ToUTF16(match->destination_url.spec()); 479 result.destination_url = UTF8ToUTF16(match->destination_url.spec());
463 result.transition = match->transition; 480 result.transition = match->transition;
464 result.relevance = match->relevance; 481 result.relevance = match->relevance;
465 DVLOG(1) << " " << result.relevance << " " << result.type << " " 482 DVLOG(1) << " " << result.relevance << " " << result.type << " "
466 << result.provider << " " << result.destination_url << " '" 483 << result.provider << " " << result.destination_url << " '"
467 << result.description << "' " << result.transition; 484 << result.description << "' " << result.transition;
468 results.push_back(result); 485 results.push_back(result);
469 } 486 }
470 } 487 }
471 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 488 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
472 "HandleAutocompleteResults: total_results=%d", 489 "HandleAutocompleteResults: total_results=%d",
473 static_cast<int>(results.size()))); 490 static_cast<int>(results.size())));
474 491
475 if (instant_tab_) 492 if (instant_tab_)
476 instant_tab_->SendAutocompleteResults(results); 493 instant_tab_->SendAutocompleteResults(results);
477 else 494 else
478 loader_->SendAutocompleteResults(results); 495 overlay_->SendAutocompleteResults(results);
479 } 496 }
480 497
481 bool InstantController::OnUpOrDownKeyPressed(int count) { 498 bool InstantController::OnUpOrDownKeyPressed(int count) {
482 if (!extended_enabled_) 499 if (!extended_enabled_)
483 return false; 500 return false;
484 501
485 if (!instant_tab_ && !loader_) 502 if (!instant_tab_ && !overlay_)
486 return false; 503 return false;
487 504
488 if (instant_tab_) 505 if (instant_tab_)
489 instant_tab_->UpOrDownKeyPressed(count); 506 instant_tab_->UpOrDownKeyPressed(count);
490 else 507 else
491 loader_->UpOrDownKeyPressed(count); 508 overlay_->UpOrDownKeyPressed(count);
492 509
493 return true; 510 return true;
494 } 511 }
495 512
496 content::WebContents* InstantController::GetPreviewContents() const { 513 content::WebContents* InstantController::GetPreviewContents() const {
497 return loader_ ? loader_->contents() : NULL; 514 return overlay_ ? overlay_->contents() : NULL;
498 } 515 }
499 516
500 bool InstantController::IsPreviewingSearchResults() const { 517 bool InstantController::IsPreviewingSearchResults() const {
501 return model_.mode().is_search_suggestions() && IsFullHeight(model_) && 518 return model_.mode().is_search_suggestions() && IsFullHeight(model_) &&
502 (last_match_was_search_ || 519 (last_match_was_search_ ||
503 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); 520 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER);
504 } 521 }
505 522
506 bool InstantController::CommitIfPossible(InstantCommitType type) { 523 bool InstantController::CommitIfPossible(InstantCommitType type) {
507 if (!extended_enabled_ && !instant_enabled_) 524 if (!extended_enabled_ && !instant_enabled_)
(...skipping 16 matching lines...) Expand all
524 return true; 541 return true;
525 } 542 }
526 return false; 543 return false;
527 } 544 }
528 545
529 if (!IsPreviewingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) 546 if (!IsPreviewingSearchResults() && type != INSTANT_COMMIT_NAVIGATED)
530 return false; 547 return false;
531 548
532 // There may re-entrance here, from the call to browser_->CommitInstant below, 549 // There may re-entrance here, from the call to browser_->CommitInstant below,
533 // which can cause a TabDeactivated notification which gets back here. 550 // which can cause a TabDeactivated notification which gets back here.
534 // In this case, loader_->ReleaseContents() was called already. 551 // In this case, overlay_->ReleaseContents() was called already.
535 if (!GetPreviewContents()) 552 if (!GetPreviewContents())
536 return false; 553 return false;
537 554
538 // Never commit the local omnibox. 555 // Never commit the local omnibox.
539 if (loader_->IsUsingLocalPreview()) 556 if (overlay_->IsUsingLocalPreview())
540 return false; 557 return false;
541 558
542 if (type == INSTANT_COMMIT_FOCUS_LOST) 559 if (type == INSTANT_COMMIT_FOCUS_LOST)
543 loader_->Cancel(last_omnibox_text_); 560 overlay_->Cancel(last_omnibox_text_);
544 else if (type != INSTANT_COMMIT_NAVIGATED && 561 else if (type != INSTANT_COMMIT_NAVIGATED &&
545 type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION) 562 type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION)
546 loader_->Submit(last_omnibox_text_); 563 overlay_->Submit(last_omnibox_text_);
547 564
548 content::WebContents* preview = loader_->ReleaseContents(); 565 scoped_ptr<content::WebContents> preview = overlay_->ReleaseContents();
549 566
550 if (extended_enabled_) { 567 if (extended_enabled_) {
551 // Consider what's happening: 568 // Consider what's happening:
552 // 1. The user has typed a query in the omnibox and committed it (either 569 // 1. The user has typed a query in the omnibox and committed it (either
553 // by pressing Enter or clicking on the preview). 570 // by pressing Enter or clicking on the preview).
554 // 2. We commit the preview to the tab strip, and tell the page. 571 // 2. We commit the preview to the tab strip, and tell the page.
555 // 3. The page will update the URL hash fragment with the query terms. 572 // 3. The page will update the URL hash fragment with the query terms.
556 // After steps 1 and 3, the omnibox will show the query terms. However, if 573 // After steps 1 and 3, the omnibox will show the query terms. However, if
557 // the URL we are committing at step 2 doesn't already have query terms, it 574 // the URL we are committing at step 2 doesn't already have query terms, it
558 // will flash for a brief moment as a plain URL. So, avoid that flicker by 575 // will flash for a brief moment as a plain URL. So, avoid that flicker by
(...skipping 12 matching lines...) Expand all
571 std::string query(UTF16ToUTF8(last_omnibox_text_)); 588 std::string query(UTF16ToUTF8(last_omnibox_text_));
572 if (type != INSTANT_COMMIT_PRESSED_ENTER) { 589 if (type != INSTANT_COMMIT_PRESSED_ENTER) {
573 query += UTF16ToUTF8(last_suggestion_.text); 590 query += UTF16ToUTF8(last_suggestion_.text);
574 // Update |last_omnibox_text_| so that the controller commits the proper 591 // Update |last_omnibox_text_| so that the controller commits the proper
575 // query if the user focuses the omnibox and presses Enter. 592 // query if the user focuses the omnibox and presses Enter.
576 last_omnibox_text_ += last_suggestion_.text; 593 last_omnibox_text_ += last_suggestion_.text;
577 } 594 }
578 entry->SetVirtualURL(GURL( 595 entry->SetVirtualURL(GURL(
579 url + "#q=" + 596 url + "#q=" +
580 net::EscapeQueryParamValue(query, true))); 597 net::EscapeQueryParamValue(query, true)));
581 chrome::search::SearchTabHelper::FromWebContents(preview)-> 598 chrome::search::SearchTabHelper::FromWebContents(preview.get())->
582 NavigationEntryUpdated(); 599 NavigationEntryUpdated();
583 } 600 }
584 } 601 }
585 602
586 // If the preview page has navigated since the last Update(), we need to add 603 // If the preview page has navigated since the last Update(), we need to add
587 // the navigation to history ourselves. Else, the page will navigate after 604 // the navigation to history ourselves. Else, the page will navigate after
588 // commit, and it will be added to history in the usual manner. 605 // commit, and it will be added to history in the usual manner.
589 const history::HistoryAddPageArgs& last_navigation = 606 const history::HistoryAddPageArgs& last_navigation =
590 loader_->last_navigation(); 607 overlay_->last_navigation();
591 if (!last_navigation.url.is_empty()) { 608 if (!last_navigation.url.is_empty()) {
592 content::NavigationEntry* entry = preview->GetController().GetActiveEntry(); 609 content::NavigationEntry* entry = preview->GetController().GetActiveEntry();
593 610
594 // The last navigation should be the same as the active entry if the loader 611 // The last navigation should be the same as the active entry if the overlay
595 // is in search mode. During navigation, the active entry could have 612 // is in search mode. During navigation, the active entry could have
596 // changed since DidCommitProvisionalLoadForFrame is called after the entry 613 // changed since DidCommitProvisionalLoadForFrame is called after the entry
597 // is changed. 614 // is changed.
598 // TODO(shishir): Should we commit the last navigation for 615 // TODO(shishir): Should we commit the last navigation for
599 // INSTANT_COMMIT_NAVIGATED. 616 // INSTANT_COMMIT_NAVIGATED.
600 DCHECK(type == INSTANT_COMMIT_NAVIGATED || 617 DCHECK(type == INSTANT_COMMIT_NAVIGATED ||
601 last_navigation.url == entry->GetURL()); 618 last_navigation.url == entry->GetURL());
602 619
603 // Add the page to history. 620 // Add the page to history.
604 HistoryTabHelper* history_tab_helper = 621 HistoryTabHelper* history_tab_helper =
605 HistoryTabHelper::FromWebContents(preview); 622 HistoryTabHelper::FromWebContents(preview.get());
606 history_tab_helper->UpdateHistoryForNavigation(last_navigation); 623 history_tab_helper->UpdateHistoryForNavigation(last_navigation);
607 624
608 // Update the page title. 625 // Update the page title.
609 history_tab_helper->UpdateHistoryPageTitle(*entry); 626 history_tab_helper->UpdateHistoryPageTitle(*entry);
610 } 627 }
611 628
612 // Add a fake history entry with a non-Instant search URL, so that search 629 // Add a fake history entry with a non-Instant search URL, so that search
613 // terms extraction (for autocomplete history matches) works. 630 // terms extraction (for autocomplete history matches) works.
614 HistoryService* history = HistoryServiceFactory::GetForProfile( 631 HistoryService* history = HistoryServiceFactory::GetForProfile(
615 Profile::FromBrowserContext(preview->GetBrowserContext()), 632 Profile::FromBrowserContext(preview->GetBrowserContext()),
616 Profile::EXPLICIT_ACCESS); 633 Profile::EXPLICIT_ACCESS);
617 if (history) { 634 if (history) {
618 history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(), 635 history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(),
619 history::RedirectList(), last_transition_type_, 636 history::RedirectList(), last_transition_type_,
620 history::SOURCE_BROWSED, false); 637 history::SOURCE_BROWSED, false);
621 } 638 }
622 639
623 preview->GetController().PruneAllButActive(); 640 preview->GetController().PruneAllButActive();
624 641
625 if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) { 642 if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) {
626 content::WebContents* active_tab = browser_->GetActiveWebContents(); 643 content::WebContents* active_tab = browser_->GetActiveWebContents();
627 AddSessionStorageHistogram(extended_enabled_, active_tab, preview); 644 AddSessionStorageHistogram(extended_enabled_, active_tab, preview.get());
628 preview->GetController().CopyStateFromAndPrune( 645 preview->GetController().CopyStateFromAndPrune(
629 &active_tab->GetController()); 646 &active_tab->GetController());
630 } 647 }
631 648
632 // Browser takes ownership of the preview. 649 // Save notification source before we release the preview.
633 browser_->CommitInstant(preview, type == INSTANT_COMMIT_PRESSED_ALT_ENTER); 650 const content::NotificationSource& notification_source =
651 content::Source<content::WebContents>(preview.get());
sreeram 2013/02/07 18:22:46 It's uncommon to bind a reference to a temporary.
samarth 2013/02/07 22:11:55 Done.
652
653 browser_->CommitInstant(preview.Pass(),
654 type == INSTANT_COMMIT_PRESSED_ALT_ENTER);
634 655
635 content::NotificationService::current()->Notify( 656 content::NotificationService::current()->Notify(
636 chrome::NOTIFICATION_INSTANT_COMMITTED, 657 chrome::NOTIFICATION_INSTANT_COMMITTED,
637 content::Source<content::WebContents>(preview), 658 notification_source,
638 content::NotificationService::NoDetails()); 659 content::NotificationService::NoDetails());
639 660
640 // Hide explicitly. See comments in HideLoader() for why. 661 // Hide explicitly. See comments in HideOverlay() for why.
641 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); 662 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
642 663
643 // Delay deletion as we could've gotten here from an InstantLoader method. 664 // Delay deletion as we could've gotten here from an InstantOverlay method.
644 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); 665 MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release());
645 666
646 // Try to create another loader immediately so that it is ready for the next 667 // Try to create another overlay immediately so that it is ready for the next
647 // user interaction. 668 // user interaction.
648 EnsureLoaderIsCurrent(false); 669 EnsureOverlayIsCurrent(false);
649 670
650 LOG_INSTANT_DEBUG_EVENT(this, "Committed"); 671 LOG_INSTANT_DEBUG_EVENT(this, "Committed");
651 return true; 672 return true;
652 } 673 }
653 674
654 void InstantController::OmniboxFocusChanged( 675 void InstantController::OmniboxFocusChanged(
655 OmniboxFocusState state, 676 OmniboxFocusState state,
656 OmniboxFocusChangeReason reason, 677 OmniboxFocusChangeReason reason,
657 gfx::NativeView view_gaining_focus) { 678 gfx::NativeView view_gaining_focus) {
658 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 679 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
659 "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_, 680 "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_,
660 state, reason)); 681 state, reason));
661 682
662 OmniboxFocusState old_focus_state = omnibox_focus_state_; 683 OmniboxFocusState old_focus_state = omnibox_focus_state_;
663 omnibox_focus_state_ = state; 684 omnibox_focus_state_ = state;
664 if (!extended_enabled_ && !instant_enabled_) 685 if (!extended_enabled_ && !instant_enabled_)
665 return; 686 return;
666 687
667 // Tell the page if the key capture mode changed unless the focus state 688 // Tell the page if the key capture mode changed unless the focus state
668 // changed because of TYPING. This is because in that case, the browser hasn't 689 // changed because of TYPING. This is because in that case, the browser hasn't
669 // really stopped capturing key strokes. 690 // really stopped capturing key strokes.
670 // 691 //
671 // (More practically, if we don't do this check, the page would receive 692 // (More practically, if we don't do this check, the page would receive
672 // onkeycapturechange before the corresponding onchange, and the page would 693 // onkeycapturechange before the corresponding onchange, and the page would
673 // have no way of telling whether the keycapturechange happened because of 694 // have no way of telling whether the keycapturechange happened because of
674 // some actual user action or just because they started typing.) 695 // some actual user action or just because they started typing.)
675 if (extended_enabled_ && GetPreviewContents() && 696 if (extended_enabled_ && GetPreviewContents() &&
676 reason != OMNIBOX_FOCUS_CHANGE_TYPING) 697 reason != OMNIBOX_FOCUS_CHANGE_TYPING) {
677 loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); 698 const bool is_key_capture_enabled =
699 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE;
700 if (overlay_)
701 overlay_->KeyCaptureChanged(is_key_capture_enabled);
702 if (instant_tab_)
703 instant_tab_->KeyCaptureChanged(is_key_capture_enabled);
704 }
678 705
679 // If focus went from outside the omnibox to the omnibox, preload the default 706 // If focus went from outside the omnibox to the omnibox, preload the default
680 // search engine, in anticipation of the user typing a query. If the reverse 707 // search engine, in anticipation of the user typing a query. If the reverse
681 // happened, commit or discard the preview. 708 // happened, commit or discard the preview.
682 if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) { 709 if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) {
683 // On explicit user actions, ignore the Instant blacklist. 710 // On explicit user actions, ignore the Instant blacklist.
684 EnsureLoaderIsCurrent(reason == OMNIBOX_FOCUS_CHANGE_EXPLICIT); 711 EnsureOverlayIsCurrent(reason == OMNIBOX_FOCUS_CHANGE_EXPLICIT);
685 } else if (state == OMNIBOX_FOCUS_NONE && 712 } else if (state == OMNIBOX_FOCUS_NONE &&
686 old_focus_state != OMNIBOX_FOCUS_NONE) { 713 old_focus_state != OMNIBOX_FOCUS_NONE) {
687 OmniboxLostFocus(view_gaining_focus); 714 OmniboxLostFocus(view_gaining_focus);
688 } 715 }
689 } 716 }
690 717
691 void InstantController::SearchModeChanged( 718 void InstantController::SearchModeChanged(
692 const chrome::search::Mode& old_mode, 719 const chrome::search::Mode& old_mode,
693 const chrome::search::Mode& new_mode) { 720 const chrome::search::Mode& new_mode) {
694 if (!extended_enabled_) 721 if (!extended_enabled_)
695 return; 722 return;
696 723
697 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 724 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
698 "SearchModeChanged: [origin:mode] %d:%d to %d:%d", old_mode.origin, 725 "SearchModeChanged: [origin:mode] %d:%d to %d:%d", old_mode.origin,
699 old_mode.mode, new_mode.origin, new_mode.mode)); 726 old_mode.mode, new_mode.origin, new_mode.mode));
700 727
701 search_mode_ = new_mode; 728 search_mode_ = new_mode;
702 if (!new_mode.is_search_suggestions()) 729 if (!new_mode.is_search_suggestions())
703 HideLoader(); 730 HideOverlay();
704 731
705 if (loader_) 732 if (overlay_)
706 loader_->SearchModeChanged(new_mode); 733 overlay_->SearchModeChanged(new_mode);
707 734
708 ResetInstantTab(); 735 ResetInstantTab();
709 } 736 }
710 737
711 void InstantController::ActiveTabChanged() { 738 void InstantController::ActiveTabChanged() {
712 if (!extended_enabled_ && !instant_enabled_) 739 if (!extended_enabled_ && !instant_enabled_)
713 return; 740 return;
714 741
715 LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged"); 742 LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged");
716 743
717 // When switching tabs, always hide the preview, except if it's showing NTP 744 // When switching tabs, always hide the preview.
718 // content, and the new tab is also an NTP. 745 HideOverlay();
719 if (!search_mode_.is_ntp() || !model_.mode().is_ntp())
720 HideLoader();
721 746
722 if (extended_enabled_) 747 if (extended_enabled_)
723 ResetInstantTab(); 748 ResetInstantTab();
724 } 749 }
725 750
726 void InstantController::TabDeactivated(content::WebContents* contents) { 751 void InstantController::TabDeactivated(content::WebContents* contents) {
727 LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated"); 752 LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated");
728 if (extended_enabled_ && !contents->IsBeingDestroyed()) 753 if (extended_enabled_ && !contents->IsBeingDestroyed())
729 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); 754 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
730 } 755 }
731 756
732 void InstantController::SetInstantEnabled(bool instant_enabled) { 757 void InstantController::SetInstantEnabled(bool instant_enabled) {
733 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 758 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
734 "SetInstantEnabled: %d", instant_enabled)); 759 "SetInstantEnabled: %d", instant_enabled));
735 instant_enabled_ = instant_enabled; 760 instant_enabled_ = instant_enabled;
736 HideInternal(); 761 HideInternal();
737 loader_.reset(); 762 overlay_.reset();
738 if (extended_enabled_ || instant_enabled_) 763 if (extended_enabled_ || instant_enabled_)
739 EnsureLoaderIsCurrent(false); 764 EnsureOverlayIsCurrent(false);
765 if (extended_enabled_)
766 ResetNTP();
740 if (instant_tab_) 767 if (instant_tab_)
741 instant_tab_->SetDisplayInstantResults(instant_enabled_); 768 instant_tab_->SetDisplayInstantResults(instant_enabled_);
742 } 769 }
743 770
744 void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) { 771 void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) {
745 if (!extended_enabled_) 772 if (!extended_enabled_)
746 return; 773 return;
747 774
748 if (loader_) 775 if (overlay_)
749 loader_->SendThemeBackgroundInfo(theme_info); 776 overlay_->SendThemeBackgroundInfo(theme_info);
777 if (ntp_)
778 ntp_->SendThemeBackgroundInfo(theme_info);
750 } 779 }
751 780
752 void InstantController::ThemeAreaHeightChanged(int height) { 781 void InstantController::ThemeAreaHeightChanged(int height) {
753 if (!extended_enabled_) 782 if (!extended_enabled_)
754 return; 783 return;
755 784
756 if (loader_) 785 if (overlay_)
757 loader_->SendThemeAreaHeight(height); 786 overlay_->SendThemeAreaHeight(height);
787 if (ntp_)
788 ntp_->SendThemeAreaHeight(height);
789 }
790
791 void InstantController::SwappedOverlayContents() {
792 model_.SetPreviewContents(GetPreviewContents());
793 }
794
795 void InstantController::FocusedOverlayContents() {
796 #if defined(USE_AURA)
797 // On aura the omnibox only receives a focus lost if we initiate the focus
798 // change. This does that.
799 if (!model_.mode().is_default())
800 browser_->InstantPreviewFocused();
801 #endif
802 }
803
804 void InstantController::ReloadOverlayIfStale() {
805 // The local popup is never stale.
806 if (overlay_ && overlay_->IsUsingLocalPreview())
807 return;
808
809 // If the preview is showing or the omnibox has focus, don't delete the
810 // overlay. It will get refreshed the next time the preview is hidden or the
811 // omnibox loses focus.
812 if ((!overlay_ || overlay_->is_stale()) &&
813 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE &&
814 model_.mode().is_default()) {
815 overlay_.reset();
816 EnsureOverlayIsCurrent(false);
817 }
818 }
819
820 void InstantController::LogDebugEvent(const std::string& info) const {
821 DVLOG(1) << info;
822
823 debug_events_.push_front(std::make_pair(
824 base::Time::Now().ToInternalValue(), info));
825 static const size_t kMaxDebugEventSize = 2000;
826 if (debug_events_.size() > kMaxDebugEventSize)
827 debug_events_.pop_back();
828 }
829
830 void InstantController::InstantPageRenderViewCreated(
831 const content::WebContents* contents) {
832 if (!extended_enabled_)
833 return;
834
835 // Ensure the searchbox API has the correct initial state.
836 if (IsContentsFrom(overlay(), contents)) {
837 overlay_->SetDisplayInstantResults(instant_enabled_);
838 overlay_->SearchModeChanged(search_mode_);
839 overlay_->KeyCaptureChanged(
840 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
841 overlay_->SetMarginSize(start_margin_, end_margin_);
842 overlay_->InitializeFonts();
843 } else if (IsContentsFrom(ntp(), contents)) {
844 ntp_->SetDisplayInstantResults(instant_enabled_);
845 ntp_->SetMarginSize(start_margin_, end_margin_);
846 ntp_->InitializeFonts();
sreeram 2013/02/07 18:22:46 Don't you need to send the theme info to the NTP?
samarth 2013/02/07 22:11:55 As we discussed, this is already somewhat broken.
847 }
848 }
849
850 void InstantController::InstantSupportDetermined(
851 const content::WebContents* contents,
852 bool supports_instant) {
853 if (IsContentsFrom(instant_tab(), contents)) {
854 if (!supports_instant)
855 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release());
856 } else if (IsContentsFrom(ntp(), contents)) {
857 if (supports_instant)
858 RemoveFromBlacklist(ntp_->instant_url());
859 else
860 BlacklistAndResetNTP();
861
862 content::NotificationService::current()->Notify(
863 chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
864 content::Source<InstantController>(this),
865 content::NotificationService::NoDetails());
866
867 } else if (IsContentsFrom(overlay(), contents)) {
868 if (supports_instant)
869 RemoveFromBlacklist(overlay_->instant_url());
870 else
871 BlacklistAndResetOverlay();
872
873 content::NotificationService::current()->Notify(
874 chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
875 content::Source<InstantController>(this),
876 content::NotificationService::NoDetails());
877 }
878 }
879
880 void InstantController::InstantPageRenderViewGone(
881 const content::WebContents* contents) {
882 if (IsContentsFrom(overlay(), contents))
883 BlacklistAndResetOverlay();
884 else if (IsContentsFrom(ntp(), contents))
885 BlacklistAndResetNTP();
886 }
887
888 void InstantController::InstantPageAboutToNavigateMainFrame(
889 const content::WebContents* contents,
890 const GURL& url) {
891 if (!IsContentsFrom(overlay(), contents))
892 return;
893
894 // If the page does not yet support instant, we allow redirects and other
895 // navigations to go through since the instant URL can redirect - e.g. to
896 // country specific pages.
897 if (!overlay_->supports_instant())
898 return;
899
900 GURL instant_url(overlay_->instant_url());
901
902 // If we are navigating to the instant URL, do nothing.
903 if (url == instant_url)
904 return;
905
906 // Commit the navigation if either:
907 // - The page is in NTP mode (so it could only navigate on a user click) or
908 // - The page is not in NTP mode and we are navigating to a URL with a
909 // different host or path than the instant URL. This enables the instant
910 // page when it is showing search results to change the query parameters
911 // and fragments of the URL without it navigating.
912 if (model_.mode().is_ntp() ||
913 (url.host() != instant_url.host() || url.path() != instant_url.path())) {
914 CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
915 }
758 } 916 }
759 917
760 void InstantController::SetSuggestions( 918 void InstantController::SetSuggestions(
761 const content::WebContents* contents, 919 const content::WebContents* contents,
762 const std::vector<InstantSuggestion>& suggestions) { 920 const std::vector<InstantSuggestion>& suggestions) {
763 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); 921 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions");
764 922
765 // Ignore if the message is from an unexpected source. 923 // Ignore if the message is from an unexpected source.
766 if (instant_tab_) { 924 if (IsContentsFrom(ntp(), contents))
767 if (instant_tab_->contents() != contents)
768 return;
769 } else if (!loader_ || loader_->contents() != contents ||
770 !allow_preview_to_show_search_suggestions_) {
771 return; 925 return;
772 } 926 if (instant_tab_ && !IsContentsFrom(instant_tab(), contents))
927 return;
928 if (IsContentsFrom(overlay(), contents) &&
929 !allow_preview_to_show_search_suggestions_)
930 return;
773 931
774 InstantSuggestion suggestion; 932 InstantSuggestion suggestion;
775 if (!suggestions.empty()) 933 if (!suggestions.empty())
776 suggestion = suggestions[0]; 934 suggestion = suggestions[0];
777 935
778 if (instant_tab_ && search_mode_.is_search_results() && 936 if (instant_tab_ && search_mode_.is_search_results() &&
779 suggestion.behavior == INSTANT_COMPLETE_REPLACE) { 937 suggestion.behavior == INSTANT_COMPLETE_REPLACE) {
780 // Update |last_omnibox_text_| so that the controller commits the proper 938 // Update |last_omnibox_text_| so that the controller commits the proper
781 // query if the user focuses the omnibox and presses Enter. 939 // query if the user focuses the omnibox and presses Enter.
782 last_omnibox_text_ = suggestion.text; 940 last_omnibox_text_ = suggestion.text;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 last_suggestion_ = suggestion; 1001 last_suggestion_ = suggestion;
844 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1002 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
845 "SetInstantSuggestion: text='%s' behavior=%d", 1003 "SetInstantSuggestion: text='%s' behavior=%d",
846 UTF16ToUTF8(suggestion.text).c_str(), suggestion.behavior)); 1004 UTF16ToUTF8(suggestion.text).c_str(), suggestion.behavior));
847 browser_->SetInstantSuggestion(suggestion); 1005 browser_->SetInstantSuggestion(suggestion);
848 } else { 1006 } else {
849 last_suggestion_ = InstantSuggestion(); 1007 last_suggestion_ = InstantSuggestion();
850 } 1008 }
851 } 1009 }
852 1010
853 // Extended mode pages will call ShowLoader() when they are ready. 1011 // Extended mode pages will call ShowOverlay() when they are ready.
854 if (!extended_enabled_) 1012 if (!extended_enabled_)
855 ShowLoader(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT); 1013 ShowOverlay(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT);
856 } 1014 }
857 1015
858 void InstantController::InstantSupportDetermined( 1016 void InstantController::ShowInstantPreview(const content::WebContents* contents,
859 const content::WebContents* contents, 1017 InstantShownReason reason,
860 bool supports_instant) { 1018 int height,
861 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1019 InstantSizeUnits units) {
862 "InstantSupportDetermined: supports_instant= %d", supports_instant)); 1020 if (extended_enabled_ && IsContentsFrom(overlay(), contents))
1021 ShowOverlay(reason, height, units);
1022 }
863 1023
864 if (instant_tab_ && instant_tab_->contents() == contents) { 1024 void InstantController::StartCapturingKeyStrokes(
865 if (!supports_instant) 1025 const content::WebContents* contents) {
866 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); 1026 if (!extended_enabled_)
867 return; 1027 return;
868 }
869 1028
870 if (loader_ && loader_->contents() == contents) { 1029 // Only honor the call if it comes from an active InstantTab or from an
871 if (supports_instant) { 1030 // InstantOverlay that is being shown.
872 if (blacklisted_urls_.erase(loader_->instant_url())) { 1031 if (IsContentsFrom(instant_tab(), contents) ||
873 RecordEventHistogram( 1032 (IsContentsFrom(overlay(), contents) && !model_.mode().is_default())) {
874 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST); 1033 browser_->FocusOmniboxInvisibly();
875 }
876 } else {
877 ++blacklisted_urls_[loader_->instant_url()];
878 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
879 HideInternal();
880 delete loader_->ReleaseContents();
881 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
882 EnsureLoaderIsCurrent(false);
883 }
884 content::NotificationService::current()->Notify(
885 chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED,
886 content::Source<InstantController>(this),
887 content::NotificationService::NoDetails());
888 } 1034 }
889 } 1035 }
890 1036
891 void InstantController::ShowInstantPreview(InstantShownReason reason, 1037 void InstantController::StopCapturingKeyStrokes(
892 int height, 1038 content::WebContents* contents) {
893 InstantSizeUnits units) { 1039 // Nothing to do if omnibox doesn't have invisible focus.
894 if (extended_enabled_) 1040 if (!extended_enabled_ || omnibox_focus_state_ != OMNIBOX_FOCUS_INVISIBLE)
895 ShowLoader(reason, height, units);
896 }
897
898 void InstantController::StartCapturingKeyStrokes() {
899 // Ignore unless the loader is active and on the NTP.
900 if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp())
901 browser_->FocusOmniboxInvisibly();
902 }
903
904 void InstantController::StopCapturingKeyStrokes() {
905 // Ignore unless the loader is active and on the NTP, and the omnibox has
906 // invisible focus.
907 if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp() &&
908 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE)
909 loader_->contents()->Focus();
910 }
911
912 void InstantController::SwappedWebContents() {
913 model_.SetPreviewContents(GetPreviewContents());
914 }
915
916 void InstantController::InstantLoaderContentsFocused() {
917 #if defined(USE_AURA)
918 // On aura the omnibox only receives a focus lost if we initiate the focus
919 // change. This does that.
920 if (!model_.mode().is_default())
921 browser_->InstantPreviewFocused();
922 #endif
923 }
924
925 void InstantController::InstantLoaderRenderViewGone() {
926 ++blacklisted_urls_[loader_->instant_url()];
927 HideInternal();
928 delete loader_->ReleaseContents();
929 // Delay deletion as we have gotten here from an InstantLoader method.
930 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
931 EnsureLoaderIsCurrent(false);
932 }
933
934 void InstantController::InstantLoaderAboutToNavigateMainFrame(const GURL& url) {
935 // If the page does not yet support instant, we allow redirects and other
936 // navigations to go through since the instant URL can redirect - e.g. to
937 // country specific pages.
938 if (!loader_->supports_instant())
939 return; 1041 return;
940 1042
941 GURL instant_url(loader_->instant_url()); 1043 // Only honor the call if it comes from an active InstantTab or from an
942 1044 // InstantOverlay that is being shown.
943 // If we are navigating to the instant URL, do nothing. 1045 if (IsContentsFrom(instant_tab(), contents) ||
944 if (url == instant_url) 1046 (IsContentsFrom(overlay(), contents) && !model_.mode().is_default())) {
945 return; 1047 contents->Focus();
946
947 // Commit the navigation if either:
948 // - The page is in NTP mode (so it could only navigate on a user click) or
949 // - The page is not in NTP mode and we are navigating to a URL with a
950 // different host or path than the instant URL. This enables the instant
951 // page when it is showing search results to change the query parameters
952 // and fragments of the URL without it navigating.
953 if (model_.mode().is_ntp() ||
954 (url.host() != instant_url.host() || url.path() != instant_url.path())) {
955 CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
956 } 1048 }
957 } 1049 }
958 1050
959 void InstantController::InstantLoaderRenderViewCreated() { 1051 void InstantController::NavigateToURL(const content::WebContents* contents,
1052 const GURL& url,
1053 content::PageTransition transition) {
1054 // TODO(samarth): handle case where contents are no longer "active" (e.g. user
1055 // has switched tabs).
960 if (!extended_enabled_) 1056 if (!extended_enabled_)
961 return; 1057 return;
962 1058 if (overlay_)
963 // Ensure the searchbox API has the correct initial state. 1059 HideOverlay();
964 loader_->SetDisplayInstantResults(instant_enabled_); 1060 browser_->OpenURLInCurrentTab(url, transition);
965 loader_->SearchModeChanged(search_mode_);
966 loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
967 loader_->SetMarginSize(start_margin_, end_margin_);
968 loader_->InitializeFonts();
969 } 1061 }
970 1062
971 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { 1063 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
972 // If the preview is showing custom NTP content, don't hide it, commit it 1064 // If the preview is showing custom NTP content, don't hide it, commit it
973 // (no matter where the user clicked) or try to recreate it. 1065 // (no matter where the user clicked) or try to recreate it.
974 if (model_.mode().is_ntp()) 1066 if (model_.mode().is_ntp())
975 return; 1067 return;
976 1068
977 // If the preview is not showing at all, recreate it if it's stale. 1069 // If the preview is not showing at all, recreate it if it's stale.
978 if (model_.mode().is_default()) { 1070 if (model_.mode().is_default()) {
979 OnStaleLoader(); 1071 ReloadOverlayIfStale();
980 MaybeSwitchToRemoteLoader(); 1072 MaybeSwitchToRemoteOverlay();
981 return; 1073 return;
982 } 1074 }
983 1075
984 // The preview is showing search suggestions. If GetPreviewContents() is NULL, 1076 // The preview is showing search suggestions. If GetPreviewContents() is NULL,
985 // we are in the commit path. Don't do anything. 1077 // we are in the commit path. Don't do anything.
986 if (!GetPreviewContents()) 1078 if (!GetPreviewContents())
987 return; 1079 return;
988 1080
989 #if defined(OS_MACOSX) 1081 #if defined(OS_MACOSX)
990 // TODO(sreeram): See if Mac really needs this special treatment. 1082 // TODO(sreeram): See if Mac really needs this special treatment.
991 if (!loader_->is_pointer_down_from_activate()) 1083 if (!overlay_->is_pointer_down_from_activate())
992 HideLoader(); 1084 HideOverlay();
993 #else 1085 #else
994 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), 1086 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus),
995 loader_->contents())) 1087 overlay_->contents()))
996 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); 1088 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
997 else 1089 else
998 HideLoader(); 1090 HideOverlay();
999 #endif 1091 #endif
1000 } 1092 }
1001 1093
1002 void InstantController::NavigateToURL(const GURL& url, 1094 void InstantController::ResetNTP() {
1003 content::PageTransition transition) { 1095 ntp_.reset();
1004 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1096 std::string instant_url;
1005 "NavigateToURL: url='%s'", url.spec().c_str())); 1097 if (!GetInstantURL(browser_->profile(), false, &instant_url))
1098 return;
1006 1099
1007 if (!extended_enabled_) 1100 ntp_.reset(new InstantNTP(this, instant_url));
1008 return; 1101 ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents(),
1009 if (loader_) 1102 base::Bind(&InstantController::ResetNTP,
1010 HideLoader(); 1103 base::Unretained(this)));
1011 browser_->OpenURLInCurrentTab(url, transition);
1012 } 1104 }
1013 1105
1014 void InstantController::LogDebugEvent(const std::string& info) const { 1106 bool InstantController::EnsureOverlayIsCurrent(bool ignore_blacklist) {
1015 DVLOG(1) << info;
1016
1017 debug_events_.push_front(std::make_pair(
1018 base::Time::Now().ToInternalValue(), info));
1019 static const size_t kMaxDebugEventSize = 2000;
1020 if (debug_events_.size() > kMaxDebugEventSize)
1021 debug_events_.pop_back();
1022 }
1023
1024 bool InstantController::EnsureLoaderIsCurrent(bool ignore_blacklist) {
1025 // If there's no active tab, the browser is closing. 1107 // If there's no active tab, the browser is closing.
1026 const content::WebContents* active_tab = browser_->GetActiveWebContents(); 1108 const content::WebContents* active_tab = browser_->GetActiveWebContents();
1027 if (!active_tab) 1109 if (!active_tab)
1028 return false; 1110 return false;
1029 1111
1112 Profile* profile = Profile::FromBrowserContext(
1113 active_tab->GetBrowserContext());
1030 std::string instant_url; 1114 std::string instant_url;
1031 if (!GetInstantURL(active_tab, ignore_blacklist, &instant_url)) { 1115 if (!GetInstantURL(profile, ignore_blacklist, &instant_url)) {
1032 // If we are in extended mode, fallback to the local popup. 1116 // If we are in extended mode, fallback to the local popup.
1033 if (extended_enabled_) 1117 if (extended_enabled_)
1034 instant_url = kLocalOmniboxPopupURL; 1118 instant_url = kLocalOmniboxPopupURL;
1035 else 1119 else
1036 return false; 1120 return false;
1037 } 1121 }
1038 1122
1039 if (!loader_ || loader_->instant_url() != instant_url) 1123 if (!overlay_ || overlay_->instant_url() != instant_url)
1040 CreateLoader(instant_url, active_tab); 1124 CreateOverlay(instant_url, active_tab);
1041 1125
1042 return true; 1126 return true;
1043 } 1127 }
1044 1128
1045 void InstantController::CreateLoader(const std::string& instant_url, 1129 void InstantController::CreateOverlay(const std::string& instant_url,
1046 const content::WebContents* active_tab) { 1130 const content::WebContents* active_tab) {
1047 // Update theme info so that the loader picks up the correct fonts. 1131 // Update theme info so that the loader picks up the correct fonts.
1048 if (extended_enabled_) 1132 if (extended_enabled_)
1049 browser_->UpdateThemeInfoForPreview(); 1133 browser_->UpdateThemeInfoForPreview();
1050 1134
1051 HideInternal(); 1135 HideInternal();
1052 loader_.reset(new InstantLoader(this, instant_url)); 1136 overlay_.reset(new InstantOverlay(this, instant_url));
1053 loader_->InitContents(active_tab); 1137 overlay_->InitContents(browser_->profile(), active_tab);
1054 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1138 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
1055 "CreateLoader: instant_url='%s'", instant_url.c_str())); 1139 "CreateOverlay: instant_url='%s'", instant_url.c_str()));
1056
1057 // Restart the stale loader timer.
1058 stale_loader_timer_.Start(FROM_HERE,
1059 base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this,
1060 &InstantController::OnStaleLoader);
1061 } 1140 }
1062 1141
1063 void InstantController::OnStaleLoader() { 1142 void InstantController::MaybeSwitchToRemoteOverlay() {
1064 // The local popup is never stale. 1143 if (!overlay_ || omnibox_focus_state_ != OMNIBOX_FOCUS_NONE ||
1065 if (loader_ && loader_->IsUsingLocalPreview())
1066 return;
1067
1068 // If the preview is showing or the omnibox has focus, don't delete the
1069 // loader. It will get refreshed the next time the preview is hidden or the
1070 // omnibox loses focus.
1071 if (!stale_loader_timer_.IsRunning() &&
1072 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE &&
1073 model_.mode().is_default()) {
1074 loader_.reset();
1075 EnsureLoaderIsCurrent(false);
1076 }
1077 }
1078
1079 void InstantController::MaybeSwitchToRemoteLoader() {
1080 if (!loader_ || omnibox_focus_state_ != OMNIBOX_FOCUS_NONE ||
1081 !model_.mode().is_default()) { 1144 !model_.mode().is_default()) {
1082 return; 1145 return;
1083 } 1146 }
1084 1147
1085 EnsureLoaderIsCurrent(false); 1148 EnsureOverlayIsCurrent(false);
1086 } 1149 }
1087 1150
1088 void InstantController::ResetInstantTab() { 1151 void InstantController::ResetInstantTab() {
1089 // Do not wire up the InstantTab if instant should only use local previews, to 1152 // Do not wire up the InstantTab if instant should only use local previews, to
1090 // prevent it from sending data to the page. 1153 // prevent it from sending data to the page.
1091 if (search_mode_.is_origin_search() && !use_local_preview_only_) { 1154 if (!search_mode_.is_origin_default() && !use_local_preview_only_) {
1092 content::WebContents* active_tab = browser_->GetActiveWebContents(); 1155 content::WebContents* active_tab = browser_->GetActiveWebContents();
1093 if (!instant_tab_ || active_tab != instant_tab_->contents()) { 1156 if (!instant_tab_ || active_tab != instant_tab_->contents()) {
1094 instant_tab_.reset(new InstantTab(this, active_tab)); 1157 instant_tab_.reset(new InstantTab(this));
1095 instant_tab_->Init(); 1158 instant_tab_->Init(active_tab);
1096 instant_tab_->SetDisplayInstantResults(instant_enabled_); 1159 instant_tab_->SetDisplayInstantResults(instant_enabled_);
1097 instant_tab_->SetMarginSize(start_margin_, end_margin_); 1160 instant_tab_->SetMarginSize(start_margin_, end_margin_);
1098 instant_tab_->InitializeFonts(); 1161 instant_tab_->InitializeFonts();
1162 instant_tab_->KeyCaptureChanged(
1163 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
1099 } 1164 }
1100 1165
1101 // Hide the |loader_| since we are now using |instant_tab_| instead. 1166 // Hide the |overlay_| since we are now using |instant_tab_| instead.
1102 HideLoader(); 1167 HideOverlay();
1103 } else { 1168 } else {
1104 instant_tab_.reset(); 1169 instant_tab_.reset();
1105 } 1170 }
1106 } 1171 }
1107 1172
1108 void InstantController::HideLoader() { 1173 void InstantController::HideOverlay() {
1109 HideInternal(); 1174 HideInternal();
1110 OnStaleLoader(); 1175 ReloadOverlayIfStale();
1111 MaybeSwitchToRemoteLoader(); 1176 MaybeSwitchToRemoteOverlay();
1112 } 1177 }
1113 1178
1114 void InstantController::HideInternal() { 1179 void InstantController::HideInternal() {
1115 LOG_INSTANT_DEBUG_EVENT(this, "Hide"); 1180 LOG_INSTANT_DEBUG_EVENT(this, "Hide");
1116 1181
1117 // If GetPreviewContents() returns NULL, either we're already in the desired 1182 // If GetPreviewContents() returns NULL, either we're already in the desired
1118 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't 1183 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't
1119 // change the state just yet; else we may hide the preview unnecessarily. 1184 // change the state just yet; else we may hide the preview unnecessarily.
1120 // Instead, the state will be set correctly after the commit is done. 1185 // Instead, the state will be set correctly after the commit is done.
1121 if (GetPreviewContents()) { 1186 if (GetPreviewContents()) {
1122 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); 1187 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
1123 allow_preview_to_show_search_suggestions_ = false; 1188 allow_preview_to_show_search_suggestions_ = false;
1124 1189
1125 // Send a message asking the preview to clear out old results. 1190 // Send a message asking the preview to clear out old results.
1126 loader_->Update(string16(), 0, 0, true); 1191 overlay_->Update(string16(), 0, 0, true);
1127 } 1192 }
1128 1193
1129 // Clear the first interaction timestamp for later use. 1194 // Clear the first interaction timestamp for later use.
1130 first_interaction_time_ = base::Time(); 1195 first_interaction_time_ = base::Time();
1131 } 1196 }
1132 1197
1133 void InstantController::ShowLoader(InstantShownReason reason, 1198 void InstantController::ShowOverlay(InstantShownReason reason,
1134 int height, 1199 int height,
1135 InstantSizeUnits units) { 1200 InstantSizeUnits units) {
1136 // If we are on a committed search results page, the |loader_| is not in use. 1201 // If we are on a committed search results page, the |overlay_| is not in use.
1137 if (instant_tab_) 1202 if (instant_tab_)
1138 return; 1203 return;
1139 1204
1140 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1205 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
1141 "Show: reason=%d height=%d units=%d", reason, height, units)); 1206 "Show: reason=%d height=%d units=%d", reason, height, units));
1142 1207
1143 // Must be on NTP to show NTP content. 1208 // INSTANT_SHOWN_CUSTOM_NTP_CONTENT is no longer supported.
1144 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !search_mode_.is_ntp()) 1209 // TODO(samarth): remove once the server has been updated.
1210 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT)
1145 return; 1211 return;
1146 1212
1147 // Must have updated omnibox after the last HideLoader() to show suggestions. 1213 // Must have updated omnibox after the last HideOverlay() to show suggestions.
1148 if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS || 1214 if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS ||
1149 reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) && 1215 reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) &&
1150 !allow_preview_to_show_search_suggestions_) 1216 !allow_preview_to_show_search_suggestions_)
1151 return; 1217 return;
1152 1218
1153 // The page is trying to hide itself. Hide explicitly (i.e., don't use 1219 // The page is trying to hide itself. Hide explicitly (i.e., don't use
1154 // HideLoader()) so that it can change its mind. 1220 // HideOverlay()) so that it can change its mind.
1155 if (height == 0) { 1221 if (height == 0) {
1156 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); 1222 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
1157 return; 1223 return;
1158 } 1224 }
1159 1225
1160 // If the preview is being shown for the first time since the user started 1226 // If the preview is being shown for the first time since the user started
1161 // typing, record a histogram value. 1227 // typing, record a histogram value.
1162 if (!first_interaction_time_.is_null() && model_.mode().is_default()) { 1228 if (!first_interaction_time_.is_null() && model_.mode().is_default()) {
1163 base::TimeDelta delta = base::Time::Now() - first_interaction_time_; 1229 base::TimeDelta delta = base::Time::Now() - first_interaction_time_;
1164 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta); 1230 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta);
1165 } 1231 }
1166 1232
1167 // Show at 100% height except in the following cases: 1233 // Show at 100% height except in the following cases:
1168 // - The local omnibox popup is being loaded. 1234 // - The local omnibox popup is being loaded.
1169 // - Instant is disabled. The page needs to be able to show only a dropdown. 1235 // - Instant is disabled. The page needs to be able to show only a dropdown.
1170 // - The page wants to show custom NTP content. 1236 // - The page wants to show custom NTP content.
1171 // - The page is over a website other than search or an NTP, and is not 1237 // - The page is over a website other than search or an NTP, and is not
1172 // already showing at 100% height. 1238 // already showing at 100% height.
1173 if (loader_->IsUsingLocalPreview() || !instant_enabled_ || 1239 if (overlay_->IsUsingLocalPreview() || !instant_enabled_ ||
1174 reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT || 1240 reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT ||
1175 (search_mode_.is_origin_default() && !IsFullHeight(model_))) 1241 (search_mode_.is_origin_default() && !IsFullHeight(model_)))
1176 model_.SetPreviewState(search_mode_, height, units); 1242 model_.SetPreviewState(search_mode_, height, units);
1177 else 1243 else
1178 model_.SetPreviewState(search_mode_, 100, INSTANT_SIZE_PERCENT); 1244 model_.SetPreviewState(search_mode_, 100, INSTANT_SIZE_PERCENT);
1179 1245
1180 // If the user clicked on a query suggestion, also go ahead and commit the 1246 // If the user clicked on a query suggestion, also go ahead and commit the
1181 // overlay. This is necessary because if the overlay was partially visible 1247 // overlay. This is necessary because if the overlay was partially visible
1182 // when the suggestion was clicked, the click itself would not commit the 1248 // when the suggestion was clicked, the click itself would not commit the
1183 // overlay (because we're not full height). 1249 // overlay (because we're not full height).
1184 if (reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) 1250 if (reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION)
1185 CommitIfPossible(INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION); 1251 CommitIfPossible(INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION);
1186 } 1252 }
1187 1253
1188 void InstantController::SendPopupBoundsToPage() { 1254 void InstantController::SendPopupBoundsToPage() {
1189 if (last_popup_bounds_ == popup_bounds_ || !loader_ || 1255 if (last_popup_bounds_ == popup_bounds_ || !overlay_ ||
1190 loader_->is_pointer_down_from_activate()) 1256 overlay_->is_pointer_down_from_activate())
1191 return; 1257 return;
1192 1258
1193 last_popup_bounds_ = popup_bounds_; 1259 last_popup_bounds_ = popup_bounds_;
1194 gfx::Rect preview_bounds = browser_->GetInstantBounds(); 1260 gfx::Rect preview_bounds = browser_->GetInstantBounds();
1195 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds); 1261 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds);
1196 1262
1197 // Translate into window coordinates. 1263 // Translate into window coordinates.
1198 if (!intersection.IsEmpty()) { 1264 if (!intersection.IsEmpty()) {
1199 intersection.Offset(-preview_bounds.origin().x(), 1265 intersection.Offset(-preview_bounds.origin().x(),
1200 -preview_bounds.origin().y()); 1266 -preview_bounds.origin().y());
1201 } 1267 }
1202 1268
1203 // In the current Chrome UI, these must always be true so they sanity check 1269 // In the current Chrome UI, these must always be true so they sanity check
1204 // the above operations. In a future UI, these may be removed or adjusted. 1270 // the above operations. In a future UI, these may be removed or adjusted.
1205 // There is no point in sanity-checking |intersection.y()| because the omnibox 1271 // There is no point in sanity-checking |intersection.y()| because the omnibox
1206 // can be placed anywhere vertically relative to the preview (for example, in 1272 // can be placed anywhere vertically relative to the preview (for example, in
1207 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds). 1273 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds).
1208 DCHECK_LE(0, intersection.x()); 1274 DCHECK_LE(0, intersection.x());
1209 DCHECK_LE(0, intersection.width()); 1275 DCHECK_LE(0, intersection.width());
1210 DCHECK_LE(0, intersection.height()); 1276 DCHECK_LE(0, intersection.height());
1211 1277
1212 loader_->SetPopupBounds(intersection); 1278 overlay_->SetPopupBounds(intersection);
1213 } 1279 }
1214 1280
1215 bool InstantController::GetInstantURL(const content::WebContents* active_tab, 1281 bool InstantController::GetInstantURL(Profile* profile,
1216 bool ignore_blacklist, 1282 bool ignore_blacklist,
1217 std::string* instant_url) const { 1283 std::string* instant_url) const {
1218 DCHECK(active_tab); 1284 DCHECK(profile);
1219 instant_url->clear(); 1285 instant_url->clear();
1220 1286
1221 if (extended_enabled_ && use_local_preview_only_) { 1287 if (extended_enabled_ && use_local_preview_only_) {
1222 *instant_url = kLocalOmniboxPopupURL; 1288 *instant_url = kLocalOmniboxPopupURL;
1223 return true; 1289 return true;
1224 } 1290 }
1225 1291
1226 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( 1292 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
1227 Profile::FromBrowserContext(active_tab->GetBrowserContext()))-> 1293 profile)->GetDefaultSearchProvider();
1228 GetDefaultSearchProvider();
1229 1294
1230 if (!template_url) { 1295 if (!template_url) {
1231 LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL"); 1296 LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL");
1232 return false; 1297 return false;
1233 } 1298 }
1234 1299
1235 CommandLine* command_line = CommandLine::ForCurrentProcess(); 1300 CommandLine* command_line = CommandLine::ForCurrentProcess();
1236 if (command_line->HasSwitch(switches::kInstantURL)) 1301 if (command_line->HasSwitch(switches::kInstantURL))
1237 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL); 1302 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL);
1238 1303
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST); 1364 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST);
1300 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( 1365 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
1301 "GetInstantURL: Instant URL blacklisted: url=%s", 1366 "GetInstantURL: Instant URL blacklisted: url=%s",
1302 instant_url->c_str())); 1367 instant_url->c_str()));
1303 return false; 1368 return false;
1304 } 1369 }
1305 } 1370 }
1306 1371
1307 return true; 1372 return true;
1308 } 1373 }
1374
1375 void InstantController::BlacklistAndResetNTP() {
1376 ++blacklisted_urls_[ntp_->instant_url()];
1377 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
1378 ignore_result(ntp_->ReleaseContents());
1379 MessageLoop::current()->DeleteSoon(FROM_HERE, ntp_.release());
1380 ResetNTP();
1381 }
1382
1383 void InstantController::BlacklistAndResetOverlay() {
1384 ++blacklisted_urls_[overlay_->instant_url()];
1385 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
1386 HideInternal();
1387 ignore_result(overlay_->ReleaseContents());
1388 MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release());
1389 EnsureOverlayIsCurrent(false);
1390 }
1391
1392 void InstantController::RemoveFromBlacklist(const std::string& url) {
1393 if (blacklisted_urls_.erase(url)) {
1394 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST);
1395 }
1396 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698