Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / infobars / infobar_service.cc
index a97d3a5..a748e05 100644 (file)
 
 #include "base/command_line.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/infobars/infobar.h"
-#include "chrome/browser/infobars/infobar_delegate.h"
 #include "chrome/browser/infobars/insecure_content_infobar_delegate.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/render_messages.h"
-#include "content/public/browser/navigation_controller.h"
+#include "components/infobars/core/infobar.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
 
-
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InfoBarService);
 
-InfoBar* InfoBarService::AddInfoBar(scoped_ptr<InfoBar> infobar) {
-  DCHECK(infobar);
-  if (!infobars_enabled_)
-    return NULL;
-
-  for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
-       ++i) {
-    if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) {
-      DCHECK_NE((*i)->delegate(), infobar->delegate());
-      return NULL;
-    }
-  }
-
-  InfoBar* infobar_ptr = infobar.release();
-  infobars_.push_back(infobar_ptr);
-  infobar_ptr->SetOwner(this);
-
-  FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar_ptr));
-  // TODO(droger): Remove the notifications and use observers instead.
-  // See http://crbug.com/354380
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
-      content::Source<InfoBarService>(this),
-      content::Details<InfoBar::AddedDetails>(infobar_ptr));
-  return infobar_ptr;
-}
+using infobars::InfoBar;
+using infobars::InfoBarDelegate;
+using infobars::InfoBarManager;
 
-void InfoBarService::RemoveInfoBar(InfoBar* infobar) {
-  RemoveInfoBarInternal(infobar, true);
-}
+namespace {
 
-InfoBar* InfoBarService::ReplaceInfoBar(InfoBar* old_infobar,
-                                        scoped_ptr<InfoBar> new_infobar) {
-  DCHECK(old_infobar);
-  if (!infobars_enabled_)
-    return AddInfoBar(new_infobar.Pass());  // Deletes the infobar.
-  DCHECK(new_infobar);
-
-  InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(),
-                                 old_infobar));
-  DCHECK(i != infobars_.end());
-
-  InfoBar* new_infobar_ptr = new_infobar.release();
-  i = infobars_.insert(i, new_infobar_ptr);
-  new_infobar_ptr->SetOwner(this);
-  InfoBar::ReplacedDetails replaced_details(old_infobar, new_infobar_ptr);
-
-  // Remove the old infobar before notifying, so that if any observers call back
-  // to AddInfoBar() or similar, we don't dupe-check against this infobar.
-  infobars_.erase(++i);
-
-  FOR_EACH_OBSERVER(Observer,
-                    observer_list_,
-                    OnInfoBarReplaced(old_infobar, new_infobar_ptr));
-  // TODO(droger): Remove the notifications and use observers instead.
-  // See http://crbug.com/354380
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
-      content::Source<InfoBarService>(this),
-      content::Details<InfoBar::ReplacedDetails>(&replaced_details));
+bool IsReload(const content::LoadCommittedDetails& details) {
+  return content::PageTransitionStripQualifier(
+      details.entry->GetTransitionType()) == content::PAGE_TRANSITION_RELOAD;
 
-  old_infobar->CloseSoon();
-  return new_infobar_ptr;
 }
 
-void InfoBarService::AddObserver(Observer* obs) {
-  observer_list_.AddObserver(obs);
+}  // namespace
+
+// static
+InfoBarDelegate::NavigationDetails
+    InfoBarService::NavigationDetailsFromLoadCommittedDetails(
+        const content::LoadCommittedDetails& details) {
+  InfoBarDelegate::NavigationDetails navigation_details;
+  navigation_details.entry_id = details.entry->GetUniqueID();
+  navigation_details.is_navigation_to_different_page =
+      details.is_navigation_to_different_page();
+  navigation_details.did_replace_entry = details.did_replace_entry;
+  navigation_details.is_main_frame = details.is_main_frame;
+
+  const content::PageTransition transition = details.entry->GetTransitionType();
+  navigation_details.is_reload = IsReload(details);
+  navigation_details.is_redirect =
+      (transition & content::PAGE_TRANSITION_IS_REDIRECT_MASK) != 0;
+
+  return navigation_details;
 }
 
