background_contents_service_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string> 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/basictypes.h" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/command_line.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_service.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/background/background_contents_service.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/background/background_contents_service_factory.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/tab_contents/background_contents.h" 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/pref_names.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/test/base/testing_browser_process.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/test/base/testing_profile.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/notification_service.h" 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "testing/platform_test.h" 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/gurl.h" 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class BackgroundContentsServiceTest : public testing::Test { 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BackgroundContentsServiceTest() {} 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual ~BackgroundContentsServiceTest() {} 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void SetUp() { 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DictionaryValue* GetPrefs(Profile* profile) { 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return profile->GetPrefs()->GetDictionary( 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) prefs::kRegisteredBackgroundContents); 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Returns the stored pref URL for the passed app id. 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string GetPrefURLForApp(Profile* profile, const string16& appid) { 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DictionaryValue* pref = GetPrefs(profile); 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(pref->HasKey(UTF16ToUTF8(appid))); 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DictionaryValue* value; 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), &value); 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string url; 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value->GetString("url", &url); 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return url; 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<CommandLine> command_line_; 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class MockBackgroundContents : public BackgroundContents { 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public: 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) explicit MockBackgroundContents(Profile* profile) 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : appid_(ASCIIToUTF16("app_id")), 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile_(profile) { 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) MockBackgroundContents(Profile* profile, const std::string& id) 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : appid_(ASCIIToUTF16(id)), 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) profile_(profile) { 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void SendOpenedNotification(BackgroundContentsService* service) { 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) string16 frame_name = ASCIIToUTF16("background"); 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BackgroundContentsOpenedDetails details = { 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this, frame_name, appid_ }; 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) service->BackgroundContentsOpened(&details); 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void Navigate(GURL url) { 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) url_ = url; 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::current()->Notify( 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED, 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Source<Profile>(profile_), 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Details<BackgroundContents>(this)); 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual const GURL& GetURL() const OVERRIDE { return url_; } 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void MockClose(Profile* profile) { 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::current()->Notify( 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED, 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Source<Profile>(profile), 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Details<BackgroundContents>(this)); 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delete this; 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~MockBackgroundContents() { 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::NotificationService::current()->Notify( 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED, 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Source<Profile>(profile_), 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::Details<BackgroundContents>(this)); 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 95 const string16& appid() { return appid_; } 96 97 private: 98 GURL url_; 99 100 // The ID of our parent application 101 string16 appid_; 102 103 // Parent profile 104 Profile* profile_; 105}; 106 107TEST_F(BackgroundContentsServiceTest, Create) { 108 // Check for creation and leaks. 109 TestingProfile profile; 110 BackgroundContentsService service(&profile, command_line_.get()); 111} 112 113TEST_F(BackgroundContentsServiceTest, BackgroundContentsCreateDestroy) { 114 TestingProfile profile; 115 BackgroundContentsService service(&profile, command_line_.get()); 116 MockBackgroundContents* contents = new MockBackgroundContents(&profile); 117 EXPECT_FALSE(service.IsTracked(contents)); 118 contents->SendOpenedNotification(&service); 119 EXPECT_TRUE(service.IsTracked(contents)); 120 delete contents; 121 EXPECT_FALSE(service.IsTracked(contents)); 122} 123 124TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAdded) { 125 TestingProfile profile; 126 BackgroundContentsService service(&profile, command_line_.get()); 127 BackgroundContentsServiceFactory::GetInstance()-> 128 RegisterUserPrefsOnBrowserContext(&profile); 129 GURL orig_url; 130 GURL url("http://a/"); 131 GURL url2("http://a/"); 132 { 133 scoped_ptr<MockBackgroundContents> contents( 134 new MockBackgroundContents(&profile)); 135 EXPECT_EQ(0U, GetPrefs(&profile)->size()); 136 contents->SendOpenedNotification(&service); 137 138 contents->Navigate(url); 139 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 140 EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid())); 141 142 // Navigate the contents to a new url, should not change url. 143 contents->Navigate(url2); 144 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 145 EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid())); 146 } 147 // Contents are deleted, url should persist. 148 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 149} 150 151TEST_F(BackgroundContentsServiceTest, BackgroundContentsUrlAddedAndClosed) { 152 TestingProfile profile; 153 BackgroundContentsService service(&profile, command_line_.get()); 154 BackgroundContentsServiceFactory::GetInstance()-> 155 RegisterUserPrefsOnBrowserContext(&profile); 156 157 GURL url("http://a/"); 158 MockBackgroundContents* contents = new MockBackgroundContents(&profile); 159 EXPECT_EQ(0U, GetPrefs(&profile)->size()); 160 contents->SendOpenedNotification(&service); 161 contents->Navigate(url); 162 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 163 EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid())); 164 165 // Fake a window closed by script. 166 contents->MockClose(&profile); 167 EXPECT_EQ(0U, GetPrefs(&profile)->size()); 168} 169 170// Test what happens if a BackgroundContents shuts down (say, due to a renderer 171// crash) then is restarted. Should not persist URL twice. 172TEST_F(BackgroundContentsServiceTest, RestartBackgroundContents) { 173 TestingProfile profile; 174 BackgroundContentsService service(&profile, command_line_.get()); 175 BackgroundContentsServiceFactory::GetInstance()-> 176 RegisterUserPrefsOnBrowserContext(&profile); 177 178 GURL url("http://a/"); 179 { 180 scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents( 181 &profile, "appid")); 182 contents->SendOpenedNotification(&service); 183 contents->Navigate(url); 184 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 185 EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid())); 186 } 187 // Contents deleted, url should be persisted. 188 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 189 190 { 191 // Reopen the BackgroundContents to the same URL, we should not register the 192 // URL again. 193 scoped_ptr<MockBackgroundContents> contents(new MockBackgroundContents( 194 &profile, "appid")); 195 contents->SendOpenedNotification(&service); 196 contents->Navigate(url); 197 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 198 } 199} 200 201// Ensures that BackgroundContentsService properly tracks the association 202// between a BackgroundContents and its parent extension, including 203// unregistering the BC when the extension is uninstalled. 204TEST_F(BackgroundContentsServiceTest, TestApplicationIDLinkage) { 205 TestingProfile profile; 206 BackgroundContentsService service(&profile, command_line_.get()); 207 BackgroundContentsServiceFactory::GetInstance()-> 208 RegisterUserPrefsOnBrowserContext(&profile); 209 210 EXPECT_EQ(NULL, service.GetAppBackgroundContents(ASCIIToUTF16("appid"))); 211 MockBackgroundContents* contents = new MockBackgroundContents(&profile, 212 "appid"); 213 scoped_ptr<MockBackgroundContents> contents2( 214 new MockBackgroundContents(&profile, "appid2")); 215 contents->SendOpenedNotification(&service); 216 EXPECT_EQ(contents, service.GetAppBackgroundContents(contents->appid())); 217 contents2->SendOpenedNotification(&service); 218 EXPECT_EQ(contents2.get(), service.GetAppBackgroundContents( 219 contents2->appid())); 220 EXPECT_EQ(0U, GetPrefs(&profile)->size()); 221 222 // Navigate the contents, then make sure the one associated with the extension 223 // is unregistered. 224 GURL url("http://a/"); 225 GURL url2("http://b/"); 226 contents->Navigate(url); 227 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 228 contents2->Navigate(url2); 229 EXPECT_EQ(2U, GetPrefs(&profile)->size()); 230 service.ShutdownAssociatedBackgroundContents(ASCIIToUTF16("appid")); 231 EXPECT_FALSE(service.IsTracked(contents)); 232 EXPECT_EQ(NULL, service.GetAppBackgroundContents(ASCIIToUTF16("appid"))); 233 EXPECT_EQ(1U, GetPrefs(&profile)->size()); 234 EXPECT_EQ(url2.spec(), GetPrefURLForApp(&profile, contents2->appid())); 235} 236