| 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 "chrome/browser/ui/tabs/tab_strip_model.h" | 5 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include "content/public/test/test_browser_thread.h" | 39 #include "content/public/test/test_browser_thread.h" |
| 40 #include "testing/gtest/include/gtest/gtest.h" | 40 #include "testing/gtest/include/gtest/gtest.h" |
| 41 | 41 |
| 42 using content::BrowserThread; | 42 using content::BrowserThread; |
| 43 using content::SiteInstance; | 43 using content::SiteInstance; |
| 44 using content::WebContents; | 44 using content::WebContents; |
| 45 using extensions::Extension; | 45 using extensions::Extension; |
| 46 | 46 |
| 47 namespace { | 47 namespace { |
| 48 | 48 |
| 49 // Class used to delete a WebContents when another WebContents is destroyed. | 49 // Class used to delete a WebContents and TabStripModel when another WebContents |
| 50 // is destroyed. |
| 50 class DeleteWebContentsOnDestroyedObserver | 51 class DeleteWebContentsOnDestroyedObserver |
| 51 : public content::NotificationObserver { | 52 : public content::NotificationObserver { |
| 52 public: | 53 public: |
| 54 // When |source| is deleted both |tab_to_delete| and |tab_strip| are deleted. |
| 55 // |tab_to_delete| and |tab_strip| may be NULL. |
| 53 DeleteWebContentsOnDestroyedObserver(WebContents* source, | 56 DeleteWebContentsOnDestroyedObserver(WebContents* source, |
| 54 WebContents* tab_to_delete) | 57 WebContents* tab_to_delete, |
| 58 TabStripModel* tab_strip) |
| 55 : source_(source), | 59 : source_(source), |
| 56 tab_to_delete_(tab_to_delete) { | 60 tab_to_delete_(tab_to_delete), |
| 61 tab_strip_(tab_strip) { |
| 57 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 62 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 58 content::Source<WebContents>(source)); | 63 content::Source<WebContents>(source)); |
| 59 } | 64 } |
| 60 | 65 |
| 61 virtual void Observe(int type, | 66 virtual void Observe(int type, |
| 62 const content::NotificationSource& source, | 67 const content::NotificationSource& source, |
| 63 const content::NotificationDetails& details) OVERRIDE { | 68 const content::NotificationDetails& details) OVERRIDE { |
| 64 WebContents* tab_to_delete = tab_to_delete_; | 69 WebContents* tab_to_delete = tab_to_delete_; |
| 65 tab_to_delete_ = NULL; | 70 tab_to_delete_ = NULL; |
| 71 TabStripModel* tab_strip_to_delete = tab_strip_; |
| 72 tab_strip_ = NULL; |
| 66 delete tab_to_delete; | 73 delete tab_to_delete; |
| 74 delete tab_strip_to_delete; |
| 67 } | 75 } |
| 68 | 76 |
| 69 private: | 77 private: |
| 70 WebContents* source_; | 78 WebContents* source_; |
| 71 WebContents* tab_to_delete_; | 79 WebContents* tab_to_delete_; |
| 80 TabStripModel* tab_strip_; |
| 72 content::NotificationRegistrar registrar_; | 81 content::NotificationRegistrar registrar_; |
| 73 | 82 |
| 74 DISALLOW_COPY_AND_ASSIGN(DeleteWebContentsOnDestroyedObserver); | 83 DISALLOW_COPY_AND_ASSIGN(DeleteWebContentsOnDestroyedObserver); |
| 75 }; | 84 }; |
| 76 | 85 |
| 77 class TabStripDummyDelegate : public TestTabStripModelDelegate { | 86 class TabStripDummyDelegate : public TestTabStripModelDelegate { |
| 78 public: | 87 public: |
| 79 TabStripDummyDelegate() : run_unload_(false) {} | 88 TabStripDummyDelegate() : run_unload_(false) {} |
| 80 virtual ~TabStripDummyDelegate() {} | 89 virtual ~TabStripDummyDelegate() {} |
| 81 | 90 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 208 } |
| 200 | 209 |
| 201 private: | 210 private: |
| 202 content::TestBrowserThread browser_thread_; | 211 content::TestBrowserThread browser_thread_; |
| 203 }; | 212 }; |
| 204 | 213 |
| 205 class MockTabStripModelObserver : public TabStripModelObserver { | 214 class MockTabStripModelObserver : public TabStripModelObserver { |
| 206 public: | 215 public: |
| 207 explicit MockTabStripModelObserver(TabStripModel* model) | 216 explicit MockTabStripModelObserver(TabStripModel* model) |
| 208 : empty_(true), | 217 : empty_(true), |
| 218 deleted_(false), |
| 209 model_(model) {} | 219 model_(model) {} |
| 210 virtual ~MockTabStripModelObserver() {} | 220 virtual ~MockTabStripModelObserver() {} |
| 211 | 221 |
| 212 enum TabStripModelObserverAction { | 222 enum TabStripModelObserverAction { |
| 213 INSERT, | 223 INSERT, |
| 214 CLOSE, | 224 CLOSE, |
| 215 DETACH, | 225 DETACH, |
| 216 ACTIVATE, | 226 ACTIVATE, |
| 217 DEACTIVATE, | 227 DEACTIVATE, |
| 218 SELECT, | 228 SELECT, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 s.src_contents = old_contents; | 332 s.src_contents = old_contents; |
| 323 states_.push_back(s); | 333 states_.push_back(s); |
| 324 } | 334 } |
| 325 virtual void TabPinnedStateChanged(WebContents* contents, | 335 virtual void TabPinnedStateChanged(WebContents* contents, |
| 326 int index) OVERRIDE { | 336 int index) OVERRIDE { |
| 327 states_.push_back(State(contents, index, PINNED)); | 337 states_.push_back(State(contents, index, PINNED)); |
| 328 } | 338 } |
| 329 virtual void TabStripEmpty() OVERRIDE { | 339 virtual void TabStripEmpty() OVERRIDE { |
| 330 empty_ = true; | 340 empty_ = true; |
| 331 } | 341 } |
| 342 virtual void TabStripModelDeleted() OVERRIDE { |
| 343 deleted_ = true; |
| 344 } |
| 332 | 345 |
| 333 void ClearStates() { | 346 void ClearStates() { |
| 334 states_.clear(); | 347 states_.clear(); |
| 335 } | 348 } |
| 336 | 349 |
| 337 bool empty() const { return empty_; } | 350 bool empty() const { return empty_; } |
| 351 bool deleted() const { return deleted_; } |
| 338 TabStripModel* model() { return model_; } | 352 TabStripModel* model() { return model_; } |
| 339 | 353 |
| 340 private: | 354 private: |
| 341 std::vector<State> states_; | 355 std::vector<State> states_; |
| 342 | 356 |
| 343 bool empty_; | 357 bool empty_; |
| 358 bool deleted_; |
| 344 TabStripModel* model_; | 359 TabStripModel* model_; |
| 345 | 360 |
| 346 DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); | 361 DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); |
| 347 }; | 362 }; |
| 348 | 363 |
| 349 TEST_F(TabStripModelTest, TestBasicAPI) { | 364 TEST_F(TabStripModelTest, TestBasicAPI) { |
| 350 TabStripDummyDelegate delegate; | 365 TabStripDummyDelegate delegate; |
| 351 TabStripModel tabstrip(&delegate, profile()); | 366 TabStripModel tabstrip(&delegate, profile()); |
| 352 MockTabStripModelObserver observer(&tabstrip); | 367 MockTabStripModelObserver observer(&tabstrip); |
| 353 tabstrip.AddObserver(&observer); | 368 tabstrip.AddObserver(&observer); |
| (...skipping 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2109 // another tab. | 2124 // another tab. |
| 2110 TEST_F(TabStripModelTest, DeleteFromDestroy) { | 2125 TEST_F(TabStripModelTest, DeleteFromDestroy) { |
| 2111 TabStripDummyDelegate delegate; | 2126 TabStripDummyDelegate delegate; |
| 2112 TabStripModel strip(&delegate, profile()); | 2127 TabStripModel strip(&delegate, profile()); |
| 2113 WebContents* contents1 = CreateWebContents(); | 2128 WebContents* contents1 = CreateWebContents(); |
| 2114 WebContents* contents2 = CreateWebContents(); | 2129 WebContents* contents2 = CreateWebContents(); |
| 2115 strip.AppendWebContents(contents1, true); | 2130 strip.AppendWebContents(contents1, true); |
| 2116 strip.AppendWebContents(contents2, true); | 2131 strip.AppendWebContents(contents2, true); |
| 2117 // DeleteWebContentsOnDestroyedObserver deletes contents1 when contents2 sends | 2132 // DeleteWebContentsOnDestroyedObserver deletes contents1 when contents2 sends |
| 2118 // out notification that it is being destroyed. | 2133 // out notification that it is being destroyed. |
| 2119 DeleteWebContentsOnDestroyedObserver observer(contents2, contents1); | 2134 DeleteWebContentsOnDestroyedObserver observer(contents2, contents1, NULL); |
| 2120 strip.CloseAllTabs(); | 2135 strip.CloseAllTabs(); |
| 2121 } | 2136 } |
| 2122 | 2137 |
| 2138 // Makes sure TabStripModel handles the case of deleting another tab and the |
| 2139 // TabStrip while removing another tab. |
| 2140 TEST_F(TabStripModelTest, DeleteTabStripFromDestroy) { |
| 2141 TabStripDummyDelegate delegate; |
| 2142 TabStripModel* strip = new TabStripModel(&delegate, profile()); |
| 2143 MockTabStripModelObserver tab_strip_model_observer(strip); |
| 2144 strip->AddObserver(&tab_strip_model_observer); |
| 2145 WebContents* contents1 = CreateWebContents(); |
| 2146 WebContents* contents2 = CreateWebContents(); |
| 2147 strip->AppendWebContents(contents1, true); |
| 2148 strip->AppendWebContents(contents2, true); |
| 2149 // DeleteWebContentsOnDestroyedObserver deletes |contents1| and |strip| when |
| 2150 // |contents2| sends out notification that it is being destroyed. |
| 2151 DeleteWebContentsOnDestroyedObserver observer(contents2, contents1, strip); |
| 2152 strip->CloseAllTabs(); |
| 2153 EXPECT_TRUE(tab_strip_model_observer.empty()); |
| 2154 EXPECT_TRUE(tab_strip_model_observer.deleted()); |
| 2155 } |
| 2156 |
| 2123 TEST_F(TabStripModelTest, MoveSelectedTabsTo) { | 2157 TEST_F(TabStripModelTest, MoveSelectedTabsTo) { |
| 2124 struct TestData { | 2158 struct TestData { |
| 2125 // Number of tabs the tab strip should have. | 2159 // Number of tabs the tab strip should have. |
| 2126 const int tab_count; | 2160 const int tab_count; |
| 2127 | 2161 |
| 2128 // Number of pinned tabs. | 2162 // Number of pinned tabs. |
| 2129 const int pinned_count; | 2163 const int pinned_count; |
| 2130 | 2164 |
| 2131 // Index of the tabs to select. | 2165 // Index of the tabs to select. |
| 2132 const std::string selected_tabs; | 2166 const std::string selected_tabs; |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2333 strip.ActivateTabAt(1, true); | 2367 strip.ActivateTabAt(1, true); |
| 2334 ASSERT_EQ(1, observer.GetStateCount()); | 2368 ASSERT_EQ(1, observer.GetStateCount()); |
| 2335 State s(contents2, 1, MockTabStripModelObserver::SELECT); | 2369 State s(contents2, 1, MockTabStripModelObserver::SELECT); |
| 2336 s.src_contents = contents2; | 2370 s.src_contents = contents2; |
| 2337 s.src_index = 1; | 2371 s.src_index = 1; |
| 2338 s.change_reason = TabStripModelObserver::CHANGE_REASON_NONE; | 2372 s.change_reason = TabStripModelObserver::CHANGE_REASON_NONE; |
| 2339 EXPECT_TRUE(observer.StateEquals(0, s)); | 2373 EXPECT_TRUE(observer.StateEquals(0, s)); |
| 2340 strip.RemoveObserver(&observer); | 2374 strip.RemoveObserver(&observer); |
| 2341 strip.CloseAllTabs(); | 2375 strip.CloseAllTabs(); |
| 2342 } | 2376 } |
| OLD | NEW |