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 |