background_contents_service_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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 <string> 6 7#include "base/basictypes.h" 8#include "base/command_line.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/prefs/pref_service.h" 11#include "base/strings/utf_string_conversions.h" 12#include "chrome/browser/background/background_contents_service.h" 13#include "chrome/browser/background/background_contents_service_factory.h" 14#include "chrome/browser/chrome_notification_types.h" 15#include "chrome/browser/prefs/scoped_user_pref_update.h" 16#include "chrome/browser/tab_contents/background_contents.h" 17#include "chrome/browser/ui/browser_list.h" 18#include "chrome/common/pref_names.h" 19#include "chrome/test/base/testing_browser_process.h" 20#include "chrome/test/base/testing_profile.h" 21#include "content/public/browser/notification_service.h" 22#include "testing/gtest/include/gtest/gtest.h" 23#include "testing/platform_test.h" 24#include "url/gurl.h" 25 26class BackgroundContentsServiceTest : public testing::Test { 27 public: 28 BackgroundContentsServiceTest() {} 29 virtual ~BackgroundContentsServiceTest() {} 30 virtual void SetUp() { 31 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); 32 } 33 34 const DictionaryValue* GetPrefs(Profile* profile) { 35 return profile->GetPrefs()->GetDictionary( 36 prefs::kRegisteredBackgroundContents); 37 } 38 39 // Returns the stored pref URL for the passed app id. 40 std::string GetPrefURLForApp(Profile* profile, const string16& appid) { 41 const DictionaryValue* pref = GetPrefs(profile); 42 EXPECT_TRUE(pref->HasKey(UTF16ToUTF8(appid))); 43 const DictionaryValue* value; 44 pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), &value); 45 std::string url; 46 value->GetString("url", &url); 47 return url; 48 } 49 50 scoped_ptr<CommandLine> command_line_; 51}; 52 53class MockBackgroundContents : public BackgroundContents { 54 public: 55 explicit MockBackgroundContents(Profile* profile) 56 : appid_(ASCIIToUTF16("app_id")), 57 profile_(profile) { 58 } 59 MockBackgroundContents(Profile* profile, const std::string& id) 60 : appid_(ASCIIToUTF16(id)), 61 profile_(profile) { 62 } 63 64 void SendOpenedNotification(BackgroundContentsService* service) { 65 string16 frame_name = ASCIIToUTF16("background"); 66 BackgroundContentsOpenedDetails details = { 67 this, frame_name, appid_ }; 68 service->BackgroundContentsOpened(&details); 69 } 70 71 virtual void Navigate(GURL url) { 72 url_ = url; 73 content::NotificationService::current()->Notify( 74 chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED, 75 content::Source<Profile>(profile_), 76 content::Details<BackgroundContents>(this)); 77 } 78 virtual const GURL& GetURL() const OVERRIDE { return url_; } 79 80 void MockClose(Profile* profile) { 81 content::NotificationService::current()->Notify( 82 chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED, 83 content::Source<Profile>(profile), 84 content::Details<BackgroundContents>(this)); 85 delete this; 86 } 87 88 virtual ~MockBackgroundContents() { 89 content::NotificationService::current()->Notify( 90 chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED, 91 content::Source<Profile>(profile_), 92 content::Details<BackgroundContents>(this)); 93 } 94 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