Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/instant/instant_controller.h" | 5 #include "chrome/browser/instant/instant_controller.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/i18n/case_conversion.h" | 8 #include "base/i18n/case_conversion.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "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 |