| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/tab_contents/match_preview.h" | 5 #include "chrome/browser/tab_contents/match_preview.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/string_number_conversions.h" |
| 10 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 11 #include "chrome/browser/autocomplete/autocomplete.h" | 12 #include "chrome/browser/autocomplete/autocomplete.h" |
| 12 #include "chrome/browser/favicon_service.h" | 13 #include "chrome/browser/favicon_service.h" |
| 13 #include "chrome/browser/history/history_marshaling.h" | 14 #include "chrome/browser/history/history_marshaling.h" |
| 14 #include "chrome/browser/profile.h" | 15 #include "chrome/browser/profile.h" |
| 15 #include "chrome/browser/renderer_host/render_view_host.h" | 16 #include "chrome/browser/renderer_host/render_view_host.h" |
| 16 #include "chrome/browser/renderer_host/render_widget_host.h" | 17 #include "chrome/browser/renderer_host/render_widget_host.h" |
| 17 #include "chrome/browser/renderer_host/render_widget_host_view.h" | 18 #include "chrome/browser/renderer_host/render_widget_host_view.h" |
| 18 #include "chrome/browser/search_engines/template_url.h" | 19 #include "chrome/browser/search_engines/template_url.h" |
| 19 #include "chrome/browser/search_engines/template_url_model.h" | 20 #include "chrome/browser/search_engines/template_url_model.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 30 #include "chrome/common/page_transition_types.h" | 31 #include "chrome/common/page_transition_types.h" |
| 31 #include "chrome/common/render_messages.h" | 32 #include "chrome/common/render_messages.h" |
| 32 #include "chrome/common/renderer_preferences.h" | 33 #include "chrome/common/renderer_preferences.h" |
| 33 #include "gfx/codec/png_codec.h" | 34 #include "gfx/codec/png_codec.h" |
| 34 #include "ipc/ipc_message.h" | 35 #include "ipc/ipc_message.h" |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 | 38 |
| 38 const char kUserInputScript[] = | 39 const char kUserInputScript[] = |
| 39 "if (window.chrome.userInput) window.chrome.userInput(\"$1\");"; | 40 "if (window.chrome.userInput) window.chrome.userInput(\"$1\");"; |
| 41 const char kUserDoneScript[] = |
| 42 "if (window.chrome.userWantsQuery) window.chrome.userWantsQuery(\"$1\");"; |
| 43 const char kSetOmniboxBoundsScript[] = |
| 44 "if (window.chrome.setOmniboxDimensions) " |
| 45 "window.chrome.setOmniboxDimensions($1, $2, $3, $4);"; |
| 40 | 46 |
| 41 // Sends the user input script to |tab_contents|. |text| is the text the user | 47 // Sends the user input script to |tab_contents|. |text| is the text the user |
| 42 // input into the omnibox. | 48 // input into the omnibox. |
| 43 void SendUserInputScript(TabContents* tab_contents, | 49 void SendUserInputScript(TabContents* tab_contents, |
| 44 const string16& text, | 50 const string16& text, |
| 45 bool done) { | 51 bool done) { |
| 46 // TODO: support done. | |
| 47 string16 escaped_text(text); | 52 string16 escaped_text(text); |
| 48 ReplaceSubstringsAfterOffset(&escaped_text, 0L, ASCIIToUTF16("\""), | 53 ReplaceSubstringsAfterOffset(&escaped_text, 0L, ASCIIToUTF16("\""), |
| 49 ASCIIToUTF16("\\\"")); | 54 ASCIIToUTF16("\\\"")); |
| 50 string16 script = ReplaceStringPlaceholders(ASCIIToUTF16(kUserInputScript), | 55 string16 script = ReplaceStringPlaceholders( |
| 51 escaped_text, NULL); | 56 ASCIIToUTF16(done ? kUserDoneScript : kUserInputScript), |
| 57 escaped_text, |
| 58 NULL); |
| 52 tab_contents->render_view_host()->ExecuteJavascriptInWebFrame( | 59 tab_contents->render_view_host()->ExecuteJavascriptInWebFrame( |
| 53 std::wstring(), | 60 std::wstring(), |
| 54 UTF16ToWide(script)); | 61 UTF16ToWide(script)); |
| 62 } |
| 63 |
| 64 // Sends the script for setting the bounds of the omnibox to |tab_contents|. |
| 65 void SendOmniboxBoundsScript(TabContents* tab_contents, |
| 66 const gfx::Rect& bounds) { |
| 67 std::vector<string16> bounds_vector; |
| 68 bounds_vector.push_back(base::IntToString16(bounds.x())); |
| 69 bounds_vector.push_back(base::IntToString16(bounds.y())); |
| 70 bounds_vector.push_back(base::IntToString16(bounds.width())); |
| 71 bounds_vector.push_back(base::IntToString16(bounds.height())); |
| 72 string16 script = ReplaceStringPlaceholders( |
| 73 ASCIIToUTF16(kSetOmniboxBoundsScript), |
| 74 bounds_vector, |
| 75 NULL); |
| 76 tab_contents->render_view_host()->ExecuteJavascriptInWebFrame( |
| 77 std::wstring(), |
| 78 UTF16ToWide(script)); |
| 55 } | 79 } |
| 56 | 80 |
| 57 } // namespace | 81 } // namespace |
| 58 | 82 |
| 59 // FrameLoadObserver is responsible for waiting for the TabContents to finish | 83 // FrameLoadObserver is responsible for waiting for the TabContents to finish |
| 60 // loading and when done sending the necessary script down to the page. | 84 // loading and when done sending the necessary script down to the page. |
| 61 class MatchPreview::FrameLoadObserver : public NotificationObserver { | 85 class MatchPreview::FrameLoadObserver : public NotificationObserver { |
| 62 public: | 86 public: |
| 63 FrameLoadObserver(MatchPreview* match_preview, const string16& text) | 87 FrameLoadObserver(MatchPreview* match_preview, const string16& text) |
| 64 : match_preview_(match_preview), | 88 : match_preview_(match_preview), |
| (...skipping 24 matching lines...) Expand all Loading... |
| 89 switch (type.value) { | 113 switch (type.value) { |
| 90 case NotificationType::LOAD_COMPLETED_MAIN_FRAME: { | 114 case NotificationType::LOAD_COMPLETED_MAIN_FRAME: { |
| 91 int page_id = *(Details<int>(details).ptr()); | 115 int page_id = *(Details<int>(details).ptr()); |
| 92 NavigationEntry* active_entry = | 116 NavigationEntry* active_entry = |
| 93 tab_contents_->controller().GetActiveEntry(); | 117 tab_contents_->controller().GetActiveEntry(); |
| 94 if (!active_entry || active_entry->page_id() != page_id || | 118 if (!active_entry || active_entry->page_id() != page_id || |
| 95 active_entry->unique_id() != unique_id_) { | 119 active_entry->unique_id() != unique_id_) { |
| 96 return; | 120 return; |
| 97 } | 121 } |
| 98 | 122 |
| 123 if (match_preview_) { |
| 124 gfx::Rect bounds = match_preview_->GetOmniboxBoundsInTermsOfPreview(); |
| 125 if (!bounds.IsEmpty()) |
| 126 SendOmniboxBoundsScript(tab_contents_, bounds); |
| 127 } |
| 128 |
| 99 SendUserInputScript(tab_contents_, text_, send_done_); | 129 SendUserInputScript(tab_contents_, text_, send_done_); |
| 100 | 130 |
| 101 if (match_preview_) | 131 if (match_preview_) |
| 102 match_preview_->PageFinishedLoading(); | 132 match_preview_->PageFinishedLoading(); |
| 103 | 133 |
| 104 delete this; | 134 delete this; |
| 105 return; | 135 return; |
| 106 } | 136 } |
| 107 | 137 |
| 108 case NotificationType::TAB_CONTENTS_DESTROYED: | 138 case NotificationType::TAB_CONTENTS_DESTROYED: |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 match.type == AutocompleteMatch::SEARCH_HISTORY || | 457 match.type == AutocompleteMatch::SEARCH_HISTORY || |
| 428 match.type == AutocompleteMatch::SEARCH_SUGGEST) { | 458 match.type == AutocompleteMatch::SEARCH_SUGGEST) { |
| 429 TemplateURLModel* model = tab_contents->profile()->GetTemplateURLModel(); | 459 TemplateURLModel* model = tab_contents->profile()->GetTemplateURLModel(); |
| 430 template_url = model ? model->GetDefaultSearchProvider() : NULL; | 460 template_url = model ? model->GetDefaultSearchProvider() : NULL; |
| 431 } | 461 } |
| 432 TemplateURLID template_url_id = template_url ? template_url->id() : 0; | 462 TemplateURLID template_url_id = template_url ? template_url->id() : 0; |
| 433 | 463 |
| 434 if (template_url && template_url->supports_instant() && | 464 if (template_url && template_url->supports_instant() && |
| 435 TemplateURL::SupportsReplacement(template_url)) { | 465 TemplateURL::SupportsReplacement(template_url)) { |
| 436 if (template_url_id == template_url_id_) { | 466 if (template_url_id == template_url_id_) { |
| 437 if (frame_load_observer_.get()) { | 467 if (is_waiting_for_load()) { |
| 438 // The page hasn't loaded yet. We'll send the script down when it does. | 468 // The page hasn't loaded yet. We'll send the script down when it does. |
| 439 frame_load_observer_->set_text(user_text_); | 469 frame_load_observer_->set_text(user_text_); |
| 440 return; | 470 return; |
| 441 } | 471 } |
| 442 SendUserInputScript(preview_contents_.get(), user_text_, false); | 472 SendUserInputScript(preview_contents_.get(), user_text_, false); |
| 443 if (complete_suggested_text_.size() > user_text_.size() && | 473 if (complete_suggested_text_.size() > user_text_.size() && |
| 444 !complete_suggested_text_.compare(0, user_text_.size(), user_text_)) { | 474 !complete_suggested_text_.compare(0, user_text_.size(), user_text_)) { |
| 445 *suggested_text = complete_suggested_text_.substr(user_text_.size()); | 475 *suggested_text = complete_suggested_text_.substr(user_text_.size()); |
| 446 } | 476 } |
| 447 } else { | 477 } else { |
| 448 // TODO: should we use a different url for instant? | 478 // TODO: should we use a different url for instant? |
| 449 GURL url = GURL(template_url->url()->ReplaceSearchTerms( | 479 GURL url = GURL(template_url->url()->ReplaceSearchTerms( |
| 450 *template_url, std::wstring(), | 480 *template_url, std::wstring(), |
| 451 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring())); | 481 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring())); |
| 452 // user_text_ is sent once the page finishes loading by FrameLoadObserver. | 482 // user_text_ is sent once the page finishes loading by FrameLoadObserver. |
| 453 preview_contents_->controller().LoadURL(url, GURL(), match.transition); | 483 preview_contents_->controller().LoadURL(url, GURL(), match.transition); |
| 454 frame_load_observer_.reset(new FrameLoadObserver(this, user_text_)); | 484 frame_load_observer_.reset(new FrameLoadObserver(this, user_text_)); |
| 455 } | 485 } |
| 456 } else { | 486 } else { |
| 487 template_url_id_ = 0; |
| 457 frame_load_observer_.reset(NULL); | 488 frame_load_observer_.reset(NULL); |
| 458 preview_contents_->controller().LoadURL(url_, GURL(), match.transition); | 489 preview_contents_->controller().LoadURL(url_, GURL(), match.transition); |
| 459 } | 490 } |
| 460 | 491 |
| 461 template_url_id_ = template_url_id; | 492 template_url_id_ = template_url_id; |
| 462 } | 493 } |
| 463 | 494 |
| 495 void MatchPreview::SetOmniboxBounds(const gfx::Rect& bounds) { |
| 496 if (omnibox_bounds_ == bounds) |
| 497 return; |
| 498 |
| 499 omnibox_bounds_ = bounds; |
| 500 if (preview_contents_.get() && is_showing_instant() && |
| 501 !is_waiting_for_load()) { |
| 502 SendOmniboxBoundsScript(preview_contents_.get(), |
| 503 GetOmniboxBoundsInTermsOfPreview()); |
| 504 } |
| 505 } |
| 506 |
| 464 void MatchPreview::DestroyPreviewContents() { | 507 void MatchPreview::DestroyPreviewContents() { |
| 465 delegate_->HideMatchPreview(); | 508 delegate_->HideMatchPreview(); |
| 466 delete ReleasePreviewContents(false); | 509 delete ReleasePreviewContents(false); |
| 467 } | 510 } |
| 468 | 511 |
| 469 void MatchPreview::CommitCurrentPreview() { | 512 void MatchPreview::CommitCurrentPreview() { |
| 470 DCHECK(preview_contents_.get()); | 513 DCHECK(preview_contents_.get()); |
| 471 delegate_->CommitMatchPreview(); | 514 delegate_->CommitMatchPreview(); |
| 472 } | 515 } |
| 473 | 516 |
| 474 TabContents* MatchPreview::ReleasePreviewContents(bool commit_history) { | 517 TabContents* MatchPreview::ReleasePreviewContents(bool commit_history) { |
| 518 omnibox_bounds_ = gfx::Rect(); |
| 475 template_url_id_ = 0; | 519 template_url_id_ = 0; |
| 476 url_ = GURL(); | 520 url_ = GURL(); |
| 477 user_text_.clear(); | 521 user_text_.clear(); |
| 478 complete_suggested_text_.clear(); | 522 complete_suggested_text_.clear(); |
| 479 if (frame_load_observer_.get()) { | 523 if (frame_load_observer_.get()) { |
| 480 frame_load_observer_->DetachFromPreview(); | 524 frame_load_observer_->DetachFromPreview(); |
| 481 // FrameLoadObserver will delete itself either when the TabContents is | 525 // FrameLoadObserver will delete itself either when the TabContents is |
| 482 // deleted, or when the page finishes loading. | 526 // deleted, or when the page finishes loading. |
| 483 FrameLoadObserver* unused ALLOW_UNUSED = frame_load_observer_.release(); | 527 FrameLoadObserver* unused ALLOW_UNUSED = frame_load_observer_.release(); |
| 484 } | 528 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 void MatchPreview::PreviewDidPaint() { | 563 void MatchPreview::PreviewDidPaint() { |
| 520 DCHECK(!is_active_); | 564 DCHECK(!is_active_); |
| 521 is_active_ = true; | 565 is_active_ = true; |
| 522 delegate_->ShowMatchPreview(); | 566 delegate_->ShowMatchPreview(); |
| 523 } | 567 } |
| 524 | 568 |
| 525 void MatchPreview::PageFinishedLoading() { | 569 void MatchPreview::PageFinishedLoading() { |
| 526 // FrameLoadObserver deletes itself after this call. | 570 // FrameLoadObserver deletes itself after this call. |
| 527 FrameLoadObserver* unused ALLOW_UNUSED = frame_load_observer_.release(); | 571 FrameLoadObserver* unused ALLOW_UNUSED = frame_load_observer_.release(); |
| 528 } | 572 } |
| 573 |
| 574 gfx::Rect MatchPreview::GetOmniboxBoundsInTermsOfPreview() { |
| 575 if (omnibox_bounds_.IsEmpty()) |
| 576 return omnibox_bounds_; |
| 577 |
| 578 gfx::Rect preview_bounds(delegate_->GetMatchPreviewBounds()); |
| 579 return gfx::Rect(omnibox_bounds_.x() - preview_bounds.x(), |
| 580 omnibox_bounds_.y() - preview_bounds.y(), |
| 581 omnibox_bounds_.width(), |
| 582 omnibox_bounds_.height()); |
| 583 } |
| OLD | NEW |