1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/find_bar_controller.h"
#include "build/build_config.h"
#include "chrome/browser/find_bar.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/common/notification_service.h"
#include "chrome/browser/tab_contents/web_contents.h"
FindBarController::FindBarController(FindBar* find_bar)
: find_bar_(find_bar), web_contents_(NULL) {
}
FindBarController::~FindBarController() {
// Web contents should have been NULLed out. If not, then we're leaking
// notification observers.
DCHECK(!web_contents_);
}
void FindBarController::Show() {
// Only show the animation if we're not already showing a find bar for the
// selected WebContents.
if (!web_contents_->find_ui_active()) {
web_contents_->set_find_ui_active(true);
find_bar_->Show();
}
find_bar_->SetFocusAndSelection();
}
void FindBarController::EndFindSession() {
find_bar_->Hide(true);
// |web_contents_| can be NULL for a number of reasons, for example when the
// tab is closing. We must guard against that case. See issue 8030.
if (web_contents_) {
// When we hide the window, we need to notify the renderer that we are done
// for now, so that we can abort the scoping effort and clear all the
// tickmarks and highlighting.
web_contents_->StopFinding(false); // false = don't clear selection on
// page.
find_bar_->ClearResults(web_contents_->find_result());
// When we get dismissed we restore the focus to where it belongs.
find_bar_->RestoreSavedFocus();
}
}
void FindBarController::ChangeWebContents(WebContents* contents) {
if (web_contents_) {
NotificationService::current()->RemoveObserver(
this, NotificationType::FIND_RESULT_AVAILABLE,
Source<TabContents>(web_contents_));
NotificationService::current()->RemoveObserver(
this, NotificationType::NAV_ENTRY_COMMITTED,
Source<NavigationController>(web_contents_->controller()));
find_bar_->StopAnimation();
}
web_contents_ = contents;
// Hide any visible find window from the previous tab if NULL |web_contents|
// is passed in or if the find UI is not active in the new tab.
if (find_bar_->IsFindBarVisible() &&
(!web_contents_ || !web_contents_->find_ui_active())) {
find_bar_->Hide(false);
}
if (web_contents_) {
NotificationService::current()->AddObserver(
this, NotificationType::FIND_RESULT_AVAILABLE,
Source<TabContents>(web_contents_));
NotificationService::current()->AddObserver(
this, NotificationType::NAV_ENTRY_COMMITTED,
Source<NavigationController>(web_contents_->controller()));
// Update the find bar with existing results and search text, regardless of
// whether or not the find bar is visible, so that if it's subsequently
// shown it is showing the right state for this tab. We update the find text
// _first_ since the FindBarView checks its emptiness to see if it should
// clear the result count display when there's nothing in the box.
find_bar_->SetFindText(web_contents_->find_text());
if (web_contents_->find_ui_active()) {
// A tab with a visible find bar just got selected and we need to show the
// find bar but without animation since it was already animated into its
// visible state. We also want to reset the window location so that
// we don't surprise the user by popping up to the left for no apparent
// reason.
gfx::Rect new_pos = find_bar_->GetDialogPosition(gfx::Rect());
find_bar_->SetDialogPosition(new_pos, false);
// Only modify focus and selection if Find is active, otherwise the Find
// Bar will interfere with user input.
find_bar_->SetFocusAndSelection();
}
find_bar_->UpdateUIForFindResult(web_contents_->find_result(),
web_contents_->find_text());
}
}
////////////////////////////////////////////////////////////////////////////////
// FindBarWin, NotificationObserver implementation:
void FindBarController::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
if (type == NotificationType::FIND_RESULT_AVAILABLE) {
// Don't update for notifications from TabContentses other than the one we
// are actively tracking.
if (Source<TabContents>(source).ptr() == web_contents_) {
find_bar_->UpdateUIForFindResult(web_contents_->find_result(),
web_contents_->find_text());
}
} else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
NavigationController* source_controller =
Source<NavigationController>(source).ptr();
if (source_controller == web_contents_->controller()) {
NavigationController::LoadCommittedDetails* commit_details =
Details<NavigationController::LoadCommittedDetails>(details).ptr();
PageTransition::Type transition_type =
commit_details->entry->transition_type();
// We hide the FindInPage window when the user navigates away, except on
// reload.
if (find_bar_->IsFindBarVisible() &&
PageTransition::StripQualifier(transition_type) !=
PageTransition::RELOAD) {
EndFindSession();
}
}
}
}
|