OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "base/json/json_reader.h" | 5 #include "base/json/json_reader.h" |
6 #include "base/message_loop.h" | 6 #include "base/message_loop.h" |
7 #include "base/string_number_conversions.h" | 7 #include "base/string_number_conversions.h" |
8 #include "base/time.h" | 8 #include "base/time.h" |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
12 #include "chrome/browser/extensions/apps_promo.h" | |
13 #include "chrome/browser/prefs/browser_prefs.h" | 12 #include "chrome/browser/prefs/browser_prefs.h" |
14 #include "chrome/browser/prefs/pref_service.h" | 13 #include "chrome/browser/prefs/pref_service.h" |
15 #include "chrome/browser/web_resource/notification_promo.h" | 14 #include "chrome/browser/web_resource/notification_promo.h" |
16 #include "chrome/browser/web_resource/promo_resource_service.h" | 15 #include "chrome/browser/web_resource/promo_resource_service.h" |
17 #include "chrome/common/chrome_notification_types.h" | 16 #include "chrome/common/chrome_notification_types.h" |
18 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
19 #include "chrome/test/base/testing_browser_process.h" | 18 #include "chrome/test/base/testing_browser_process.h" |
20 #include "chrome/test/base/testing_pref_service.h" | 19 #include "chrome/test/base/testing_pref_service.h" |
21 #include "chrome/test/base/testing_profile.h" | 20 #include "chrome/test/base/testing_profile.h" |
22 #include "content/public/browser/notification_registrar.h" | 21 #include "content/public/browser/notification_registrar.h" |
23 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
24 #include "content/public/test/test_url_fetcher_factory.h" | 23 #include "content/public/test/test_url_fetcher_factory.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
26 | 25 |
27 class PromoResourceServiceTest : public testing::Test { | 26 class PromoResourceServiceTest : public testing::Test { |
28 public: | 27 public: |
29 PromoResourceServiceTest() | 28 PromoResourceServiceTest() |
30 : local_state_(static_cast<TestingBrowserProcess*>(g_browser_process)), | 29 : local_state_(static_cast<TestingBrowserProcess*>(g_browser_process)), |
31 web_resource_service_(new PromoResourceService(&profile_)) { | 30 web_resource_service_(new PromoResourceService(&profile_)) { |
32 } | 31 } |
33 | 32 |
34 protected: | 33 protected: |
35 TestingProfile profile_; | 34 TestingProfile profile_; |
36 ScopedTestingLocalState local_state_; | 35 ScopedTestingLocalState local_state_; |
37 scoped_refptr<PromoResourceService> web_resource_service_; | 36 scoped_refptr<PromoResourceService> web_resource_service_; |
38 MessageLoop loop_; | 37 MessageLoop loop_; |
39 }; | 38 }; |
40 | 39 |
41 // Verifies that custom dates read from a web resource server are written to | |
42 // the preferences file. | |
43 TEST_F(PromoResourceServiceTest, UnpackLogoSignal) { | |
44 // Set up start and end dates in a Dictionary as if parsed from the service. | |
45 std::string json = "{ " | |
46 " \"topic\": {" | |
47 " \"answers\": [" | |
48 " {" | |
49 " \"name\": \"custom_logo_start\"," | |
50 " \"inproduct\": \"31/01/10 01:00 GMT\"" | |
51 " }," | |
52 " {" | |
53 " \"name\": \"custom_logo_end\"," | |
54 " \"inproduct\": \"31/01/12 01:00 GMT\"" | |
55 " }" | |
56 " ]" | |
57 " }" | |
58 "}"; | |
59 scoped_ptr<DictionaryValue> test_json( | |
60 static_cast<DictionaryValue*>(base::JSONReader::Read(json))); | |
61 | |
62 // Check that prefs are set correctly. | |
63 web_resource_service_->UnpackLogoSignal(*(test_json.get())); | |
64 PrefService* prefs = profile_.GetPrefs(); | |
65 ASSERT_TRUE(prefs != NULL); | |
66 | |
67 double logo_start = | |
68 prefs->GetDouble(prefs::kNtpCustomLogoStart); | |
69 EXPECT_EQ(logo_start, 1264899600); // unix epoch for Jan 31 2010 0100 GMT. | |
70 double logo_end = | |
71 prefs->GetDouble(prefs::kNtpCustomLogoEnd); | |
72 EXPECT_EQ(logo_end, 1327971600); // unix epoch for Jan 31 2012 0100 GMT. | |
73 | |
74 // Change the start only and recheck. | |
75 json = "{ " | |
76 " \"topic\": {" | |
77 " \"answers\": [" | |
78 " {" | |
79 " \"name\": \"custom_logo_start\"," | |
80 " \"inproduct\": \"28/02/10 14:00 GMT\"" | |
81 " }," | |
82 " {" | |
83 " \"name\": \"custom_logo_end\"," | |
84 " \"inproduct\": \"31/01/12 01:00 GMT\"" | |
85 " }" | |
86 " ]" | |
87 " }" | |
88 "}"; | |
89 test_json->Clear(); | |
90 test_json.reset(static_cast<DictionaryValue*>( | |
91 base::JSONReader::Read(json))); | |
92 | |
93 // Check that prefs are set correctly. | |
94 web_resource_service_->UnpackLogoSignal(*(test_json.get())); | |
95 | |
96 logo_start = prefs->GetDouble(prefs::kNtpCustomLogoStart); | |
97 EXPECT_EQ(logo_start, 1267365600); // date changes to Feb 28 2010 1400 GMT. | |
98 | |
99 // If no date is included in the prefs, reset custom logo dates to 0. | |
100 json = "{ " | |
101 " \"topic\": {" | |
102 " \"answers\": [" | |
103 " {" | |
104 " }" | |
105 " ]" | |
106 " }" | |
107 "}"; | |
108 test_json->Clear(); | |
109 test_json.reset(static_cast<DictionaryValue*>( | |
110 base::JSONReader::Read(json))); | |
111 | |
112 // Check that prefs are set correctly. | |
113 web_resource_service_->UnpackLogoSignal(*(test_json.get())); | |
114 logo_start = prefs->GetDouble(prefs::kNtpCustomLogoStart); | |
115 EXPECT_EQ(logo_start, 0); // date value reset to 0; | |
116 logo_end = prefs->GetDouble(prefs::kNtpCustomLogoEnd); | |
117 EXPECT_EQ(logo_end, 0); // date value reset to 0; | |
118 } | |
119 | |
120 class NotificationPromoTest { | 40 class NotificationPromoTest { |
121 public: | 41 public: |
122 explicit NotificationPromoTest(Profile* profile) | 42 explicit NotificationPromoTest(Profile* profile) |
123 : profile_(profile), | 43 : profile_(profile), |
124 prefs_(profile->GetPrefs()), | 44 prefs_(profile->GetPrefs()), |
125 notification_promo_(profile), | 45 notification_promo_(profile), |
126 received_notification_(false), | 46 received_notification_(false), |
127 start_(0.0), | 47 start_(0.0), |
128 end_(0.0), | 48 end_(0.0), |
129 num_groups_(0), | 49 num_groups_(0), |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 promo_test.TestIncrement(); | 407 promo_test.TestIncrement(); |
488 promo_test.TestGplus(); | 408 promo_test.TestGplus(); |
489 } | 409 } |
490 | 410 |
491 TEST_F(PromoResourceServiceTest, PromoServerURLTest) { | 411 TEST_F(PromoResourceServiceTest, PromoServerURLTest) { |
492 GURL promo_server_url = NotificationPromo::PromoServerURL(); | 412 GURL promo_server_url = NotificationPromo::PromoServerURL(); |
493 EXPECT_FALSE(promo_server_url.is_empty()); | 413 EXPECT_FALSE(promo_server_url.is_empty()); |
494 EXPECT_TRUE(promo_server_url.SchemeIs("https")); | 414 EXPECT_TRUE(promo_server_url.SchemeIs("https")); |
495 // TODO(achuith): Test this better. | 415 // TODO(achuith): Test this better. |
496 } | 416 } |
497 | |
498 TEST_F(PromoResourceServiceTest, UnpackWebStoreSignal) { | |
499 web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV); | |
500 | |
501 std::string json = "{ " | |
502 " \"topic\": {" | |
503 " \"answers\": [" | |
504 " {" | |
505 " \"answer_id\": \"341252\"," | |
506 " \"name\": \"webstore_promo:15:1:\"," | |
507 " \"question\": \"The header!\"," | |
508 " \"inproduct_target\": \"The button label!\"," | |
509 " \"inproduct\": \"http://link.com\"," | |
510 " \"tooltip\": \"No thanks, hide this.\"" | |
511 " }" | |
512 " ]" | |
513 " }" | |
514 "}"; | |
515 scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( | |
516 base::JSONReader::Read(json))); | |
517 | |
518 // Set the source logo URL to verify that it gets cleared. | |
519 AppsPromo::SetSourcePromoLogoURL(GURL("https://www.google.com/test.png")); | |
520 | |
521 // Check that prefs are set correctly. | |
522 web_resource_service_->UnpackWebStoreSignal(*(test_json.get())); | |
523 | |
524 AppsPromo::PromoData actual_data = AppsPromo::GetPromo(); | |
525 EXPECT_EQ("341252", actual_data.id); | |
526 EXPECT_EQ("The header!", actual_data.header); | |
527 EXPECT_EQ("The button label!", actual_data.button); | |
528 EXPECT_EQ(GURL("http://link.com"), actual_data.link); | |
529 EXPECT_EQ("No thanks, hide this.", actual_data.expire); | |
530 EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group); | |
531 | |
532 // When we don't download a logo, we revert to the default and clear the | |
533 // source pref. | |
534 EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo); | |
535 EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL()); | |
536 } | |
537 | |
538 // Tests that the "web store active" flag is set even when the web store promo | |
539 // fails parsing. | |
540 TEST_F(PromoResourceServiceTest, UnpackPartialWebStoreSignal) { | |
541 std::string json = "{ " | |
542 " \"topic\": {" | |
543 " \"answers\": [" | |
544 " {" | |
545 " \"answer_id\": \"sdlfj32\"," | |
546 " \"name\": \"webstore_promo:#klsdjlfSD\"" | |
547 " }" | |
548 " ]" | |
549 " }" | |
550 "}"; | |
551 scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( | |
552 base::JSONReader::Read(json))); | |
553 | |
554 // Check that prefs are set correctly. | |
555 web_resource_service_->UnpackWebStoreSignal(*(test_json.get())); | |
556 EXPECT_FALSE(AppsPromo::IsPromoSupportedForLocale()); | |
557 EXPECT_TRUE(AppsPromo::IsWebStoreSupportedForLocale()); | |
558 } | |
559 | |
560 // Tests that we can successfully unpack web store signals with HTTPS | |
561 // logos. | |
562 TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpsLogo) { | |
563 web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV); | |
564 | |
565 std::string logo_url = "https://www.google.com/image/test.png"; | |
566 std::string png_data = "!$#%,./nvl;iadh9oh82"; | |
567 std::string png_base64 = "data:image/png;base64,ISQjJSwuL252bDtpYWRoOW9oODI="; | |
568 | |
569 FakeURLFetcherFactory factory; | |
570 factory.SetFakeResponse(logo_url, png_data, true); | |
571 | |
572 std::string json = | |
573 "{ " | |
574 " \"topic\": {" | |
575 " \"answers\": [" | |
576 " {" | |
577 " \"answer_id\": \"340252\"," | |
578 " \"name\": \"webstore_promo:15:1:" + logo_url + "\"," | |
579 " \"question\": \"Header!\"," | |
580 " \"inproduct_target\": \"The button label!\"," | |
581 " \"inproduct\": \"http://link.com\"," | |
582 " \"tooltip\": \"No thanks, hide this.\"" | |
583 " }" | |
584 " ]" | |
585 " }" | |
586 "}"; | |
587 | |
588 scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( | |
589 base::JSONReader::Read(json))); | |
590 | |
591 // Update the promo multiple times to verify the logo is cached correctly. | |
592 for (size_t i = 0; i < 2; ++i) { | |
593 web_resource_service_->UnpackWebStoreSignal(*(test_json.get())); | |
594 | |
595 // We should only need to run the message loop the first time since the | |
596 // image is then cached. | |
597 if (i == 0) | |
598 loop_.RunAllPending(); | |
599 | |
600 // Reset this scoped_ptr to prevent a DCHECK. | |
601 web_resource_service_->apps_promo_logo_fetcher_.reset(); | |
602 | |
603 AppsPromo::PromoData actual_data = AppsPromo::GetPromo(); | |
604 EXPECT_EQ("340252", actual_data.id); | |
605 EXPECT_EQ("Header!", actual_data.header); | |
606 EXPECT_EQ("The button label!", actual_data.button); | |
607 EXPECT_EQ(GURL("http://link.com"), actual_data.link); | |
608 EXPECT_EQ("No thanks, hide this.", actual_data.expire); | |
609 EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group); | |
610 | |
611 // The logo should now be a base64 DATA URL. | |
612 EXPECT_EQ(GURL(png_base64), actual_data.logo); | |
613 | |
614 // And the source pref should hold the source HTTPS URL. | |
615 EXPECT_EQ(GURL(logo_url), AppsPromo::GetSourcePromoLogoURL()); | |
616 } | |
617 } | |
618 | |
619 // Tests that we revert to the default logo when the fetch fails. | |
620 TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpsLogoError) { | |
621 web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV); | |
622 | |
623 std::string logo_url = "https://www.google.com/image/test.png"; | |
624 std::string png_data = "!$#%,./nvl;iadh9oh82"; | |
625 std::string png_base64 = "ISQjJSwuL252bDtpYWRoOW9oODI="; | |
626 | |
627 FakeURLFetcherFactory factory; | |
628 | |
629 // Have URLFetcher return a 500 error. | |
630 factory.SetFakeResponse(logo_url, png_data, false); | |
631 | |
632 std::string json = | |
633 "{ " | |
634 " \"topic\": {" | |
635 " \"answers\": [" | |
636 " {" | |
637 " \"answer_id\": \"340252\"," | |
638 " \"name\": \"webstore_promo:15:1:" + logo_url + "\"," | |
639 " \"question\": \"Header!\"," | |
640 " \"inproduct_target\": \"The button label!\"," | |
641 " \"inproduct\": \"http://link.com\"," | |
642 " \"tooltip\": \"No thanks, hide this.\"" | |
643 " }" | |
644 " ]" | |
645 " }" | |
646 "}"; | |
647 | |
648 scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( | |
649 base::JSONReader::Read(json))); | |
650 | |
651 web_resource_service_->UnpackWebStoreSignal(*(test_json.get())); | |
652 | |
653 loop_.RunAllPending(); | |
654 | |
655 // Reset this scoped_ptr to prevent a DCHECK. | |
656 web_resource_service_->apps_promo_logo_fetcher_.reset(); | |
657 | |
658 AppsPromo::PromoData actual_data = AppsPromo::GetPromo(); | |
659 EXPECT_EQ("340252", actual_data.id); | |
660 EXPECT_EQ("Header!", actual_data.header); | |
661 EXPECT_EQ("The button label!", actual_data.button); | |
662 EXPECT_EQ(GURL("http://link.com"), actual_data.link); | |
663 EXPECT_EQ("No thanks, hide this.", actual_data.expire); | |
664 EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group); | |
665 | |
666 // Logos are the default values. | |
667 EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo); | |
668 EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL()); | |
669 } | |
670 | |
671 // Tests that we don't download images over HTTP. | |
672 TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpLogo) { | |
673 web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV); | |
674 | |
675 // Use an HTTP URL. | |
676 std::string logo_url = "http://www.google.com/image/test.png"; | |
677 std::string png_data = "!$#%,./nvl;iadh9oh82"; | |
678 std::string png_base64 = "ISQjJSwuL252bDtpYWRoOW9oODI="; | |
679 | |
680 FakeURLFetcherFactory factory; | |
681 factory.SetFakeResponse(logo_url, png_data, true); | |
682 | |
683 std::string json = | |
684 "{ " | |
685 " \"topic\": {" | |
686 " \"answers\": [" | |
687 " {" | |
688 " \"answer_id\": \"340252\"," | |
689 " \"name\": \"webstore_promo:15:1:" + logo_url + "\"," | |
690 " \"question\": \"Header!\"," | |
691 " \"inproduct_target\": \"The button label!\"," | |
692 " \"inproduct\": \"http://link.com\"," | |
693 " \"tooltip\": \"No thanks, hide this.\"" | |
694 " }" | |
695 " ]" | |
696 " }" | |
697 "}"; | |
698 | |
699 scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( | |
700 base::JSONReader::Read(json))); | |
701 | |
702 web_resource_service_->UnpackWebStoreSignal(*(test_json.get())); | |
703 | |
704 loop_.RunAllPending(); | |
705 | |
706 // Reset this scoped_ptr to prevent a DCHECK. | |
707 web_resource_service_->apps_promo_logo_fetcher_.reset(); | |
708 | |
709 AppsPromo::PromoData actual_data = AppsPromo::GetPromo(); | |
710 EXPECT_EQ("340252", actual_data.id); | |
711 EXPECT_EQ("Header!", actual_data.header); | |
712 EXPECT_EQ("The button label!", actual_data.button); | |
713 EXPECT_EQ(GURL("http://link.com"), actual_data.link); | |
714 EXPECT_EQ("No thanks, hide this.", actual_data.expire); | |
715 EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group); | |
716 | |
717 // Logos should be the default values because HTTP URLs are not valid. | |
718 EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo); | |
719 EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL()); | |
720 } | |
721 | |
722 TEST_F(PromoResourceServiceTest, IsBuildTargetedTest) { | |
723 // canary | |
724 const chrome::VersionInfo::Channel canary = | |
725 chrome::VersionInfo::CHANNEL_CANARY; | |
726 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 1)); | |
727 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 3)); | |
728 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 7)); | |
729 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 15)); | |
730 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 8)); | |
731 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 11)); | |
732 | |
733 // dev | |
734 const chrome::VersionInfo::Channel dev = | |
735 chrome::VersionInfo::CHANNEL_DEV; | |
736 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(dev, 1)); | |
737 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(dev, 3)); | |
738 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(dev, 7)); | |
739 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(dev, 15)); | |
740 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(dev, 8)); | |
741 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(dev, 11)); | |
742 | |
743 // beta | |
744 const chrome::VersionInfo::Channel beta = | |
745 chrome::VersionInfo::CHANNEL_BETA; | |
746 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(beta, 1)); | |
747 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(beta, 3)); | |
748 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(beta, 7)); | |
749 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(beta, 15)); | |
750 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(beta, 8)); | |
751 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(beta, 11)); | |
752 | |
753 // stable | |
754 const chrome::VersionInfo::Channel stable = | |
755 chrome::VersionInfo::CHANNEL_STABLE; | |
756 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 1)); | |
757 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 3)); | |
758 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 7)); | |
759 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 15)); | |
760 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 8)); | |
761 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 11)); | |
762 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 12)); | |
763 | |
764 // invalid | |
765 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, -1)); | |
766 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, INT_MAX)); | |
767 } | |
OLD | NEW |