Home | History | Annotate | Download | only in background
      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 
     26 class 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 
     53 class 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 
    107 TEST_F(BackgroundContentsServiceTest, Create) {
    108   // Check for creation and leaks.
    109   TestingProfile profile;
    110   BackgroundContentsService service(&profile, command_line_.get());
    111 }
    112 
    113 TEST_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 
    124 TEST_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 
    151 TEST_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.
    172 TEST_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.
    204 TEST_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