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 |