1// Copyright (c) 2012 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 <deque>
6#include <string>
7
8#include "base/bind.h"
9#include "base/callback.h"
10#include "base/command_line.h"
11#include "base/compiler_specific.h"
12#include "base/memory/ref_counted.h"
13#include "base/run_loop.h"
14#include "base/strings/stringprintf.h"
15#include "base/strings/utf_string_conversions.h"
16#include "chrome/browser/browser_process.h"
17#include "chrome/browser/chrome_notification_types.h"
18#include "chrome/browser/infobars/confirm_infobar_delegate.h"
19#include "chrome/browser/infobars/infobar.h"
20#include "chrome/browser/infobars/infobar_service.h"
21#include "chrome/browser/notifications/balloon.h"
22#include "chrome/browser/notifications/balloon_collection.h"
23#include "chrome/browser/notifications/balloon_host.h"
24#include "chrome/browser/notifications/balloon_notification_ui_manager.h"
25#include "chrome/browser/notifications/desktop_notification_service.h"
26#include "chrome/browser/notifications/desktop_notification_service_factory.h"
27#include "chrome/browser/notifications/notification.h"
28#include "chrome/browser/profiles/profile.h"
29#include "chrome/browser/ui/browser.h"
30#include "chrome/browser/ui/browser_tabstrip.h"
31#include "chrome/browser/ui/browser_window.h"
32#include "chrome/browser/ui/tabs/tab_strip_model.h"
33#include "chrome/common/content_settings.h"
34#include "chrome/common/content_settings_pattern.h"
35#include "chrome/test/base/in_process_browser_test.h"
36#include "chrome/test/base/ui_test_utils.h"
37#include "content/public/browser/notification_service.h"
38#include "content/public/browser/notification_source.h"
39#include "content/public/browser/notification_types.h"
40#include "content/public/browser/render_view_host.h"
41#include "content/public/browser/web_contents.h"
42#include "content/public/test/browser_test_utils.h"
43#include "content/public/test/test_utils.h"
44#include "net/base/net_util.h"
45#include "net/test/embedded_test_server/embedded_test_server.h"
46#include "testing/gtest/include/gtest/gtest.h"
47#include "ui/base/window_open_disposition.h"
48#include "ui/message_center/message_center.h"
49#include "ui/message_center/message_center_observer.h"
50#include "ui/message_center/message_center_switches.h"
51#include "ui/message_center/message_center_util.h"
52#include "url/gurl.h"
53
54namespace {
55
56const char kExpectedIconUrl[] = "/notifications/no_such_file.png";
57
58enum InfobarAction {
59  DISMISS = 0,
60  ALLOW,
61  DENY,
62};
63
64class NotificationChangeObserver {
65public:
66  virtual ~NotificationChangeObserver() {}
67  virtual bool Wait() = 0;
68};
69
70class MessageCenterChangeObserver
71    : public message_center::MessageCenterObserver,
72      public NotificationChangeObserver {
73 public:
74  MessageCenterChangeObserver()
75      : notification_received_(false) {
76    message_center::MessageCenter::Get()->AddObserver(this);
77  }
78
79  virtual ~MessageCenterChangeObserver() {
80    message_center::MessageCenter::Get()->RemoveObserver(this);
81  }
82
83  // NotificationChangeObserver:
84  virtual bool Wait() OVERRIDE {
85    if (notification_received_)
86      return true;
87
88    message_loop_runner_ = new content::MessageLoopRunner;
89    message_loop_runner_->Run();
90    return notification_received_;
91  }
92
93  // message_center::MessageCenterObserver:
94  virtual void OnNotificationAdded(
95      const std::string& notification_id) OVERRIDE {
96    OnMessageCenterChanged();
97  }
98
99  virtual void OnNotificationRemoved(const std::string& notification_id,
100                                     bool by_user) OVERRIDE {
101    OnMessageCenterChanged();
102  }
103
104  virtual void OnNotificationUpdated(
105      const std::string& notification_id) OVERRIDE {
106    OnMessageCenterChanged();
107  }
108
109  void OnMessageCenterChanged() {
110    notification_received_ = true;
111    if (message_loop_runner_.get())
112      message_loop_runner_->Quit();
113  }
114
115  bool notification_received_;
116  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
117
118  DISALLOW_COPY_AND_ASSIGN(MessageCenterChangeObserver);
119};
120
121class NotificationBalloonChangeObserver
122    : public content::NotificationObserver,
123      public NotificationChangeObserver {
124 public:
125  NotificationBalloonChangeObserver()
126      : collection_(BalloonNotificationUIManager::GetInstanceForTesting()->
127            balloon_collection()),
128        collection_changed_(false),
129        notification_received_(false),
130        running_(false),
131        done_(false) {
132    registrar_.Add(this, chrome::NOTIFICATION_NOTIFY_BALLOON_CONNECTED,
133                   content::NotificationService::AllSources());
134    registrar_.Add(this, chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
135                   content::NotificationService::AllSources());
136    collection_->set_on_collection_changed_callback(
137        base::Bind(&NotificationBalloonChangeObserver::OnCollectionChanged,
138                   base::Unretained(this)));
139  }
140
141  virtual ~NotificationBalloonChangeObserver() {
142    collection_->set_on_collection_changed_callback(base::Closure());
143  }
144
145  // NotificationChangeObserver:
146  virtual bool Wait() OVERRIDE {
147    if (!Check()) {
148      running_ = true;
149      message_loop_runner_ = new content::MessageLoopRunner;
150      message_loop_runner_->Run();
151      EXPECT_TRUE(done_);
152    }
153    return done_;
154  }
155
156  bool Check() {
157    if (done_)
158      return true;
159
160    if (collection_changed_ && notification_received_) {
161      done_ = true;
162      if (running_) {
163        message_loop_runner_->Quit();
164        running_ = false;
165      }
166    }
167    return done_;
168  }
169
170  void OnCollectionChanged() {
171    collection_changed_ = true;
172    Check();
173  }
174
175  // content::NotificationObserver:
176  virtual void Observe(int type,
177                       const content::NotificationSource& source,
178                       const content::NotificationDetails& details) OVERRIDE {
179    DCHECK(type == chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED ||
180           type == chrome::NOTIFICATION_NOTIFY_BALLOON_CONNECTED);
181    notification_received_ = true;
182    Check();
183  }
184
185 private:
186  content::NotificationRegistrar registrar_;
187  BalloonCollection* collection_;
188
189  bool collection_changed_;
190  bool notification_received_;
191  bool running_;
192  bool done_;
193  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
194
195  DISALLOW_COPY_AND_ASSIGN(NotificationBalloonChangeObserver);
196};
197
198}  // namespace
199
200class NotificationsTest : public InProcessBrowserTest {
201 public:
202  NotificationsTest() {}
203
204 protected:
205  int GetNotificationCount();
206
207  NotificationChangeObserver* CreateObserver();
208
209  void CloseBrowserWindow(Browser* browser);
210  void CrashTab(Browser* browser, int index);
211  const std::deque<Balloon*>& GetActiveBalloons();
212  void CrashNotification(Balloon* balloon);
213  bool CloseNotificationAndWait(const Notification& notification);
214
215  void SetDefaultPermissionSetting(ContentSetting setting);
216  void DenyOrigin(const GURL& origin);
217  void AllowOrigin(const GURL& origin);
218  void AllowAllOrigins();
219
220  void VerifyInfoBar(const Browser* browser, int index);
221  std::string CreateNotification(Browser* browser,
222                                 bool wait_for_new_balloon,
223                                 const char* icon,
224                                 const char* title,
225                                 const char* body,
226                                 const char* replace_id);
227  std::string CreateSimpleNotification(Browser* browser,
228                                       bool wait_for_new_balloon);
229  bool RequestPermissionAndWait(Browser* browser);
230  bool CancelNotification(const char* notification_id, Browser* browser);
231  bool PerformActionOnInfoBar(Browser* browser,
232                              InfobarAction action,
233                              size_t infobar_index,
234                              int tab_index);
235  void GetPrefsByContentSetting(ContentSetting setting,
236                                ContentSettingsForOneType* settings);
237  bool CheckOriginInSetting(const ContentSettingsForOneType& settings,
238                            const GURL& origin);
239
240  GURL GetTestPageURL() const {
241    return embedded_test_server()->GetURL(
242      "/notifications/notification_tester.html");
243  }
244
245 private:
246  void DropOriginPreference(const GURL& origin);
247  DesktopNotificationService* GetDesktopNotificationService();
248};
249
250int NotificationsTest::GetNotificationCount() {
251  if (message_center::IsRichNotificationEnabled()) {
252    return message_center::MessageCenter::Get()->NotificationCount();
253  } else {
254    return BalloonNotificationUIManager::GetInstanceForTesting()->
255           balloon_collection()->GetActiveBalloons().size();
256  }
257}
258
259NotificationChangeObserver* NotificationsTest::CreateObserver() {
260  if (message_center::IsRichNotificationEnabled())
261    return new MessageCenterChangeObserver();
262  else
263    return new NotificationBalloonChangeObserver();
264}
265
266void NotificationsTest::CloseBrowserWindow(Browser* browser) {
267  content::WindowedNotificationObserver observer(
268      chrome::NOTIFICATION_BROWSER_CLOSED,
269      content::Source<Browser>(browser));
270  browser->window()->Close();
271  observer.Wait();
272}
273
274void NotificationsTest::CrashTab(Browser* browser, int index) {
275  content::CrashTab(browser->tab_strip_model()->GetWebContentsAt(index));
276}
277
278const std::deque<Balloon*>& NotificationsTest::GetActiveBalloons() {
279  return BalloonNotificationUIManager::GetInstanceForTesting()->
280      balloon_collection()->GetActiveBalloons();
281}
282
283void NotificationsTest::CrashNotification(Balloon* balloon) {
284  content::CrashTab(balloon->balloon_view()->GetHost()->web_contents());
285}
286
287bool NotificationsTest::CloseNotificationAndWait(
288    const Notification& notification) {
289  scoped_ptr<NotificationChangeObserver> observer(CreateObserver());
290  bool success = g_browser_process->notification_ui_manager()->
291      CancelById(notification.notification_id());
292  if (success)
293    return observer->Wait();
294  return false;
295}
296
297void NotificationsTest::SetDefaultPermissionSetting(ContentSetting setting) {
298  DesktopNotificationService* service = GetDesktopNotificationService();
299  service->SetDefaultContentSetting(setting);
300}
301
302void NotificationsTest::DenyOrigin(const GURL& origin) {
303  DropOriginPreference(origin);
304  GetDesktopNotificationService()->DenyPermission(origin);
305}
306
307void NotificationsTest::AllowOrigin(const GURL& origin) {
308  DropOriginPreference(origin);
309  GetDesktopNotificationService()->GrantPermission(origin);
310}
311
312void NotificationsTest::AllowAllOrigins() {
313  GetDesktopNotificationService()->ResetAllOrigins();
314  GetDesktopNotificationService()->SetDefaultContentSetting(
315      CONTENT_SETTING_ALLOW);
316}
317
318void NotificationsTest::VerifyInfoBar(const Browser* browser, int index) {
319  InfoBarService* infobar_service = InfoBarService::FromWebContents(
320      browser->tab_strip_model()->GetWebContentsAt(index));
321
322  ASSERT_EQ(1U, infobar_service->infobar_count());
323  ConfirmInfoBarDelegate* confirm_infobar =
324      infobar_service->infobar_at(0)->delegate()->AsConfirmInfoBarDelegate();
325  ASSERT_TRUE(confirm_infobar);
326  int buttons = confirm_infobar->GetButtons();
327  EXPECT_TRUE(buttons & ConfirmInfoBarDelegate::BUTTON_OK);
328  EXPECT_TRUE(buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL);
329}
330
331std::string NotificationsTest::CreateNotification(
332    Browser* browser,
333    bool wait_for_new_balloon,
334    const char* icon,
335    const char* title,
336    const char* body,
337    const char* replace_id) {
338  std::string script = base::StringPrintf(
339      "createNotification('%s', '%s', '%s', '%s');",
340      icon, title, body, replace_id);
341
342  scoped_ptr<NotificationChangeObserver> observer(CreateObserver());
343  std::string result;
344  bool success = content::ExecuteScriptAndExtractString(
345      browser->tab_strip_model()->GetActiveWebContents(),
346      script,
347      &result);
348  if (success && result != "-1" && wait_for_new_balloon)
349    success = observer->Wait();
350  EXPECT_TRUE(success);
351
352  return result;
353}
354
355std::string NotificationsTest::CreateSimpleNotification(
356    Browser* browser,
357    bool wait_for_new_balloon) {
358  return CreateNotification(
359      browser, wait_for_new_balloon,
360      "no_such_file.png", "My Title", "My Body", "");
361}
362
363bool NotificationsTest::RequestPermissionAndWait(Browser* browser) {
364  InfoBarService* infobar_service = InfoBarService::FromWebContents(
365      browser->tab_strip_model()->GetActiveWebContents());
366  content::WindowedNotificationObserver observer(
367      chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
368      content::Source<InfoBarService>(infobar_service));
369  std::string result;
370  bool success = content::ExecuteScriptAndExtractString(
371      browser->tab_strip_model()->GetActiveWebContents(),
372      "requestPermission();",
373      &result);
374  if (!success || result != "1")
375    return false;
376  observer.Wait();
377  return true;
378}
379
380bool NotificationsTest::CancelNotification(
381    const char* notification_id,
382    Browser* browser) {
383  std::string script = base::StringPrintf(
384      "cancelNotification('%s');",
385      notification_id);
386
387  scoped_ptr<NotificationChangeObserver> observer(CreateObserver());
388  std::string result;
389  bool success = content::ExecuteScriptAndExtractString(
390      browser->tab_strip_model()->GetActiveWebContents(),
391      script,
392      &result);
393  if (!success || result != "1")
394    return false;
395  return observer->Wait();
396}
397
398bool NotificationsTest::PerformActionOnInfoBar(
399    Browser* browser,
400    InfobarAction action,
401    size_t infobar_index,
402    int tab_index) {
403  InfoBarService* infobar_service = InfoBarService::FromWebContents(
404      browser->tab_strip_model()->GetWebContentsAt(tab_index));
405  if (infobar_index >= infobar_service->infobar_count()) {
406    ADD_FAILURE();
407    return false;
408  }
409
410  InfoBar* infobar = infobar_service->infobar_at(infobar_index);
411  InfoBarDelegate* infobar_delegate = infobar->delegate();
412  switch (action) {
413    case DISMISS:
414      infobar_delegate->InfoBarDismissed();
415      infobar_service->RemoveInfoBar(infobar);
416      return true;
417
418    case ALLOW: {
419      ConfirmInfoBarDelegate* confirm_infobar_delegate =
420          infobar_delegate->AsConfirmInfoBarDelegate();
421      if (!confirm_infobar_delegate) {
422        ADD_FAILURE();
423      } else if (confirm_infobar_delegate->Accept()) {
424        infobar_service->RemoveInfoBar(infobar);
425        return true;
426      }
427    }
428
429    case DENY: {
430      ConfirmInfoBarDelegate* confirm_infobar_delegate =
431          infobar_delegate->AsConfirmInfoBarDelegate();
432      if (!confirm_infobar_delegate) {
433        ADD_FAILURE();
434      } else if (confirm_infobar_delegate->Cancel()) {
435        infobar_service->RemoveInfoBar(infobar);
436        return true;
437      }
438    }
439  }
440
441  return false;
442}
443
444void NotificationsTest::GetPrefsByContentSetting(
445    ContentSetting setting,
446    ContentSettingsForOneType* settings) {
447  DesktopNotificationService* service = GetDesktopNotificationService();
448  service->GetNotificationsSettings(settings);
449  for (ContentSettingsForOneType::iterator it = settings->begin();
450       it != settings->end(); ) {
451    if (it->setting != setting || it->source.compare("preference") != 0)
452      it = settings->erase(it);
453    else
454      ++it;
455  }
456}
457
458bool NotificationsTest::CheckOriginInSetting(
459    const ContentSettingsForOneType& settings,
460    const GURL& origin) {
461  ContentSettingsPattern pattern =
462      ContentSettingsPattern::FromURLNoWildcard(origin);
463  for (ContentSettingsForOneType::const_iterator it = settings.begin();
464       it != settings.end(); ++it) {
465    if (it->primary_pattern == pattern)
466      return true;
467  }
468  return false;
469}
470
471void NotificationsTest::DropOriginPreference(const GURL& origin) {
472  GetDesktopNotificationService()->ClearSetting(
473      ContentSettingsPattern::FromURLNoWildcard(origin));
474}
475
476DesktopNotificationService* NotificationsTest::GetDesktopNotificationService() {
477  Profile* profile = browser()->profile();
478  return DesktopNotificationServiceFactory::GetForProfile(profile);
479}
480
481// If this flakes, use http://crbug.com/62311 and http://crbug.com/74428.
482IN_PROC_BROWSER_TEST_F(NotificationsTest, TestUserGestureInfobar) {
483  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
484
485  ui_test_utils::NavigateToURL(
486      browser(),
487      embedded_test_server()->GetURL(
488          "/notifications/notifications_request_function.html"));
489
490  // Request permission by calling request() while eval'ing an inline script;
491  // That's considered a user gesture to webkit, and should produce an infobar.
492  bool result;
493  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
494      browser()->tab_strip_model()->GetActiveWebContents(),
495      "window.domAutomationController.send(request());",
496      &result));
497  EXPECT_TRUE(result);
498
499  EXPECT_EQ(1U, InfoBarService::FromWebContents(
500      browser()->tab_strip_model()->GetWebContentsAt(0))->infobar_count());
501}
502
503// If this flakes, use http://crbug.com/62311.
504IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNoUserGestureInfobar) {
505  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
506
507  // Load a page which just does a request; no user gesture should result
508  // in no infobar.
509  ui_test_utils::NavigateToURL(
510      browser(),
511      embedded_test_server()->GetURL(
512          "/notifications/notifications_request_inline.html"));
513
514  EXPECT_EQ(0U, InfoBarService::FromWebContents(
515      browser()->tab_strip_model()->GetWebContentsAt(0))->infobar_count());
516}
517
518IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCreateSimpleNotification) {
519  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
520
521  // Creates a simple notification.
522  AllowAllOrigins();
523  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
524
525  std::string result = CreateSimpleNotification(browser(), true);
526  EXPECT_NE("-1", result);
527
528  GURL EXPECTED_ICON_URL = embedded_test_server()->GetURL(kExpectedIconUrl);
529  ASSERT_EQ(1, GetNotificationCount());
530  if (message_center::IsRichNotificationEnabled()) {
531    message_center::NotificationList::Notifications notifications =
532        message_center::MessageCenter::Get()->GetVisibleNotifications();
533    EXPECT_EQ(ASCIIToUTF16("My Title"), (*notifications.rbegin())->title());
534    EXPECT_EQ(ASCIIToUTF16("My Body"), (*notifications.rbegin())->message());
535  } else {
536    const std::deque<Balloon*>& balloons = GetActiveBalloons();
537    ASSERT_EQ(1U, balloons.size());
538    Balloon* balloon = balloons[0];
539    const Notification& notification = balloon->notification();
540    EXPECT_EQ(EXPECTED_ICON_URL, notification.icon_url());
541    EXPECT_EQ(ASCIIToUTF16("My Title"), notification.title());
542    EXPECT_EQ(ASCIIToUTF16("My Body"), notification.message());
543  }
544}
545
546IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCloseNotification) {
547  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
548
549  // Creates a notification and closes it.
550  AllowAllOrigins();
551  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
552
553  std::string result = CreateSimpleNotification(browser(), true);
554  EXPECT_NE("-1", result);
555  ASSERT_EQ(1, GetNotificationCount());
556
557  if (message_center::IsRichNotificationEnabled()) {
558    message_center::NotificationList::Notifications notifications =
559        message_center::MessageCenter::Get()->GetVisibleNotifications();
560    message_center::MessageCenter::Get()->RemoveNotification(
561        (*notifications.rbegin())->id(),
562        true);  // by_user
563  } else {
564    const std::deque<Balloon*>& balloons = GetActiveBalloons();
565    EXPECT_TRUE(CloseNotificationAndWait(balloons[0]->notification()));
566  }
567
568  ASSERT_EQ(0, GetNotificationCount());
569}
570
571IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCancelNotification) {
572  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
573
574  // Creates a notification and cancels it in the origin page.
575  AllowAllOrigins();
576  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
577
578  std::string note_id = CreateSimpleNotification(browser(), true);
579  EXPECT_NE(note_id, "-1");
580
581  ASSERT_EQ(1, GetNotificationCount());
582  ASSERT_TRUE(CancelNotification(note_id.c_str(), browser()));
583  ASSERT_EQ(0, GetNotificationCount());
584}
585
586IN_PROC_BROWSER_TEST_F(NotificationsTest, TestPermissionInfobarAppears) {
587  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
588
589  // Requests notification privileges and verifies the infobar appears.
590  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
591  ASSERT_TRUE(RequestPermissionAndWait(browser()));
592
593  ASSERT_EQ(0, GetNotificationCount());
594  ASSERT_NO_FATAL_FAILURE(VerifyInfoBar(browser(), 0));
595}
596
597IN_PROC_BROWSER_TEST_F(NotificationsTest, TestAllowOnPermissionInfobar) {
598  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
599
600  // Tries to create a notification and clicks allow on the infobar.
601  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
602  // This notification should not be shown because we do not have permission.
603  CreateSimpleNotification(browser(), false);
604  ASSERT_EQ(0, GetNotificationCount());
605
606  ASSERT_TRUE(RequestPermissionAndWait(browser()));
607  ASSERT_TRUE(PerformActionOnInfoBar(browser(), ALLOW, 0, 0));
608
609  CreateSimpleNotification(browser(), true);
610  EXPECT_EQ(1, GetNotificationCount());
611}
612
613IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyOnPermissionInfobar) {
614  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
615
616  // Test that no notification is created
617  // when Deny is chosen from permission infobar.
618  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
619  ASSERT_TRUE(RequestPermissionAndWait(browser()));
620  PerformActionOnInfoBar(browser(), DENY, 0, 0);
621  CreateSimpleNotification(browser(), false);
622  ASSERT_EQ(0, GetNotificationCount());
623  ContentSettingsForOneType settings;
624  GetPrefsByContentSetting(CONTENT_SETTING_BLOCK, &settings);
625  EXPECT_TRUE(CheckOriginInSetting(settings, GetTestPageURL()));
626}
627
628IN_PROC_BROWSER_TEST_F(NotificationsTest, TestClosePermissionInfobar) {
629  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
630
631  // Test that no notification is created when permission infobar is dismissed.
632  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
633  ASSERT_TRUE(RequestPermissionAndWait(browser()));
634  PerformActionOnInfoBar(browser(), DISMISS, 0, 0);
635  CreateSimpleNotification(browser(), false);
636  ASSERT_EQ(0, GetNotificationCount());
637  ContentSettingsForOneType settings;
638  GetPrefsByContentSetting(CONTENT_SETTING_BLOCK, &settings);
639  EXPECT_EQ(0U, settings.size());
640}
641
642IN_PROC_BROWSER_TEST_F(NotificationsTest, TestAllowNotificationsFromAllSites) {
643  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
644
645  // Verify that all domains can be allowed to show notifications.
646  SetDefaultPermissionSetting(CONTENT_SETTING_ALLOW);
647  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
648
649  std::string result = CreateSimpleNotification(browser(), true);
650  EXPECT_NE("-1", result);
651
652  ASSERT_EQ(1, GetNotificationCount());
653  EXPECT_EQ(0U, InfoBarService::FromWebContents(
654      browser()->tab_strip_model()->GetWebContentsAt(0))->infobar_count());
655}
656
657IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyNotificationsFromAllSites) {
658  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
659
660  // Verify that no domain can show notifications.
661  SetDefaultPermissionSetting(CONTENT_SETTING_BLOCK);
662  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
663
664  std::string result = CreateSimpleNotification(browser(), false);
665  EXPECT_EQ("-1", result);
666
667  ASSERT_EQ(0, GetNotificationCount());
668}
669
670IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyDomainAndAllowAll) {
671  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
672
673  // Verify that denying a domain and allowing all shouldn't show
674  // notifications from the denied domain.
675  DenyOrigin(GetTestPageURL().GetOrigin());
676  SetDefaultPermissionSetting(CONTENT_SETTING_ALLOW);
677
678  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
679
680  std::string result = CreateSimpleNotification(browser(), false);
681  EXPECT_EQ("-1", result);
682
683  ASSERT_EQ(0, GetNotificationCount());
684}
685
686IN_PROC_BROWSER_TEST_F(NotificationsTest, TestAllowDomainAndDenyAll) {
687  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
688
689  // Verify that allowing a domain and denying all others should show
690  // notifications from the allowed domain.
691  AllowOrigin(GetTestPageURL().GetOrigin());
692  SetDefaultPermissionSetting(CONTENT_SETTING_BLOCK);
693
694  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
695
696  std::string result = CreateSimpleNotification(browser(), true);
697  EXPECT_NE("-1", result);
698
699  ASSERT_EQ(1, GetNotificationCount());
700}
701
702IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyAndThenAllowDomain) {
703  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
704
705  // Verify that denying and again allowing should show notifications.
706  DenyOrigin(GetTestPageURL().GetOrigin());
707
708  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
709
710  std::string result = CreateSimpleNotification(browser(), false);
711  EXPECT_EQ("-1", result);
712
713  ASSERT_EQ(0, GetNotificationCount());
714
715  AllowOrigin(GetTestPageURL().GetOrigin());
716  result = CreateSimpleNotification(browser(), true);
717  EXPECT_NE("-1", result);
718
719  ASSERT_EQ(1, GetNotificationCount());
720  EXPECT_EQ(0U, InfoBarService::FromWebContents(
721      browser()->tab_strip_model()->GetWebContentsAt(0))->infobar_count());
722}
723
724IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCreateDenyCloseNotifications) {
725  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
726
727  // Verify able to create, deny, and close the notification.
728  AllowAllOrigins();
729  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
730  CreateSimpleNotification(browser(), true);
731  ASSERT_EQ(1, GetNotificationCount());
732
733  DenyOrigin(GetTestPageURL().GetOrigin());
734  ContentSettingsForOneType settings;
735  GetPrefsByContentSetting(CONTENT_SETTING_BLOCK, &settings);
736  ASSERT_TRUE(CheckOriginInSetting(settings, GetTestPageURL().GetOrigin()));
737
738  EXPECT_EQ(1, GetNotificationCount());
739  if (message_center::IsRichNotificationEnabled()) {
740    message_center::NotificationList::Notifications notifications =
741        message_center::MessageCenter::Get()->GetVisibleNotifications();
742    message_center::MessageCenter::Get()->RemoveNotification(
743        (*notifications.rbegin())->id(),
744        true);  // by_user
745  } else {
746    const std::deque<Balloon*>& balloons = GetActiveBalloons();
747    ASSERT_TRUE(CloseNotificationAndWait(balloons[0]->notification()));
748  }
749  ASSERT_EQ(0, GetNotificationCount());
750}
751
752// Crashes on Linux/Win. See http://crbug.com/160657.
753IN_PROC_BROWSER_TEST_F(
754    NotificationsTest,
755    DISABLED_TestOriginPrefsNotSavedInIncognito) {
756  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
757
758  // Verify that allow/deny origin preferences are not saved in incognito.
759  Browser* incognito = CreateIncognitoBrowser();
760  ui_test_utils::NavigateToURL(incognito, GetTestPageURL());
761  ASSERT_TRUE(RequestPermissionAndWait(incognito));
762  PerformActionOnInfoBar(incognito, DENY, 0, 0);
763  CloseBrowserWindow(incognito);
764
765  incognito = CreateIncognitoBrowser();
766  ui_test_utils::NavigateToURL(incognito, GetTestPageURL());
767  ASSERT_TRUE(RequestPermissionAndWait(incognito));
768  PerformActionOnInfoBar(incognito, ALLOW, 0, 0);
769  CreateSimpleNotification(incognito, true);
770  ASSERT_EQ(1, GetNotificationCount());
771  CloseBrowserWindow(incognito);
772
773  incognito = CreateIncognitoBrowser();
774  ui_test_utils::NavigateToURL(incognito, GetTestPageURL());
775  ASSERT_TRUE(RequestPermissionAndWait(incognito));
776
777  ContentSettingsForOneType settings;
778  GetPrefsByContentSetting(CONTENT_SETTING_BLOCK, &settings);
779  EXPECT_EQ(0U, settings.size());
780  GetPrefsByContentSetting(CONTENT_SETTING_ALLOW, &settings);
781  EXPECT_EQ(0U, settings.size());
782}
783
784IN_PROC_BROWSER_TEST_F(NotificationsTest, TestExitBrowserWithInfobar) {
785  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
786
787  // Exit the browser window, when the infobar appears.
788  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
789  ASSERT_TRUE(RequestPermissionAndWait(browser()));
790}
791
792// Times out on Windows and Linux. http://crbug.com/168976
793#if defined(OS_WIN) || defined(OS_LINUX)
794#define MAYBE_TestCrashTabWithPermissionInfobar \
795    DISABLED_TestCrashTabWithPermissionInfobar
796#else
797#define MAYBE_TestCrashTabWithPermissionInfobar \
798    TestCrashTabWithPermissionInfobar
799#endif
800IN_PROC_BROWSER_TEST_F(NotificationsTest,
801                       MAYBE_TestCrashTabWithPermissionInfobar) {
802  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
803
804  // Test crashing the tab with permission infobar doesn't crash Chrome.
805  ui_test_utils::NavigateToURLWithDisposition(
806      browser(),
807      embedded_test_server()->GetURL("/empty.html"),
808      NEW_BACKGROUND_TAB,
809      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
810  browser()->tab_strip_model()->ActivateTabAt(0, true);
811  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
812  ASSERT_TRUE(RequestPermissionAndWait(browser()));
813  CrashTab(browser(), 0);
814}
815
816IN_PROC_BROWSER_TEST_F(NotificationsTest, TestKillNotificationProcess) {
817  // Notifications don't have their own process with the message center.
818  if (message_center::IsRichNotificationEnabled())
819    return;
820
821  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
822
823  // Test killing a notification doesn't crash Chrome.
824  AllowAllOrigins();
825  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
826  CreateSimpleNotification(browser(), true);
827  ASSERT_EQ(1, GetNotificationCount());
828
829  const std::deque<Balloon*>& balloons = GetActiveBalloons();
830  ASSERT_EQ(1U, balloons.size());
831  CrashNotification(balloons[0]);
832  ASSERT_EQ(0, GetNotificationCount());
833}
834
835IN_PROC_BROWSER_TEST_F(NotificationsTest, TestIncognitoNotification) {
836  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
837
838  // Test notifications in incognito window.
839  Browser* browser = CreateIncognitoBrowser();
840  ui_test_utils::NavigateToURL(browser, GetTestPageURL());
841  browser->tab_strip_model()->ActivateTabAt(0, true);
842  ASSERT_TRUE(RequestPermissionAndWait(browser));
843  PerformActionOnInfoBar(browser, ALLOW, 0, 0);
844  CreateSimpleNotification(browser, true);
845  ASSERT_EQ(1, GetNotificationCount());
846}
847
848IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCloseTabWithPermissionInfobar) {
849  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
850
851  // Test that user can close tab when infobar present.
852  ui_test_utils::NavigateToURLWithDisposition(
853      browser(),
854      GURL("about:blank"),
855      NEW_BACKGROUND_TAB,
856      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
857  browser()->tab_strip_model()->ActivateTabAt(0, true);
858  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
859  ASSERT_TRUE(RequestPermissionAndWait(browser()));
860  content::WebContentsDestroyedWatcher destroyed_watcher(
861      browser()->tab_strip_model()->GetWebContentsAt(0));
862  browser()->tab_strip_model()->CloseWebContentsAt(0,
863                                                   TabStripModel::CLOSE_NONE);
864  destroyed_watcher.Wait();
865}
866
867IN_PROC_BROWSER_TEST_F(
868    NotificationsTest,
869    TestNavigateAwayWithPermissionInfobar) {
870  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
871
872  // Test navigating away when an infobar is present,
873  // then trying to create a notification from the same page.
874  ui_test_utils::NavigateToURLWithDisposition(
875      browser(),
876      GURL("about:blank"),
877      NEW_BACKGROUND_TAB,
878      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
879  browser()->tab_strip_model()->ActivateTabAt(0, true);
880  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
881  ASSERT_TRUE(RequestPermissionAndWait(browser()));
882  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
883  ASSERT_TRUE(RequestPermissionAndWait(browser()));
884  PerformActionOnInfoBar(browser(), ALLOW, 0, 0);
885  CreateSimpleNotification(browser(), true);
886  ASSERT_EQ(1, GetNotificationCount());
887}
888
889// See crbug.com/248470
890#if defined(OS_LINUX)
891#define MAYBE_TestCrashRendererNotificationRemain \
892    DISABLED_TestCrashRendererNotificationRemain
893#else
894#define MAYBE_TestCrashRendererNotificationRemain \
895    TestCrashRendererNotificationRemain
896#endif
897
898IN_PROC_BROWSER_TEST_F(NotificationsTest,
899                       MAYBE_TestCrashRendererNotificationRemain) {
900  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
901
902  // Test crashing renderer does not close or crash notification.
903  AllowAllOrigins();
904  ui_test_utils::NavigateToURLWithDisposition(
905      browser(),
906      GURL("about:blank"),
907      NEW_BACKGROUND_TAB,
908      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
909  browser()->tab_strip_model()->ActivateTabAt(0, true);
910  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
911  CreateSimpleNotification(browser(), true);
912  ASSERT_EQ(1, GetNotificationCount());
913  CrashTab(browser(), 0);
914  ASSERT_EQ(1, GetNotificationCount());
915}
916
917IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNotificationReplacement) {
918  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
919
920  // Test that we can replace a notification using the replaceId.
921  AllowAllOrigins();
922
923  ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
924
925  std::string result = CreateNotification(
926      browser(), true, "abc.png", "Title1", "Body1", "chat");
927  EXPECT_NE("-1", result);
928
929  ASSERT_EQ(1, GetNotificationCount());
930
931  result = CreateNotification(
932      browser(), false, "no_such_file.png", "Title2", "Body2", "chat");
933  EXPECT_NE("-1", result);
934
935  if (message_center::IsRichNotificationEnabled()) {
936    ASSERT_EQ(1, GetNotificationCount());
937    message_center::NotificationList::Notifications notifications =
938        message_center::MessageCenter::Get()->GetVisibleNotifications();
939    EXPECT_EQ(ASCIIToUTF16("Title2"), (*notifications.rbegin())->title());
940    EXPECT_EQ(ASCIIToUTF16("Body2"), (*notifications.rbegin())->message());
941  } else {
942    const std::deque<Balloon*>& balloons = GetActiveBalloons();
943    ASSERT_EQ(1U, balloons.size());
944    Balloon* balloon = balloons[0];
945    const Notification& notification = balloon->notification();
946    GURL EXPECTED_ICON_URL = embedded_test_server()->GetURL(kExpectedIconUrl);
947    EXPECT_EQ(EXPECTED_ICON_URL, notification.icon_url());
948    EXPECT_EQ(ASCIIToUTF16("Title2"), notification.title());
949    EXPECT_EQ(ASCIIToUTF16("Body2"), notification.message());
950  }
951}
952