-void InfoBarService::RemoveObserver(Observer* obs) {
-  observer_list_.RemoveObserver(obs);
+// static
+content::WebContents* InfoBarService::WebContentsFromInfoBar(InfoBar* infobar) {
+  if (!infobar || !infobar->owner())
+    return NULL;
+  InfoBarService* infobar_service =
+      static_cast<InfoBarService*>(infobar->owner());
+  return infobar_service->web_contents();
 }
 
 InfoBarService::InfoBarService(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
-      infobars_enabled_(true) {
+      ignore_next_reload_(false) {
   DCHECK(web_contents);
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars))
-    infobars_enabled_ = false;
 }
 
 InfoBarService::~InfoBarService() {
-  // Destroy all remaining InfoBars.  It's important to not animate here so that
-  // we guarantee that we'll delete all delegates before we do anything else.
-  RemoveAllInfoBars(false);
-  FOR_EACH_OBSERVER(Observer, observer_list_, OnServiceShuttingDown(this));
+  ShutDown();
+}
+
+int InfoBarService::GetActiveEntryID() {
+  content::NavigationEntry* active_entry =
+      web_contents()->GetController().GetActiveEntry();
+  return active_entry ? active_entry->GetUniqueID() : 0;
+}
+
+void InfoBarService::NotifyInfoBarAdded(InfoBar* infobar) {
+  InfoBarManager::NotifyInfoBarAdded(infobar);
+  // TODO(droger): Remove the notifications and have listeners change to be
+  // InfoBarManager::Observers instead. See http://crbug.com/354380
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
+      content::Source<InfoBarService>(this),
+      content::Details<InfoBar::AddedDetails>(infobar));
+}
+
+void InfoBarService::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) {
+  InfoBarManager::NotifyInfoBarRemoved(infobar, animate);
+  // TODO(droger): Remove the notifications and have listeners change to be
+  // InfoBarManager::Observers instead. See http://crbug.com/354380
+  InfoBar::RemovedDetails removed_details(infobar, animate);
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
+      content::Source<InfoBarService>(this),
+      content::Details<InfoBar::RemovedDetails>(&removed_details));
 }
 
 void InfoBarService::RenderProcessGone(base::TerminationStatus status) {
   RemoveAllInfoBars(true);
 }
 
+void InfoBarService::DidStartNavigationToPendingEntry(
+    const GURL& url,
+    content::NavigationController::ReloadType reload_type) {
+  ignore_next_reload_ = false;
+}
+
 void InfoBarService::NavigationEntryCommitted(
     const content::LoadCommittedDetails& load_details) {
-  // NOTE: It is not safe to change the following code to count upwards or
-  // use iterators, as the RemoveInfoBar() call synchronously modifies our
-  // delegate list.
-  for (size_t i = infobars_.size(); i > 0; --i) {
-    InfoBar* infobar = infobars_[i - 1];
-    if (infobar->delegate()->ShouldExpire(load_details))
-      RemoveInfoBar(infobar);
-  }
+  const bool ignore = ignore_next_reload_ && IsReload(load_details);
+  ignore_next_reload_ = false;
+  if (!ignore)
+    OnNavigation(NavigationDetailsFromLoadCommittedDetails(load_details));
 }
 
-void InfoBarService::WebContentsDestroyed(content::WebContents* web_contents) {
+void InfoBarService::WebContentsDestroyed() {
   // The WebContents is going away; be aggressively paranoid and delete
   // ourselves lest other parts of the system attempt to add infobars or use
   // us otherwise during the destruction.
-  web_contents->RemoveUserData(UserDataKey());
+  web_contents()->RemoveUserData(UserDataKey());
   // That was the equivalent of "delete this". This object is now destroyed;
   // returning from this function is the only safe thing to do.
 }
@@ -143,40 +134,6 @@ bool InfoBarService::OnMessageReceived(const IPC::Message& message) {
   return handled;
 }
 
-void InfoBarService::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
-  DCHECK(infobar);
-  if (!infobars_enabled_) {
-    DCHECK(infobars_.empty());
-    return;
-  }
-
-  InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
-  DCHECK(i != infobars_.end());
-
-  // Remove the infobar before notifying, so that if any observers call back to
-  // AddInfoBar() or similar, we don't dupe-check against this infobar.
-  infobars_.erase(i);
-
-  // This notification must happen before the call to CloseSoon() below, since
-  // observers may want to access |infobar| and that call can delete it.
-  FOR_EACH_OBSERVER(Observer, observer_list_,
-                    OnInfoBarRemoved(infobar, animate));
-  // TODO(droger): Remove the notifications and use observers instead.
-  // See http://crbug.com/354380
-  InfoBar::RemovedDetails removed_details(infobar, animate);
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
-      content::Source<InfoBarService>(this),
-      content::Details<InfoBar::RemovedDetails>(&removed_details));
-
-  infobar->CloseSoon();
-}
-
-void InfoBarService::RemoveAllInfoBars(bool animate) {
-  while (!infobars_.empty())
-    RemoveInfoBarInternal(infobars_.back(), animate);
-}
-
 void InfoBarService::OnDidBlockDisplayingInsecureContent() {
   InsecureContentInfoBarDelegate::Create(
       this, InsecureContentInfoBarDelegate::DISPLAY);