| Index: chrome/browser/sessions/session_restore_uitest.cc
|
| ===================================================================
|
| --- chrome/browser/sessions/session_restore_uitest.cc (revision 133679)
|
| +++ chrome/browser/sessions/session_restore_uitest.cc (working copy)
|
| @@ -1,491 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/file_path.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "base/test/test_timeouts.h"
|
| -#include "chrome/app/chrome_command_ids.h"
|
| -#include "chrome/browser/defaults.h"
|
| -#include "chrome/common/chrome_paths.h"
|
| -#include "chrome/common/chrome_switches.h"
|
| -#include "chrome/common/url_constants.h"
|
| -#include "chrome/test/automation/automation_proxy.h"
|
| -#include "chrome/test/automation/browser_proxy.h"
|
| -#include "chrome/test/automation/tab_proxy.h"
|
| -#include "chrome/test/automation/window_proxy.h"
|
| -#include "chrome/test/ui/ui_test.h"
|
| -#include "googleurl/src/gurl.h"
|
| -#include "net/base/net_util.h"
|
| -#include "net/test/test_server.h"
|
| -
|
| -namespace {
|
| -
|
| -class SessionRestoreUITest : public UITest {
|
| - protected:
|
| - SessionRestoreUITest() : UITest() {
|
| - FilePath path_prefix = test_data_directory_.AppendASCII("session_history");
|
| -
|
| - url1_ = net::FilePathToFileURL(path_prefix.AppendASCII("bot1.html"));
|
| - url2_ = net::FilePathToFileURL(path_prefix.AppendASCII("bot2.html"));
|
| - url3_ = net::FilePathToFileURL(path_prefix.AppendASCII("bot3.html"));
|
| - }
|
| -
|
| - virtual void QuitBrowserAndRestore(int expected_tab_count) {
|
| -#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
|
| - set_shutdown_type(ProxyLauncher::USER_QUIT);
|
| -#endif
|
| - UITest::TearDown();
|
| -
|
| - clear_profile_ = false;
|
| -
|
| - // Clear launch_arguments so that the URL arg doesn't get added on restart.
|
| - launch_arguments_ = CommandLine(launch_arguments_.GetProgram());
|
| -
|
| - launch_arguments_.AppendSwitchASCII(switches::kRestoreLastSession,
|
| - base::IntToString(expected_tab_count));
|
| - UITest::SetUp();
|
| - }
|
| -
|
| - void CloseWindow(int window_index, int initial_count) {
|
| - scoped_refptr<BrowserProxy> browser_proxy(
|
| - automation()->GetBrowserWindow(window_index));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| - ASSERT_TRUE(browser_proxy->RunCommand(IDC_CLOSE_WINDOW));
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(initial_count - 1, window_count);
|
| - }
|
| -
|
| - void AssertOneWindowWithOneTab() {
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - GURL url;
|
| - AssertWindowHasOneTab(0, &url);
|
| - }
|
| -
|
| - void AssertWindowHasOneTab(int window_index, GURL* url) {
|
| - scoped_refptr<BrowserProxy> browser_proxy(
|
| - automation()->GetBrowserWindow(window_index));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| -
|
| - int tab_count;
|
| - ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
|
| - ASSERT_EQ(1, tab_count);
|
| -
|
| - int active_tab_index;
|
| - ASSERT_TRUE(browser_proxy->GetActiveTabIndex(&active_tab_index));
|
| - ASSERT_EQ(0, active_tab_index);
|
| -
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetActiveTab());
|
| - ASSERT_TRUE(tab_proxy.get());
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| -
|
| - ASSERT_TRUE(tab_proxy->GetCurrentURL(url));
|
| - }
|
| -
|
| - GURL url1_;
|
| - GURL url2_;
|
| - GURL url3_;
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(SessionRestoreUITest);
|
| -};
|
| -
|
| -TEST_F(SessionRestoreUITest, Basic) {
|
| - NavigateToURL(url1_);
|
| - NavigateToURL(url2_);
|
| -
|
| - QuitBrowserAndRestore(1);
|
| -
|
| - // NOTE: Don't use GetActiveWindow here, when run with the screen locked
|
| - // active windows returns NULL.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| -
|
| - ASSERT_EQ(url2_, GetActiveTabURL());
|
| - ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab_proxy->GoBack());
|
| - ASSERT_EQ(url1_, GetActiveTabURL());
|
| -}
|
| -
|
| -TEST_F(SessionRestoreUITest, RestoresForwardAndBackwardNavs) {
|
| - NavigateToURL(url1_);
|
| - NavigateToURL(url2_);
|
| - NavigateToURL(url3_);
|
| -
|
| - scoped_refptr<TabProxy> active_tab(GetActiveTab());
|
| - ASSERT_TRUE(active_tab.get());
|
| - ASSERT_TRUE(active_tab->GoBack());
|
| -
|
| - QuitBrowserAndRestore(1);
|
| -
|
| - // NOTE: Don't use GetActiveWindow here, when run with the screen locked
|
| - // active windows returns NULL.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| -
|
| - ASSERT_TRUE(GetActiveTabURL() == url2_);
|
| - ASSERT_TRUE(tab_proxy->GoForward());
|
| - ASSERT_TRUE(GetActiveTabURL() == url3_);
|
| - ASSERT_TRUE(tab_proxy->GoBack());
|
| - ASSERT_TRUE(GetActiveTabURL() == url2_);
|
| -
|
| - // Test renderer-initiated back/forward as well.
|
| - GURL go_back_url("javascript:history.back();");
|
| - ASSERT_TRUE(tab_proxy->NavigateToURL(go_back_url));
|
| - ASSERT_TRUE(GetActiveTabURL() == url1_);
|
| -}
|
| -
|
| -// Tests that the SiteInstances used for entries in a restored tab's history
|
| -// are given appropriate max page IDs, so that going back to a restored
|
| -// cross-site page and then forward again works. (Bug 1204135)
|
| -TEST_F(SessionRestoreUITest, RestoresCrossSiteForwardAndBackwardNavs) {
|
| - net::TestServer test_server(net::TestServer::TYPE_HTTP,
|
| - net::TestServer::kLocalhost,
|
| - FilePath(FILE_PATH_LITERAL("chrome/test/data")));
|
| - ASSERT_TRUE(test_server.Start());
|
| -
|
| - GURL cross_site_url(test_server.GetURL("files/title2.html"));
|
| -
|
| - // Visit URLs on different sites.
|
| - NavigateToURL(url1_);
|
| - NavigateToURL(cross_site_url);
|
| - NavigateToURL(url2_);
|
| -
|
| - scoped_refptr<TabProxy> active_tab(GetActiveTab());
|
| - ASSERT_TRUE(active_tab.get());
|
| - ASSERT_TRUE(active_tab->GoBack());
|
| -
|
| - QuitBrowserAndRestore(1);
|
| -
|
| - // NOTE: Don't use GetActiveWindow here, when run with the screen locked
|
| - // active windows returns NULL.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| - int tab_count;
|
| - ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
|
| - ASSERT_EQ(1, tab_count);
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
|
| - ASSERT_TRUE(tab_proxy.get());
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| -
|
| - // Check that back and forward work as expected.
|
| - GURL url;
|
| - ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
|
| - ASSERT_EQ(cross_site_url, url);
|
| -
|
| - ASSERT_TRUE(tab_proxy->GoBack());
|
| - ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
|
| - ASSERT_EQ(url1_, url);
|
| -
|
| - ASSERT_TRUE(tab_proxy->GoForward());
|
| - ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
|
| - ASSERT_EQ(cross_site_url, url);
|
| -
|
| - // Test renderer-initiated back/forward as well.
|
| - GURL go_forward_url("javascript:history.forward();");
|
| - ASSERT_TRUE(tab_proxy->NavigateToURL(go_forward_url));
|
| - ASSERT_TRUE(tab_proxy->GetCurrentURL(&url));
|
| - ASSERT_EQ(url2_, url);
|
| -}
|
| -
|
| -TEST_F(SessionRestoreUITest, TwoTabsSecondSelected) {
|
| - NavigateToURL(url1_);
|
| -
|
| - // NOTE: Don't use GetActiveWindow here, when run with the screen locked
|
| - // active windows returns NULL.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| -
|
| - ASSERT_TRUE(browser_proxy->AppendTab(url2_));
|
| -
|
| - QuitBrowserAndRestore(2);
|
| - browser_proxy = NULL;
|
| -
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - browser_proxy = automation()->GetBrowserWindow(0);
|
| -
|
| - int tab_count;
|
| - ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
|
| - ASSERT_EQ(2, tab_count);
|
| -
|
| - int active_tab_index;
|
| - ASSERT_TRUE(browser_proxy->GetActiveTabIndex(&active_tab_index));
|
| - ASSERT_EQ(1, active_tab_index);
|
| -
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetActiveTab());
|
| - ASSERT_TRUE(tab_proxy.get());
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| -
|
| - ASSERT_EQ(url2_, GetActiveTabURL());
|
| -
|
| - ASSERT_TRUE(browser_proxy->ActivateTab(0));
|
| - tab_proxy = browser_proxy->GetActiveTab();
|
| - ASSERT_TRUE(tab_proxy.get());
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| -
|
| - ASSERT_EQ(url1_, GetActiveTabURL());
|
| -}
|
| -
|
| -// Creates two tabs, closes one, quits and makes sure only one tab is restored.
|
| -TEST_F(SessionRestoreUITest, ClosedTabStaysClosed) {
|
| - NavigateToURL(url1_);
|
| -
|
| - // NOTE: Don't use GetActiveWindow here, when run with the screen locked
|
| - // active windows returns NULL.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(0));
|
| - ASSERT_TRUE(tab_proxy.get());
|
| -
|
| - ASSERT_TRUE(browser_proxy->AppendTab(url2_));
|
| -
|
| - scoped_refptr<TabProxy> active_tab(browser_proxy->GetActiveTab());
|
| - ASSERT_TRUE(active_tab.get());
|
| - ASSERT_TRUE(active_tab->Close(true));
|
| -
|
| - QuitBrowserAndRestore(1);
|
| - browser_proxy = NULL;
|
| - tab_proxy = NULL;
|
| -
|
| - AssertOneWindowWithOneTab();
|
| -
|
| - ASSERT_EQ(url1_, GetActiveTabURL());
|
| -}
|
| -
|
| -// Test to verify that the print preview tab is not restored.
|
| -TEST_F(SessionRestoreUITest, DontRestorePrintPreviewTabTest) {
|
| - NavigateToURL(url1_);
|
| -
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get());
|
| -
|
| - // Append the print preview tab.
|
| - GURL printPreviewURL(chrome::kChromeUIPrintURL);
|
| - ASSERT_TRUE(browser_proxy->AppendTab(printPreviewURL));
|
| -
|
| - scoped_refptr<TabProxy> active_tab(browser_proxy->GetActiveTab());
|
| - ASSERT_TRUE(active_tab.get());
|
| - ASSERT_EQ(printPreviewURL, GetActiveTabURL());
|
| -
|
| - // Restart and make sure we have only one window with one tab and the url
|
| - // is url1_.
|
| - QuitBrowserAndRestore(1);
|
| - browser_proxy = NULL;
|
| -
|
| - AssertOneWindowWithOneTab();
|
| -
|
| - ASSERT_EQ(url1_, GetActiveTabURL());
|
| -}
|
| -
|
| -// Creates a tabbed browser and popup and makes sure we restore both.
|
| -TEST_F(SessionRestoreUITest, NormalAndPopup) {
|
| - if (!browser_defaults::kRestorePopups)
|
| - return; // Test only applicable if restoring popups.
|
| -
|
| - NavigateToURL(url1_);
|
| -
|
| - // Make sure we have one window.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| -
|
| - // Open a popup.
|
| - ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_POPUP,
|
| - true));
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(2, window_count);
|
| -
|
| - scoped_refptr<BrowserProxy> popup(automation()->GetBrowserWindow(1));
|
| - ASSERT_TRUE(popup.get());
|
| -
|
| - scoped_refptr<TabProxy> tab(popup->GetTab(0));
|
| - ASSERT_TRUE(tab.get());
|
| -
|
| - ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(url1_));
|
| -
|
| - // Simulate an exit by shuting down the session service. If we don't do this
|
| - // the first window close is treated as though the user closed the window
|
| - // and won't be restored.
|
| - ASSERT_TRUE(popup->ShutdownSessionService());
|
| -
|
| - tab = NULL;
|
| - popup = NULL;
|
| -
|
| - // Restart and make sure we have only one window with one tab and the url
|
| - // is url1_.
|
| - QuitBrowserAndRestore(1);
|
| -
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(2, window_count);
|
| -
|
| - scoped_refptr<BrowserProxy> browser_proxy1(
|
| - automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy1.get());
|
| -
|
| - scoped_refptr<BrowserProxy> browser_proxy2(
|
| - automation()->GetBrowserWindow(1));
|
| - ASSERT_TRUE(browser_proxy2.get());
|
| -
|
| - Browser::Type type1, type2;
|
| - ASSERT_TRUE(browser_proxy1->GetType(&type1));
|
| - ASSERT_TRUE(browser_proxy2->GetType(&type2));
|
| -
|
| - // The order of whether the normal window or popup is first depends upon
|
| - // activation order, which is not necessarily consistant across runs.
|
| - if (type1 == Browser::TYPE_TABBED) {
|
| - EXPECT_EQ(type2, Browser::TYPE_POPUP);
|
| - } else {
|
| - EXPECT_EQ(type1, Browser::TYPE_POPUP);
|
| - EXPECT_EQ(type2, Browser::TYPE_TABBED);
|
| - }
|
| -}
|
| -
|
| -#if !defined(OS_MACOSX)
|
| -// This test doesn't apply to the Mac version; see
|
| -// LaunchAnotherBrowserBlockUntilClosed for details.
|
| -
|
| -// Launches an app window, closes tabbed browser, launches and makes sure
|
| -// we restore the tabbed browser url.
|
| -// Flaky: http://crbug.com/29110
|
| -TEST_F(SessionRestoreUITest,
|
| - DISABLED_RestoreAfterClosingTabbedBrowserWithAppAndLaunching) {
|
| - NavigateToURL(url1_);
|
| -
|
| - // Launch an app.
|
| -
|
| - bool include_testing_id_orig = include_testing_id_;
|
| - include_testing_id_ = false;
|
| - clear_profile_ = false;
|
| - CommandLine app_launch_arguments = launch_arguments_;
|
| - app_launch_arguments.AppendSwitchASCII(switches::kApp, url2_.spec());
|
| - LaunchAnotherBrowserBlockUntilClosed(app_launch_arguments);
|
| - ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2));
|
| -
|
| - // Close the first window. The only window left is the App window.
|
| - CloseWindow(0, 2);
|
| -
|
| - // Restore the session, which should bring back the first window with url1_.
|
| - // First restore the settings so we can connect to the browser.
|
| - include_testing_id_ = include_testing_id_orig;
|
| - // Restore the session with 1 tab.
|
| - QuitBrowserAndRestore(1);
|
| -
|
| - AssertOneWindowWithOneTab();
|
| -
|
| - ASSERT_EQ(url1_, GetActiveTabURL());
|
| -}
|
| -
|
| -#endif // !OS_MACOSX
|
| -
|
| -// Creates two windows, closes one, restores, make sure only one window open.
|
| -TEST_F(SessionRestoreUITest, TwoWindowsCloseOneRestoreOnlyOne) {
|
| - NavigateToURL(url1_);
|
| -
|
| - // Make sure we have one window.
|
| - int window_count;
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(1, window_count);
|
| -
|
| - // Open a second window.
|
| - ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_TABBED,
|
| - true));
|
| - ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
|
| - ASSERT_EQ(2, window_count);
|
| -
|
| - // Close it.
|
| - CloseWindow(1, 2);
|
| -
|
| - // Restart and make sure we have only one window with one tab and the url
|
| - // is url1_.
|
| - QuitBrowserAndRestore(1);
|
| -
|
| - AssertOneWindowWithOneTab();
|
| -
|
| - ASSERT_EQ(url1_, GetActiveTabURL());
|
| -}
|
| -
|
| -// Make sure after a restore the number of processes matches that of the number
|
| -// of processes running before the restore. This creates a new tab so that
|
| -// we should have two new tabs running. (This test will pass in both
|
| -// process-per-site and process-per-site-instance, because we treat the new tab
|
| -// as a special case in process-per-site-instance so that it only ever uses one
|
| -// process.)
|
| -//
|
| -// Flaky: http://code.google.com/p/chromium/issues/detail?id=52022
|
| -// Unfortunately, the fix at http://codereview.chromium.org/6546078
|
| -// breaks NTP background image refreshing, so ThemeSource had to revert to
|
| -// replacing the existing data source.
|
| -TEST_F(SessionRestoreUITest, DISABLED_ShareProcessesOnRestore) {
|
| - scoped_refptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
|
| - ASSERT_TRUE(browser_proxy.get() != NULL);
|
| - int tab_count;
|
| - ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
|
| -
|
| - // Create two new tabs.
|
| - ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_TAB));
|
| - ASSERT_TRUE(browser_proxy->RunCommand(IDC_NEW_TAB));
|
| - int new_tab_count;
|
| - ASSERT_TRUE(browser_proxy->GetTabCount(&new_tab_count));
|
| - ASSERT_EQ(tab_count + 2, new_tab_count);
|
| -
|
| - int expected_process_count = 0;
|
| - ASSERT_TRUE(GetBrowserProcessCount(&expected_process_count));
|
| - int expected_tab_count = new_tab_count;
|
| -
|
| - // Restart.
|
| - browser_proxy = NULL;
|
| - QuitBrowserAndRestore(3);
|
| -
|
| - // Wait for each tab to finish being restored, then make sure the process
|
| - // count matches.
|
| - browser_proxy = automation()->GetBrowserWindow(0);
|
| - ASSERT_TRUE(browser_proxy.get() != NULL);
|
| - ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
|
| - ASSERT_EQ(expected_tab_count, tab_count);
|
| -
|
| - for (int i = 0; i < expected_tab_count; ++i) {
|
| - scoped_refptr<TabProxy> tab_proxy(browser_proxy->GetTab(i));
|
| - ASSERT_TRUE(tab_proxy.get() != NULL);
|
| - ASSERT_TRUE(tab_proxy->WaitForTabToBeRestored(
|
| - TestTimeouts::action_max_timeout_ms()));
|
| - }
|
| -
|
| - int process_count = 0;
|
| - ASSERT_TRUE(GetBrowserProcessCount(&process_count));
|
| - ASSERT_EQ(expected_process_count, process_count);
|
| -}
|
| -
|
| -} // namespace
|
|
|