- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / infobars / infobar_service.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/infobars/infobar_service.h"
6
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/infobars/infobar.h"
9 #include "chrome/browser/infobars/infobar_delegate.h"
10 #include "chrome/browser/infobars/insecure_content_infobar_delegate.h"
11 #include "chrome/common/render_messages.h"
12 #include "content/public/browser/navigation_controller.h"
13 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/web_contents.h"
15
16
17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InfoBarService);
18
19 InfoBarDelegate* InfoBarService::AddInfoBar(
20     scoped_ptr<InfoBarDelegate> infobar) {
21   DCHECK(infobar);
22   if (!infobars_enabled_)
23     return NULL;
24
25   for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
26        ++i) {
27     if ((*i)->EqualsDelegate(infobar.get())) {
28       DCHECK_NE(*i, infobar.get());
29       return NULL;
30     }
31   }
32
33   InfoBarDelegate* infobar_ptr = infobar.release();
34   infobars_.push_back(infobar_ptr);
35   // TODO(pkasting): Remove InfoBarService arg from delegate constructors and
36   // instead use a setter from here.
37
38   content::NotificationService::current()->Notify(
39       chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
40       content::Source<InfoBarService>(this),
41       content::Details<InfoBarAddedDetails>(infobar_ptr));
42   return infobar_ptr;
43 }
44
45 void InfoBarService::RemoveInfoBar(InfoBarDelegate* infobar) {
46   RemoveInfoBarInternal(infobar, true);
47 }
48
49 InfoBarDelegate* InfoBarService::ReplaceInfoBar(
50     InfoBarDelegate* old_infobar,
51     scoped_ptr<InfoBarDelegate> new_infobar) {
52   DCHECK(old_infobar);
53   if (!infobars_enabled_)
54     return AddInfoBar(new_infobar.Pass());  // Deletes the delegate.
55   DCHECK(new_infobar);
56
57   InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(),
58                                  old_infobar));
59   DCHECK(i != infobars_.end());
60
61   InfoBarDelegate* new_infobar_ptr = new_infobar.release();
62   i = infobars_.insert(i, new_infobar_ptr);
63   InfoBarReplacedDetails replaced_details(old_infobar, new_infobar_ptr);
64
65   // Remove the old infobar before notifying, so that if any observers call
66   // back to AddInfoBar() or similar, we don't dupe-check against this infobar.
67   infobars_.erase(++i);
68
69   old_infobar->clear_owner();
70   content::NotificationService::current()->Notify(
71       chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
72       content::Source<InfoBarService>(this),
73       content::Details<InfoBarReplacedDetails>(&replaced_details));
74   return new_infobar_ptr;
75 }
76
77 InfoBarService::InfoBarService(content::WebContents* web_contents)
78     : content::WebContentsObserver(web_contents),
79       infobars_enabled_(true) {
80   DCHECK(web_contents);
81 }
82
83 InfoBarService::~InfoBarService() {
84   // Destroy all remaining InfoBars.  It's important to not animate here so that
85   // we guarantee that we'll delete all delegates before we do anything else.
86   //
87   // TODO(pkasting): If there is no InfoBarContainer, this leaks all the
88   // InfoBarDelegates.  This will be fixed once we call CloseSoon() directly on
89   // Infobars.
90   RemoveAllInfoBars(false);
91 }
92
93 void InfoBarService::RenderProcessGone(base::TerminationStatus status) {
94   RemoveAllInfoBars(true);
95 }
96
97 void InfoBarService::NavigationEntryCommitted(
98     const content::LoadCommittedDetails& load_details) {
99   // NOTE: It is not safe to change the following code to count upwards or
100   // use iterators, as the RemoveInfoBar() call synchronously modifies our
101   // delegate list.
102   for (size_t i = infobars_.size(); i > 0; --i) {
103     InfoBarDelegate* infobar = infobars_[i - 1];
104     if (infobar->ShouldExpire(load_details))
105       RemoveInfoBar(infobar);
106   }
107 }
108
109 void InfoBarService::WebContentsDestroyed(content::WebContents* web_contents) {
110   // The WebContents is going away; be aggressively paranoid and delete
111   // ourselves lest other parts of the system attempt to add infobars or use
112   // us otherwise during the destruction.
113   web_contents->RemoveUserData(UserDataKey());
114   // That was the equivalent of "delete this". This object is now destroyed;
115   // returning from this function is the only safe thing to do.
116 }
117
118 bool InfoBarService::OnMessageReceived(const IPC::Message& message) {
119   bool handled = true;
120   IPC_BEGIN_MESSAGE_MAP(InfoBarService, message)
121     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidBlockDisplayingInsecureContent,
122                         OnDidBlockDisplayingInsecureContent)
123     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidBlockRunningInsecureContent,
124                         OnDidBlockRunningInsecureContent)
125     IPC_MESSAGE_UNHANDLED(handled = false)
126   IPC_END_MESSAGE_MAP()
127   return handled;
128 }
129
130 void InfoBarService::RemoveInfoBarInternal(InfoBarDelegate* infobar,
131                                            bool animate) {
132   DCHECK(infobar);
133   if (!infobars_enabled_) {
134     DCHECK(infobars_.empty());
135     return;
136   }
137
138   InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
139   DCHECK(i != infobars_.end());
140
141   infobar->clear_owner();
142   // Remove the infobar before notifying, so that if any observers call back to
143   // AddInfoBar() or similar, we don't dupe-check against this infobar.
144   infobars_.erase(i);
145
146   InfoBarRemovedDetails removed_details(infobar, animate);
147   content::NotificationService::current()->Notify(
148       chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
149       content::Source<InfoBarService>(this),
150       content::Details<InfoBarRemovedDetails>(&removed_details));
151 }
152
153 void InfoBarService::RemoveAllInfoBars(bool animate) {
154   while (!infobars_.empty())
155     RemoveInfoBarInternal(infobars_.back(), animate);
156 }
157
158 void InfoBarService::OnDidBlockDisplayingInsecureContent() {
159   InsecureContentInfoBarDelegate::Create(
160       this, InsecureContentInfoBarDelegate::DISPLAY);
161 }
162
163 void InfoBarService::OnDidBlockRunningInsecureContent() {
164   InsecureContentInfoBarDelegate::Create(this,
165                                          InsecureContentInfoBarDelegate::RUN);
166 }