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 "chrome/browser/autocomplete/autocomplete_match.h" | 10 #include "chrome/browser/autocomplete/autocomplete_match.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
45 | 45 |
46 // An artificial delay (in milliseconds) we introduce before telling the Instant | 46 // An artificial delay (in milliseconds) we introduce before telling the Instant |
47 // page about the new omnibox bounds, in cases where the bounds shrink. This is | 47 // page about the new omnibox bounds, in cases where the bounds shrink. This is |
48 // to avoid the page jumping up/down very fast in response to bounds changes. | 48 // to avoid the page jumping up/down very fast in response to bounds changes. |
49 const int kUpdateBoundsDelayMS = 1000; | 49 const int kUpdateBoundsDelayMS = 1000; |
50 | 50 |
51 // The maximum number of times we'll load a non-Instant-supporting search engine | 51 // The maximum number of times we'll load a non-Instant-supporting search engine |
52 // before we give up and blacklist it for the rest of the browsing session. | 52 // before we give up and blacklist it for the rest of the browsing session. |
53 const int kMaxInstantSupportFailures = 10; | 53 const int kMaxInstantSupportFailures = 10; |
54 | 54 |
55 // If an Instant page has not been used in this many milliseconds, it is | |
sreeram
2012/08/24 21:06:25
this -> these
Shishir
2012/08/24 22:17:39
Done.
| |
56 // reloaded so that the page does not become stale. | |
57 const int kStaleLoaderTimeoutMS = 3 * 3600 * 1000; | |
58 | |
55 std::string ModeToString(InstantController::Mode mode) { | 59 std::string ModeToString(InstantController::Mode mode) { |
56 switch (mode) { | 60 switch (mode) { |
57 case InstantController::INSTANT: return "_Instant"; | 61 case InstantController::INSTANT: return "_Instant"; |
58 case InstantController::SUGGEST: return "_Suggest"; | 62 case InstantController::SUGGEST: return "_Suggest"; |
59 case InstantController::HIDDEN: return "_Hidden"; | 63 case InstantController::HIDDEN: return "_Hidden"; |
60 case InstantController::SILENT: return "_Silent"; | 64 case InstantController::SILENT: return "_Silent"; |
61 } | 65 } |
62 | 66 |
63 NOTREACHED(); | 67 NOTREACHED(); |
64 return std::string(); | 68 return std::string(); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 return !IsOutOfDate() && GetPreviewContents() && loader_->supports_instant(); | 261 return !IsOutOfDate() && GetPreviewContents() && loader_->supports_instant(); |
258 } | 262 } |
259 | 263 |
260 TabContents* InstantController::CommitCurrentPreview(InstantCommitType type) { | 264 TabContents* InstantController::CommitCurrentPreview(InstantCommitType type) { |
261 const TabContents* active_tab = delegate_->GetActiveTabContents(); | 265 const TabContents* active_tab = delegate_->GetActiveTabContents(); |
262 TabContents* preview = ReleasePreviewContents(type); | 266 TabContents* preview = ReleasePreviewContents(type); |
263 AddSessionStorageHistogram(mode_, active_tab, preview); | 267 AddSessionStorageHistogram(mode_, active_tab, preview); |
264 preview->web_contents()->GetController().CopyStateFromAndPrune( | 268 preview->web_contents()->GetController().CopyStateFromAndPrune( |
265 &active_tab->web_contents()->GetController()); | 269 &active_tab->web_contents()->GetController()); |
266 delegate_->CommitInstant(preview); | 270 delegate_->CommitInstant(preview); |
271 | |
272 // Try to create another loader immediately so that it is ready for the next | |
273 // user interaction. | |
274 CreateDefaultLoader(); | |
275 | |
267 return preview; | 276 return preview; |
268 } | 277 } |
269 | 278 |
270 TabContents* InstantController::ReleasePreviewContents(InstantCommitType type) { | 279 TabContents* InstantController::ReleasePreviewContents(InstantCommitType type) { |
271 TabContents* preview = loader_->ReleasePreviewContents(type, last_full_text_); | 280 TabContents* preview = loader_->ReleasePreviewContents(type, last_full_text_); |
272 | 281 |
273 // If the preview page has navigated since the last Update(), we need to add | 282 // If the preview page has navigated since the last Update(), we need to add |
274 // the navigation to history ourselves. Else, the page will navigate after | 283 // the navigation to history ourselves. Else, the page will navigate after |
275 // commit, and it will be added to history in the usual manner. | 284 // commit, and it will be added to history in the usual manner. |
276 scoped_refptr<history::HistoryAddPageArgs> last_navigation = | 285 scoped_refptr<history::HistoryAddPageArgs> last_navigation = |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 // still be on the stack. So, schedule a destruction for later. | 326 // still be on the stack. So, schedule a destruction for later. |
318 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | 327 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
319 | 328 |
320 // This call is here to hide the preview and reset view state. It won't | 329 // This call is here to hide the preview and reset view state. It won't |
321 // actually delete |loader_| because it was just released to DeleteSoon(). | 330 // actually delete |loader_| because it was just released to DeleteSoon(). |
322 DeleteLoader(); | 331 DeleteLoader(); |
323 | 332 |
324 return preview; | 333 return preview; |
325 } | 334 } |
326 | 335 |
327 // TODO(sreeram): Since we never delete the loader except when committing | |
328 // Instant, the loader may have a very stale page. Reload it when stale. | |
329 void InstantController::OnAutocompleteLostFocus( | 336 void InstantController::OnAutocompleteLostFocus( |
330 gfx::NativeView view_gaining_focus) { | 337 gfx::NativeView view_gaining_focus) { |
331 DCHECK(!is_showing_ || GetPreviewContents()); | 338 DCHECK(!is_showing_ || GetPreviewContents()); |
332 | 339 |
333 // If the preview is not showing, nothing to do. | 340 // If there is no preview, nothing to do. |
334 if (!is_showing_ || !GetPreviewContents()) | 341 if (!GetPreviewContents()) |
335 return; | 342 return; |
336 | 343 |
344 // If the preview is not showing, only need to check for loader staleness. | |
345 if (!is_showing_) { | |
346 MaybeOnStaleLoader(); | |
347 return; | |
348 } | |
349 | |
337 #if defined(OS_MACOSX) | 350 #if defined(OS_MACOSX) |
338 if (!loader_->IsPointerDownFromActivate()) | 351 if (!loader_->IsPointerDownFromActivate()) { |
339 Hide(); | 352 Hide(); |
353 MaybeOnStaleLoader(); | |
354 } | |
340 #else | 355 #else |
341 content::RenderWidgetHostView* rwhv = | 356 content::RenderWidgetHostView* rwhv = |
342 GetPreviewContents()->web_contents()->GetRenderWidgetHostView(); | 357 GetPreviewContents()->web_contents()->GetRenderWidgetHostView(); |
343 if (!view_gaining_focus || !rwhv) { | 358 if (!view_gaining_focus || !rwhv) { |
344 Hide(); | 359 Hide(); |
360 MaybeOnStaleLoader(); | |
345 return; | 361 return; |
346 } | 362 } |
347 | 363 |
348 #if defined(TOOLKIT_VIEWS) | 364 #if defined(TOOLKIT_VIEWS) |
349 // For views the top level widget is always focused. If the focus change | 365 // For views the top level widget is always focused. If the focus change |
350 // originated in views determine the child Widget from the view that is being | 366 // originated in views determine the child Widget from the view that is being |
351 // focused. | 367 // focused. |
352 views::Widget* widget = | 368 views::Widget* widget = |
353 views::Widget::GetWidgetForNativeView(view_gaining_focus); | 369 views::Widget::GetWidgetForNativeView(view_gaining_focus); |
354 if (widget) { | 370 if (widget) { |
355 views::FocusManager* focus_manager = widget->GetFocusManager(); | 371 views::FocusManager* focus_manager = widget->GetFocusManager(); |
356 if (focus_manager && focus_manager->is_changing_focus() && | 372 if (focus_manager && focus_manager->is_changing_focus() && |
357 focus_manager->GetFocusedView() && | 373 focus_manager->GetFocusedView() && |
358 focus_manager->GetFocusedView()->GetWidget()) { | 374 focus_manager->GetFocusedView()->GetWidget()) { |
359 view_gaining_focus = | 375 view_gaining_focus = |
360 focus_manager->GetFocusedView()->GetWidget()->GetNativeView(); | 376 focus_manager->GetFocusedView()->GetWidget()->GetNativeView(); |
361 } | 377 } |
362 } | 378 } |
363 #endif | 379 #endif |
364 | 380 |
365 gfx::NativeView tab_view = | 381 gfx::NativeView tab_view = |
366 GetPreviewContents()->web_contents()->GetNativeView(); | 382 GetPreviewContents()->web_contents()->GetNativeView(); |
367 | 383 |
368 // Focus is going to the renderer. | 384 // Focus is going to the renderer. |
369 if (rwhv->GetNativeView() == view_gaining_focus || | 385 if (rwhv->GetNativeView() == view_gaining_focus || |
370 tab_view == view_gaining_focus) { | 386 tab_view == view_gaining_focus) { |
371 | 387 |
372 // If the mouse is not down, focus is not going to the renderer. Someone | 388 // If the mouse is not down, focus is not going to the renderer. Someone |
373 // else moved focus and we shouldn't commit. | 389 // else moved focus and we shouldn't commit. |
374 if (!loader_->IsPointerDownFromActivate()) | 390 if (!loader_->IsPointerDownFromActivate()) { |
375 Hide(); | 391 Hide(); |
392 MaybeOnStaleLoader(); | |
393 } | |
376 | 394 |
377 return; | 395 return; |
378 } | 396 } |
379 | 397 |
380 // Walk up the view hierarchy. If the view gaining focus is a subview of the | 398 // Walk up the view hierarchy. If the view gaining focus is a subview of the |
381 // WebContents view (such as a windowed plugin or http auth dialog), we want | 399 // WebContents view (such as a windowed plugin or http auth dialog), we want |
382 // to keep the preview contents. Otherwise, focus has gone somewhere else, | 400 // to keep the preview contents. Otherwise, focus has gone somewhere else, |
383 // such as the JS inspector, and we want to cancel the preview. | 401 // such as the JS inspector, and we want to cancel the preview. |
384 gfx::NativeView view_gaining_focus_ancestor = view_gaining_focus; | 402 gfx::NativeView view_gaining_focus_ancestor = view_gaining_focus; |
385 while (view_gaining_focus_ancestor && | 403 while (view_gaining_focus_ancestor && |
386 view_gaining_focus_ancestor != tab_view) { | 404 view_gaining_focus_ancestor != tab_view) { |
387 view_gaining_focus_ancestor = | 405 view_gaining_focus_ancestor = |
388 platform_util::GetParent(view_gaining_focus_ancestor); | 406 platform_util::GetParent(view_gaining_focus_ancestor); |
389 } | 407 } |
390 | 408 |
391 if (view_gaining_focus_ancestor) { | 409 if (view_gaining_focus_ancestor) { |
392 CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST); | 410 CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST); |
393 return; | 411 return; |
394 } | 412 } |
395 | 413 |
396 Hide(); | 414 Hide(); |
415 MaybeOnStaleLoader(); | |
397 #endif | 416 #endif |
398 } | 417 } |
399 | 418 |
400 void InstantController::OnAutocompleteGotFocus() { | 419 void InstantController::OnAutocompleteGotFocus() { |
401 const TabContents* active_tab = delegate_->GetActiveTabContents(); | 420 CreateDefaultLoader(); |
402 | |
403 // We could get here with no active tab if the Browser is closing. | |
404 if (!active_tab) | |
405 return; | |
406 | |
407 // Since we don't have any autocomplete match to work with, we'll just use | |
408 // the default search provider's Instant URL. | |
409 const TemplateURL* template_url = | |
410 TemplateURLServiceFactory::GetForProfile(active_tab->profile())-> | |
411 GetDefaultSearchProvider(); | |
412 | |
413 std::string instant_url; | |
414 if (!GetInstantURL(template_url, &instant_url)) | |
415 return; | |
416 | |
417 ResetLoader(instant_url, active_tab); | |
418 } | 421 } |
419 | 422 |
420 bool InstantController::commit_on_pointer_release() const { | 423 bool InstantController::commit_on_pointer_release() const { |
421 return GetPreviewContents() && loader_->IsPointerDownFromActivate(); | 424 return GetPreviewContents() && loader_->IsPointerDownFromActivate(); |
422 } | 425 } |
423 | 426 |
424 void InstantController::SetSuggestions( | 427 void InstantController::SetSuggestions( |
425 InstantLoader* loader, | 428 InstantLoader* loader, |
426 const std::vector<InstantSuggestion>& suggestions) { | 429 const std::vector<InstantSuggestion>& suggestions) { |
427 DCHECK_EQ(loader_.get(), loader); | 430 DCHECK_EQ(loader_.get(), loader); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 delegate_->InstantPreviewFocused(); | 508 delegate_->InstantPreviewFocused(); |
506 #endif | 509 #endif |
507 } | 510 } |
508 | 511 |
509 void InstantController::ResetLoader(const std::string& instant_url, | 512 void InstantController::ResetLoader(const std::string& instant_url, |
510 const TabContents* active_tab) { | 513 const TabContents* active_tab) { |
511 if (GetPreviewContents() && loader_->instant_url() != instant_url) | 514 if (GetPreviewContents() && loader_->instant_url() != instant_url) |
512 DeleteLoader(); | 515 DeleteLoader(); |
513 | 516 |
514 if (!GetPreviewContents()) { | 517 if (!GetPreviewContents()) { |
518 DCHECK(!loader_.get()); | |
515 loader_.reset(new InstantLoader(this, instant_url, active_tab)); | 519 loader_.reset(new InstantLoader(this, instant_url, active_tab)); |
516 loader_->Init(); | 520 loader_->Init(); |
517 AddPreviewUsageForHistogram(mode_, PREVIEW_CREATED); | 521 AddPreviewUsageForHistogram(mode_, PREVIEW_CREATED); |
522 | |
523 // Reset the loader timer. | |
524 stale_loader_timer_.Stop(); | |
525 stale_loader_timer_.Start( | |
526 FROM_HERE, | |
527 base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this, | |
528 &InstantController::OnStaleLoader); | |
518 } | 529 } |
519 } | 530 } |
520 | 531 |
532 void InstantController::CreateDefaultLoader() { | |
533 const TabContents* active_tab = delegate_->GetActiveTabContents(); | |
534 | |
535 // We could get here with no active tab if the Browser is closing. | |
536 if (!active_tab) | |
537 return; | |
538 | |
539 const TemplateURL* template_url = | |
540 TemplateURLServiceFactory::GetForProfile(active_tab->profile())-> | |
541 GetDefaultSearchProvider(); | |
542 std::string instant_url; | |
543 if (!GetInstantURL(template_url, &instant_url)) | |
544 return; | |
545 | |
546 ResetLoader(instant_url, active_tab); | |
547 } | |
548 | |
549 void InstantController::OnStaleLoader() { | |
550 // If the loader is showing, do not delete it. It will get deleted the next | |
551 // time the autocomplete looses focus. | |
sreeram
2012/08/24 21:06:25
looses -> loses
Shishir
2012/08/24 22:17:39
Done.
| |
552 if (is_showing_) | |
553 return; | |
554 | |
555 DeleteLoader(); | |
556 CreateDefaultLoader(); | |
557 } | |
558 | |
559 void InstantController::MaybeOnStaleLoader() { | |
560 if (!stale_loader_timer_.IsRunning()) | |
561 OnStaleLoader(); | |
562 } | |
563 | |
521 void InstantController::DeleteLoader() { | 564 void InstantController::DeleteLoader() { |
522 Hide(); | 565 Hide(); |
523 last_full_text_.clear(); | 566 last_full_text_.clear(); |
524 last_user_text_.clear(); | 567 last_user_text_.clear(); |
525 last_verbatim_ = false; | 568 last_verbatim_ = false; |
526 last_suggestion_ = InstantSuggestion(); | 569 last_suggestion_ = InstantSuggestion(); |
527 last_transition_type_ = content::PAGE_TRANSITION_LINK; | 570 last_transition_type_ = content::PAGE_TRANSITION_LINK; |
528 last_omnibox_bounds_ = gfx::Rect(); | 571 last_omnibox_bounds_ = gfx::Rect(); |
529 url_for_history_ = GURL(); | 572 url_for_history_ = GURL(); |
530 if (GetPreviewContents()) | 573 if (GetPreviewContents()) |
531 AddPreviewUsageForHistogram(mode_, PREVIEW_DELETED); | 574 AddPreviewUsageForHistogram(mode_, PREVIEW_DELETED); |
575 stale_loader_timer_.Stop(); | |
sreeram
2012/08/24 21:06:25
Don't do this. Consider this sequence of events:
1
Shishir
2012/08/24 22:17:39
Removed.
I think we need to handle the doenst sup
| |
532 loader_.reset(); | 576 loader_.reset(); |
533 } | 577 } |
534 | 578 |
535 void InstantController::Show() { | 579 void InstantController::Show() { |
536 if (!is_showing_) { | 580 if (!is_showing_) { |
537 is_showing_ = true; | 581 is_showing_ = true; |
538 delegate_->ShowInstant(); | 582 delegate_->ShowInstant(); |
539 AddPreviewUsageForHistogram(mode_, PREVIEW_SHOWED); | 583 AddPreviewUsageForHistogram(mode_, PREVIEW_SHOWED); |
540 } | 584 } |
541 } | 585 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
594 return false; | 638 return false; |
595 } | 639 } |
596 | 640 |
597 return true; | 641 return true; |
598 } | 642 } |
599 | 643 |
600 bool InstantController::IsOutOfDate() const { | 644 bool InstantController::IsOutOfDate() const { |
601 return !last_active_tab_ || | 645 return !last_active_tab_ || |
602 last_active_tab_ != delegate_->GetActiveTabContents(); | 646 last_active_tab_ != delegate_->GetActiveTabContents(); |
603 } | 647 } |
OLD | NEW |