Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: chrome/browser/infobars/infobar_service.cc

Issue 22694006: Infobar system refactor. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/infobars/infobar_service.h" 5 #include "chrome/browser/infobars/infobar_service.h"
6 6
7 #include "chrome/browser/chrome_notification_types.h" 7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/infobars/infobar.h" 8 #include "chrome/browser/infobars/infobar.h"
9 #include "chrome/browser/infobars/infobar_delegate.h" 9 #include "chrome/browser/infobars/infobar_delegate.h"
10 #include "chrome/browser/infobars/insecure_content_infobar_delegate.h" 10 #include "chrome/browser/infobars/insecure_content_infobar_delegate.h"
11 #include "chrome/common/render_messages.h" 11 #include "chrome/common/render_messages.h"
12 #include "content/public/browser/navigation_controller.h" 12 #include "content/public/browser/navigation_controller.h"
13 #include "content/public/browser/notification_service.h" 13 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
15 15
16 16
17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InfoBarService); 17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InfoBarService);
18 18
19 InfoBarDelegate* InfoBarService::AddInfoBar( 19 InfoBar* InfoBarService::AddInfoBar(scoped_ptr<InfoBar> infobar) {
20 scoped_ptr<InfoBarDelegate> infobar) {
21 DCHECK(infobar); 20 DCHECK(infobar);
22 if (!infobars_enabled_) 21 if (!infobars_enabled_)
23 return NULL; 22 return NULL;
24 23
25 for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end(); 24 for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
26 ++i) { 25 ++i) {
27 if ((*i)->EqualsDelegate(infobar.get())) { 26 if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) {
28 DCHECK_NE(*i, infobar.get()); 27 DCHECK_NE((*i)->delegate(), infobar->delegate());
29 return NULL; 28 return NULL;
30 } 29 }
31 } 30 }
32 31
33 InfoBarDelegate* infobar_ptr = infobar.release(); 32 InfoBar* infobar_ptr = infobar.release();
34 infobars_.push_back(infobar_ptr); 33 infobars_.push_back(infobar_ptr);
35 // TODO(pkasting): Remove InfoBarService arg from delegate constructors and 34 infobar_ptr->SetOwner(this);
36 // instead use a setter from here.
37 35
38 // Add ourselves as an observer for navigations the first time a delegate is 36 // Add ourselves as an observer for navigations the first time a delegate is
39 // added. We use this notification to expire InfoBars that need to expire on 37 // added. We use this notification to expire InfoBars that need to expire on
40 // page transitions. We must do this before calling Notify() below; 38 // page transitions. We must do this before calling Notify() below;
41 // otherwise, if that call causes a call to RemoveInfoBar(), we'll try to 39 // otherwise, if that call causes a call to RemoveInfoBar(), we'll try to
42 // unregister for the NAV_ENTRY_COMMITTED notification, which we won't have 40 // unregister for the NAV_ENTRY_COMMITTED notification, which we won't have
43 // yet registered here, and we'll fail the "was registered" DCHECK in 41 // yet registered here, and we'll fail the "was registered" DCHECK in
44 // NotificationRegistrar::Remove(). 42 // NotificationRegistrar::Remove().
45 if (infobars_.size() == 1) { 43 if (infobars_.size() == 1) {
46 registrar_.Add( 44 registrar_.Add(
47 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 45 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
48 content::Source<content::NavigationController>( 46 content::Source<content::NavigationController>(
49 &web_contents()->GetController())); 47 &web_contents()->GetController()));
50 } 48 }
51 49
52 content::NotificationService::current()->Notify( 50 content::NotificationService::current()->Notify(
53 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, 51 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
54 content::Source<InfoBarService>(this), 52 content::Source<InfoBarService>(this),
55 content::Details<InfoBarAddedDetails>(infobar_ptr)); 53 content::Details<InfoBar::AddedDetails>(infobar_ptr));
56 return infobar_ptr; 54 return infobar_ptr;
57 } 55 }
58 56
59 void InfoBarService::RemoveInfoBar(InfoBarDelegate* infobar) { 57 void InfoBarService::RemoveInfoBar(InfoBar* infobar) {
60 RemoveInfoBarInternal(infobar, true); 58 RemoveInfoBarInternal(infobar, true);
61 } 59 }
62 60
63 InfoBarDelegate* InfoBarService::ReplaceInfoBar( 61 InfoBar* InfoBarService::ReplaceInfoBar(InfoBar* old_infobar,
64 InfoBarDelegate* old_infobar, 62 scoped_ptr<InfoBar> new_infobar) {
65 scoped_ptr<InfoBarDelegate> new_infobar) {
66 DCHECK(old_infobar); 63 DCHECK(old_infobar);
67 if (!infobars_enabled_) 64 if (!infobars_enabled_)
68 return AddInfoBar(new_infobar.Pass()); // Deletes the delegate. 65 return AddInfoBar(new_infobar.Pass()); // Deletes the infobar.
69 DCHECK(new_infobar); 66 DCHECK(new_infobar);
70 67
71 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), 68 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(),
72 old_infobar)); 69 old_infobar));
73 DCHECK(i != infobars_.end()); 70 DCHECK(i != infobars_.end());
74 71
75 InfoBarDelegate* new_infobar_ptr = new_infobar.release(); 72 InfoBar* new_infobar_ptr = new_infobar.release();
76 i = infobars_.insert(i, new_infobar_ptr); 73 i = infobars_.insert(i, new_infobar_ptr);
77 InfoBarReplacedDetails replaced_details(old_infobar, new_infobar_ptr); 74 new_infobar_ptr->SetOwner(this);
75 InfoBar::ReplacedDetails replaced_details(old_infobar, new_infobar_ptr);
78 76
79 // Remove the old infobar before notifying, so that if any observers call 77 // Remove the old infobar before notifying, so that if any observers call back
80 // back to AddInfoBar() or similar, we don't dupe-check against this infobar. 78 // to AddInfoBar() or similar, we don't dupe-check against this infobar.
81 infobars_.erase(++i); 79 infobars_.erase(++i);
82 80
83 old_infobar->clear_owner();
84 content::NotificationService::current()->Notify( 81 content::NotificationService::current()->Notify(
85 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED, 82 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
86 content::Source<InfoBarService>(this), 83 content::Source<InfoBarService>(this),
87 content::Details<InfoBarReplacedDetails>(&replaced_details)); 84 content::Details<InfoBar::ReplacedDetails>(&replaced_details));
85
86 old_infobar->CloseSoon();
88 return new_infobar_ptr; 87 return new_infobar_ptr;
89 } 88 }
90 89
91 InfoBarService::InfoBarService(content::WebContents* web_contents) 90 InfoBarService::InfoBarService(content::WebContents* web_contents)
92 : content::WebContentsObserver(web_contents), 91 : content::WebContentsObserver(web_contents),
93 infobars_enabled_(true) { 92 infobars_enabled_(true) {
94 DCHECK(web_contents); 93 DCHECK(web_contents);
95 registrar_.Add(this, 94 registrar_.Add(this,
96 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 95 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
97 content::Source<content::WebContents>(web_contents)); 96 content::Source<content::WebContents>(web_contents));
98 } 97 }
99 98
100 InfoBarService::~InfoBarService() { 99 InfoBarService::~InfoBarService() {
101 // Destroy all remaining InfoBars. It's important to not animate here so that 100 // Destroy all remaining InfoBars. It's important to not animate here so that
102 // we guarantee that we'll delete all delegates before we do anything else. 101 // we guarantee that we'll delete all delegates before we do anything else.
103 //
104 // TODO(pkasting): If there is no InfoBarContainer, this leaks all the
105 // InfoBarDelegates. This will be fixed once we call CloseSoon() directly on
106 // Infobars.
107 RemoveAllInfoBars(false); 102 RemoveAllInfoBars(false);
108 } 103 }
109 104
110 void InfoBarService::RenderProcessGone(base::TerminationStatus status) { 105 void InfoBarService::RenderProcessGone(base::TerminationStatus status) {
111 RemoveAllInfoBars(true); 106 RemoveAllInfoBars(true);
112 } 107 }
113 108
114 bool InfoBarService::OnMessageReceived(const IPC::Message& message) { 109 bool InfoBarService::OnMessageReceived(const IPC::Message& message) {
115 bool handled = true; 110 bool handled = true;
116 IPC_BEGIN_MESSAGE_MAP(InfoBarService, message) 111 IPC_BEGIN_MESSAGE_MAP(InfoBarService, message)
(...skipping 13 matching lines...) Expand all
130 DCHECK(&web_contents()->GetController() == 125 DCHECK(&web_contents()->GetController() ==
131 content::Source<content::NavigationController>(source).ptr()); 126 content::Source<content::NavigationController>(source).ptr());
132 127
133 content::LoadCommittedDetails& committed_details = 128 content::LoadCommittedDetails& committed_details =
134 *(content::Details<content::LoadCommittedDetails>(details).ptr()); 129 *(content::Details<content::LoadCommittedDetails>(details).ptr());
135 130
136 // NOTE: It is not safe to change the following code to count upwards or 131 // NOTE: It is not safe to change the following code to count upwards or
137 // use iterators, as the RemoveInfoBar() call synchronously modifies our 132 // use iterators, as the RemoveInfoBar() call synchronously modifies our
138 // delegate list. 133 // delegate list.
139 for (size_t i = infobars_.size(); i > 0; --i) { 134 for (size_t i = infobars_.size(); i > 0; --i) {
140 InfoBarDelegate* infobar = infobars_[i - 1]; 135 InfoBar* infobar = infobars_[i - 1];
141 if (infobar->ShouldExpire(committed_details)) 136 if (infobar->delegate()->ShouldExpire(committed_details))
142 RemoveInfoBar(infobar); 137 RemoveInfoBar(infobar);
143 } 138 }
144 139
145 return; 140 return;
146 } 141 }
147 142
148 DCHECK_EQ(type, content::NOTIFICATION_WEB_CONTENTS_DESTROYED); 143 DCHECK_EQ(type, content::NOTIFICATION_WEB_CONTENTS_DESTROYED);
149 // The WebContents is going away; be aggressively paranoid and delete 144 // The WebContents is going away; be aggressively paranoid and delete
150 // ourselves lest other parts of the system attempt to add infobars or use 145 // ourselves lest other parts of the system attempt to add infobars or use
151 // us otherwise during the destruction. 146 // us otherwise during the destruction.
152 DCHECK_EQ(web_contents(), 147 DCHECK_EQ(web_contents(),
153 content::Source<content::WebContents>(source).ptr()); 148 content::Source<content::WebContents>(source).ptr());
154 web_contents()->RemoveUserData(UserDataKey()); 149 web_contents()->RemoveUserData(UserDataKey());
155 // That was the equivalent of "delete this". This object is now destroyed; 150 // That was the equivalent of "delete this". This object is now destroyed;
156 // returning from this function is the only safe thing to do. 151 // returning from this function is the only safe thing to do.
157 return; 152 return;
158 } 153 }
159 154
160 void InfoBarService::RemoveInfoBarInternal(InfoBarDelegate* infobar, 155 void InfoBarService::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
161 bool animate) {
162 DCHECK(infobar); 156 DCHECK(infobar);
163 if (!infobars_enabled_) { 157 if (!infobars_enabled_) {
164 DCHECK(infobars_.empty()); 158 DCHECK(infobars_.empty());
165 return; 159 return;
166 } 160 }
167 161
168 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar)); 162 InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
169 DCHECK(i != infobars_.end()); 163 DCHECK(i != infobars_.end());
170 164
171 infobar->clear_owner();
172 // Remove the infobar before notifying, so that if any observers call back to 165 // Remove the infobar before notifying, so that if any observers call back to
173 // AddInfoBar() or similar, we don't dupe-check against this infobar. 166 // AddInfoBar() or similar, we don't dupe-check against this infobar.
174 infobars_.erase(i); 167 infobars_.erase(i);
175 168
176 // Remove ourselves as an observer if we are tracking no more InfoBars. We 169 // Remove ourselves as an observer if we are tracking no more InfoBars. We
177 // must do this before calling Notify() below; otherwise, if that call 170 // must do this before calling Notify() below; otherwise, if that call
178 // causes a call to AddInfoBar(), we'll try to register for the 171 // causes a call to AddInfoBar(), we'll try to register for the
179 // NAV_ENTRY_COMMITTED notification, which we won't have yet unregistered 172 // NAV_ENTRY_COMMITTED notification, which we won't have yet unregistered
180 // here, and we'll fail the "not already registered" DCHECK in 173 // here, and we'll fail the "not already registered" DCHECK in
181 // NotificationRegistrar::Add(). 174 // NotificationRegistrar::Add().
182 if (infobars_.empty()) { 175 if (infobars_.empty()) {
183 registrar_.Remove( 176 registrar_.Remove(
184 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 177 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
185 content::Source<content::NavigationController>( 178 content::Source<content::NavigationController>(
186 &web_contents()->GetController())); 179 &web_contents()->GetController()));
187 } 180 }
188 181
189 InfoBarRemovedDetails removed_details(infobar, animate); 182 // This notification must happen before the call to CloseSoon() below, since
183 // observers may want to access |infobar| and that call can delete it.
184 InfoBar::RemovedDetails removed_details(infobar, animate);
190 content::NotificationService::current()->Notify( 185 content::NotificationService::current()->Notify(
191 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, 186 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
192 content::Source<InfoBarService>(this), 187 content::Source<InfoBarService>(this),
193 content::Details<InfoBarRemovedDetails>(&removed_details)); 188 content::Details<InfoBar::RemovedDetails>(&removed_details));
189
190 infobar->CloseSoon();
194 } 191 }
195 192
196 void InfoBarService::RemoveAllInfoBars(bool animate) { 193 void InfoBarService::RemoveAllInfoBars(bool animate) {
197 while (!infobars_.empty()) 194 while (!infobars_.empty())
198 RemoveInfoBarInternal(infobars_.back(), animate); 195 RemoveInfoBarInternal(infobars_.back(), animate);
199 } 196 }
200 197
201 void InfoBarService::OnDidBlockDisplayingInsecureContent() { 198 void InfoBarService::OnDidBlockDisplayingInsecureContent() {
202 InsecureContentInfoBarDelegate::Create( 199 InsecureContentInfoBarDelegate::Create(
203 this, InsecureContentInfoBarDelegate::DISPLAY); 200 this, InsecureContentInfoBarDelegate::DISPLAY);
204 } 201 }
205 202
206 void InfoBarService::OnDidBlockRunningInsecureContent() { 203 void InfoBarService::OnDidBlockRunningInsecureContent() {
207 InsecureContentInfoBarDelegate::Create(this, 204 InsecureContentInfoBarDelegate::Create(this,
208 InsecureContentInfoBarDelegate::RUN); 205 InsecureContentInfoBarDelegate::RUN);
209 } 206 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698