Home | History | Annotate | Download | only in profiles
      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 "chrome/browser/profiles/profile_destroyer.h"
      6 
      7 #include "chrome/test/base/browser_with_test_window_test.h"
      8 #include "chrome/test/base/testing_profile.h"
      9 #include "content/public/browser/render_process_host.h"
     10 #include "content/public/browser/site_instance.h"
     11 
     12 class TestingOffTheRecordDestructionProfile : public TestingProfile {
     13  public:
     14   TestingOffTheRecordDestructionProfile()
     15       : TestingProfile(base::FilePath(),
     16                        NULL,
     17                        scoped_refptr<ExtensionSpecialStoragePolicy>()
     18                        scoped_ptr<PrefServiceSyncable>(),
     19                        true,
     20                        TestingFactories()),
     21         destroyed_otr_profile_(false) {
     22     set_incognito(true);
     23   }
     24   virtual void DestroyOffTheRecordProfile() OVERRIDE {
     25     destroyed_otr_profile_ = true;
     26   }
     27   bool destroyed_otr_profile_;
     28 
     29   DISALLOW_COPY_AND_ASSIGN(TestingOffTheRecordDestructionProfile);
     30 };
     31 
     32 class TestingOriginalDestructionProfile : public TestingProfile {
     33  public:
     34   TestingOriginalDestructionProfile() : destroyed_otr_profile_(false) {
     35     DCHECK_EQ(kNull, living_instance_);
     36     living_instance_ = this;
     37   }
     38   virtual ~TestingOriginalDestructionProfile() {
     39     DCHECK_EQ(this, living_instance_);
     40     living_instance_ = NULL;
     41   }
     42   virtual void DestroyOffTheRecordProfile() OVERRIDE {
     43     SetOffTheRecordProfile(NULL);
     44     destroyed_otr_profile_ = true;
     45   }
     46   bool destroyed_otr_profile_;
     47   static TestingOriginalDestructionProfile* living_instance_;
     48 
     49   // This is to avoid type casting in DCHECK_EQ & EXPECT_NE.
     50   static const TestingOriginalDestructionProfile* kNull;
     51 
     52   DISALLOW_COPY_AND_ASSIGN(TestingOriginalDestructionProfile);
     53 };
     54 const TestingOriginalDestructionProfile*
     55     TestingOriginalDestructionProfile::kNull = NULL;
     56 
     57 TestingOriginalDestructionProfile*
     58     TestingOriginalDestructionProfile::living_instance_ = NULL;
     59 
     60 class ProfileDestroyerTest : public BrowserWithTestWindowTest {
     61  public:
     62   ProfileDestroyerTest() : off_the_record_profile_(NULL) {}
     63 
     64  protected:
     65   virtual TestingProfile* CreateProfile() OVERRIDE {
     66     if (off_the_record_profile_ == NULL)
     67       off_the_record_profile_ = new TestingOffTheRecordDestructionProfile();
     68     return off_the_record_profile_;
     69   }
     70   TestingOffTheRecordDestructionProfile* off_the_record_profile_;
     71 
     72   DISALLOW_COPY_AND_ASSIGN(ProfileDestroyerTest);
     73 };
     74 
     75 TEST_F(ProfileDestroyerTest, DelayProfileDestruction) {
     76   scoped_refptr<content::SiteInstance> instance1(
     77       content::SiteInstance::Create(off_the_record_profile_));
     78   scoped_ptr<content::RenderProcessHost> render_process_host1;
     79   render_process_host1.reset(instance1->GetProcess());
     80   ASSERT_TRUE(render_process_host1.get() != NULL);
     81 
     82   scoped_refptr<content::SiteInstance> instance2(
     83       content::SiteInstance::Create(off_the_record_profile_));
     84   scoped_ptr<content::RenderProcessHost> render_process_host2;
     85   render_process_host2.reset(instance2->GetProcess());
     86   ASSERT_TRUE(render_process_host2.get() != NULL);
     87 
     88   // destroying the browser should not destroy the off the record profile...
     89   set_browser(NULL);
     90   EXPECT_FALSE(off_the_record_profile_->destroyed_otr_profile_);
     91 
     92   // until we destroy the render process host holding on to it...
     93   render_process_host1.release()->Cleanup();
     94 
     95   // And asynchronicity kicked in properly.
     96   base::MessageLoop::current()->RunUntilIdle();
     97   EXPECT_FALSE(off_the_record_profile_->destroyed_otr_profile_);
     98 
     99   // I meant, ALL the render process hosts... :-)
    100   render_process_host2.release()->Cleanup();
    101   base::MessageLoop::current()->RunUntilIdle();
    102   EXPECT_TRUE(off_the_record_profile_->destroyed_otr_profile_);
    103 }
    104 
    105 TEST_F(ProfileDestroyerTest, DelayOriginalProfileDestruction) {
    106   TestingOriginalDestructionProfile* original_profile =
    107       new TestingOriginalDestructionProfile;
    108 
    109   TestingOffTheRecordDestructionProfile* off_the_record_profile =
    110       new TestingOffTheRecordDestructionProfile;
    111 
    112   original_profile->SetOffTheRecordProfile(off_the_record_profile);
    113 
    114   scoped_refptr<content::SiteInstance> instance1(
    115       content::SiteInstance::Create(off_the_record_profile));
    116   scoped_ptr<content::RenderProcessHost> render_process_host1;
    117   render_process_host1.reset(instance1->GetProcess());
    118   ASSERT_TRUE(render_process_host1.get() != NULL);
    119 
    120   // Trying to destroy the original profile should be delayed until associated
    121   // off the record profile is released by all render process hosts.
    122   ProfileDestroyer::DestroyProfileWhenAppropriate(original_profile);
    123   EXPECT_NE(TestingOriginalDestructionProfile::kNull,
    124             TestingOriginalDestructionProfile::living_instance_);
    125   EXPECT_FALSE(original_profile->destroyed_otr_profile_);
    126 
    127   render_process_host1.release()->Cleanup();
    128   base::MessageLoop::current()->RunUntilIdle();
    129   EXPECT_EQ(NULL, TestingOriginalDestructionProfile::living_instance_);
    130 
    131   // And the same protection should apply to the main profile.
    132   TestingOriginalDestructionProfile* main_profile =
    133       new TestingOriginalDestructionProfile;
    134   scoped_refptr<content::SiteInstance> instance2(
    135       content::SiteInstance::Create(main_profile));
    136   scoped_ptr<content::RenderProcessHost> render_process_host2;
    137   render_process_host2.reset(instance2->GetProcess());
    138   ASSERT_TRUE(render_process_host2.get() != NULL);
    139 
    140   ProfileDestroyer::DestroyProfileWhenAppropriate(main_profile);
    141   EXPECT_EQ(main_profile, TestingOriginalDestructionProfile::living_instance_);
    142   render_process_host2.release()->Cleanup();
    143   base::MessageLoop::current()->RunUntilIdle();
    144   EXPECT_EQ(NULL, TestingOriginalDestructionProfile::living_instance_);
    145 }
    146