diff options
author | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-21 19:37:09 +0000 |
---|---|---|
committer | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-21 19:37:09 +0000 |
commit | ca17d03744b3f8b3ce31e82164e10b3c4a96ad8e (patch) | |
tree | 4c7adadd629e9978e5cbab7afeff2a19e6fceaba /chrome/browser/ui | |
parent | 669c46eed0f7df6774ff807b22d6946491525cdf (diff) | |
download | chromium_src-ca17d03744b3f8b3ce31e82164e10b3c4a96ad8e.zip chromium_src-ca17d03744b3f8b3ce31e82164e10b3c4a96ad8e.tar.gz chromium_src-ca17d03744b3f8b3ce31e82164e10b3c4a96ad8e.tar.bz2 |
Revert 72153 - Remove user-related data from local_state and add to user_preferences, in preparation for multi-profile.
devtools
kDevToolsSplitLocation
browser
kBrowserWindowPlacement
Also add a method to browser_prefs to delete obsolete preferences from local state, and fix all related tests.
BUG=66717
TEST=all browser, interactive, and ui tests work properly
Review URL: http://codereview.chromium.org/5915006
TBR=mirandac@chromium.org
Review URL: http://codereview.chromium.org/6247017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72175 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui')
-rw-r--r-- | chrome/browser/ui/browser.cc | 21 | ||||
-rw-r--r-- | chrome/browser/ui/browser.h | 7 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/browser_window_controller.mm | 6 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/browser_window_controller_private.mm | 7 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/browser_window_controller_unittest.mm | 4 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/dev_tools_controller.h | 6 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/dev_tools_controller.mm | 19 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/browser_window_gtk.cc | 14 | ||||
-rw-r--r-- | chrome/browser/ui/views/chrome_views_delegate.cc | 20 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/browser_view.cc | 8 | ||||
-rw-r--r-- | chrome/browser/ui/window_sizer.cc | 19 | ||||
-rw-r--r-- | chrome/browser/ui/window_sizer.h | 5 |
12 files changed, 63 insertions, 73 deletions
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 81fb6db..54f8677 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -543,7 +543,7 @@ TabContents* Browser::OpenApplicationWindow( else app_name = web_app::GenerateApplicationNameFromURL(url); - RegisterAppPrefs(app_name, profile); + RegisterAppPrefs(app_name); bool as_panel = extension && (container == extension_misc::LAUNCH_PANEL); @@ -739,7 +739,7 @@ gfx::Rect Browser::GetSavedWindowBounds() const { gfx::Rect restored_bounds = override_bounds_; bool maximized; - WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this, + WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL, &restored_bounds, &maximized); return restored_bounds; } @@ -758,7 +758,7 @@ bool Browser::GetSavedMaximizedState() const { // An explicit maximized state was not set. Query the window sizer. gfx::Rect restored_bounds; bool maximized = false; - WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, this, + WindowSizer::GetBrowserWindowBounds(app_name_, restored_bounds, NULL, &restored_bounds, &maximized); return maximized; } @@ -1974,10 +1974,11 @@ void Browser::SetNewHomePagePrefs(PrefService* prefs) { // static void Browser::RegisterPrefs(PrefService* prefs) { + prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement); prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0); + prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1); prefs->RegisterDictionaryPref(prefs::kPreferencesWindowPlacement); prefs->RegisterIntegerPref(prefs::kExtensionSidebarWidth, -1); - prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0); // Educated guess: Chrome has a bundled Flash version supporting // clearing LSO data, Chromium hasn't. #if defined(GOOGLE_CHROME_BUILD) @@ -2025,8 +2026,7 @@ void Browser::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterStringPref(prefs::kCloudPrintEmail, std::string()); prefs->RegisterBooleanPref(prefs::kDevToolsDisabled, false); prefs->RegisterRealPref(prefs::kDefaultZoomLevel, 0.0); - prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1); - prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement); + prefs->RegisterIntegerPref(prefs::kMultipleProfilePrefMigration, 0); // We need to register the type of this preference in order to query // it even though it's only typically controlled via policy. prefs->RegisterBooleanPref(prefs::kDisable3DAPIs, false); @@ -2964,7 +2964,7 @@ bool Browser::IsApplication() const { void Browser::ConvertContentsToApplication(TabContents* contents) { const GURL& url = contents->controller().GetActiveEntry()->url(); std::string app_name = web_app::GenerateApplicationNameFromURL(url); - RegisterAppPrefs(app_name, contents->profile()); + RegisterAppPrefs(app_name); DetachContents(contents); Browser* app_browser = Browser::CreateForApp( @@ -4118,7 +4118,7 @@ void Browser::TabDetachedAtImpl(TabContentsWrapper* contents, int index, } // static -void Browser::RegisterAppPrefs(const std::string& app_name, Profile* profile) { +void Browser::RegisterAppPrefs(const std::string& app_name) { // A set of apps that we've already started. static std::set<std::string>* g_app_names = NULL; @@ -4134,7 +4134,10 @@ void Browser::RegisterAppPrefs(const std::string& app_name, Profile* profile) { std::string window_pref(prefs::kBrowserWindowPlacement); window_pref.append("_"); window_pref.append(app_name); - profile->GetPrefs()->RegisterDictionaryPref(window_pref.c_str()); + PrefService* prefs = g_browser_process->local_state(); + DCHECK(prefs); + + prefs->RegisterDictionaryPref(window_pref.c_str()); } void Browser::TabRestoreServiceChanged(TabRestoreService* service) { diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 63f7d5c..a72e7e9 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -959,10 +959,9 @@ class Browser : public TabHandlerDelegate, void TabDetachedAtImpl(TabContentsWrapper* contents, int index, DetachType type); - // Create a preference dictionary for the provided application name, in the - // given user profile. This is done only once per application name / per - // session / per user profile. - static void RegisterAppPrefs(const std::string& app_name, Profile* profile); + // Create a preference dictionary for the provided application name. This is + // done only once per application name / per session. + static void RegisterAppPrefs(const std::string& app_name); // Shared code between Reload() and ReloadIgnoringCache(). void ReloadInternal(WindowOpenDisposition disposition, bool ignore_cache); diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 9ad91e5..d761f54 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm @@ -479,8 +479,7 @@ } - (void)updateDevToolsForContents:(TabContents*)contents { - [devToolsController_ updateDevToolsForTabContents:contents - withProfile:browser_->profile()]; + [devToolsController_ updateDevToolsForTabContents:contents]; [devToolsController_ ensureContentsVisible]; } @@ -1429,8 +1428,7 @@ windowShim_->UpdateTitleBar(); [sidebarController_ updateSidebarForTabContents:contents]; - [devToolsController_ updateDevToolsForTabContents:contents - withProfile:browser_->profile()]; + [devToolsController_ updateDevToolsForTabContents:contents]; // Update the bookmark bar. // Must do it after sidebar and devtools update, otherwise bookmark bar might diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 5898ba5..73c6e01 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm @@ -62,12 +62,11 @@ const CGFloat kLocBarBottomInset = 1; if (browser_ != BrowserList::GetLastActive()) return; - if (!browser_->profile()->GetPrefs() || - !browser_->ShouldSaveWindowPlacement()) { + if (!g_browser_process || !g_browser_process->local_state() || + !browser_->ShouldSaveWindowPlacement()) return; - } - [self saveWindowPositionToPrefs:browser_->profile()->GetPrefs()]; + [self saveWindowPositionToPrefs:g_browser_process->local_state()]; } - (void)saveWindowPositionToPrefs:(PrefService*)prefs { diff --git a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm index 6fd75b4..4351532 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm @@ -88,7 +88,9 @@ TEST_F(BrowserWindowControllerTest, TestSaveWindowPosition) { ASSERT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) == NULL); // Ask the window to save its position, then check that a preference - // exists. + // exists. We're technically passing in a pointer to the user prefs + // and not the local state prefs, but a PrefService* is a + // PrefService*, and this is a unittest. [controller_ saveWindowPositionToPrefs:prefs]; EXPECT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) != NULL); } diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.h b/chrome/browser/ui/cocoa/dev_tools_controller.h index 4555b9a..c89a9f8 100644 --- a/chrome/browser/ui/cocoa/dev_tools_controller.h +++ b/chrome/browser/ui/cocoa/dev_tools_controller.h @@ -14,12 +14,11 @@ @class NSSplitView; @class NSView; -class Profile; class TabContents; // A class that handles updates of the devTools view within a browser window. // It swaps in the relevant devTools contents for a given TabContents or removes -// the view, if there's no devTools contents to show. +// the vew, if there's no devTools contents to show. @interface DevToolsController : NSObject { @private // A view hosting docked devTools contents. @@ -41,8 +40,7 @@ class TabContents; // Depending on |contents|'s state, decides whether the docked web inspector // should be shown or hidden and adjusts its height (|delegate_| handles // the actual resize). -- (void)updateDevToolsForTabContents:(TabContents*)contents - withProfile:(Profile*)profile; +- (void)updateDevToolsForTabContents:(TabContents*)contents; // Call when the devTools view is properly sized and the render widget host view // should be put into the view hierarchy. diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.mm b/chrome/browser/ui/cocoa/dev_tools_controller.mm index 617d773..4d29794 100644 --- a/chrome/browser/ui/cocoa/dev_tools_controller.mm +++ b/chrome/browser/ui/cocoa/dev_tools_controller.mm @@ -11,7 +11,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/debugger/devtools_window.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #import "chrome/browser/ui/cocoa/view_id_util.h" #include "chrome/common/pref_names.h" @@ -29,8 +28,7 @@ const int kMinWebHeight = 50; @interface DevToolsController (Private) -- (void)showDevToolsContents:(TabContents*)devToolsContents - withProfile:(Profile*)profile; +- (void)showDevToolsContents:(TabContents*)devToolsContents; - (void)resizeDevToolsToNewHeight:(CGFloat)height; @end @@ -65,21 +63,19 @@ const int kMinWebHeight = 50; return splitView_.get(); } -- (void)updateDevToolsForTabContents:(TabContents*)contents - withProfile:(Profile*)profile { +- (void)updateDevToolsForTabContents:(TabContents*)contents { // Get current devtools content. TabContents* devToolsContents = contents ? DevToolsWindow::GetDevToolsContents(contents) : NULL; - [self showDevToolsContents:devToolsContents withProfile:profile]; + [self showDevToolsContents:devToolsContents]; } - (void)ensureContentsVisible { [contentsController_ ensureContentsVisible]; } -- (void)showDevToolsContents:(TabContents*)devToolsContents - withProfile:(Profile*)profile { +- (void)showDevToolsContents:(TabContents*)devToolsContents { [contentsController_ ensureContentsSizeDoesNotChange]; NSArray* subviews = [splitView_ subviews]; @@ -95,8 +91,8 @@ const int kMinWebHeight = 50; CGFloat splitOffset = 0; if ([subviews count] == 1) { // Load the default split offset. - splitOffset = profile->GetPrefs()-> - GetInteger(prefs::kDevToolsSplitLocation); + splitOffset = g_browser_process->local_state()->GetInteger( + prefs::kDevToolsSplitLocation); if (splitOffset < 0) { // Initial load, set to default value. splitOffset = kDefaultContentsSplitOffset; @@ -121,8 +117,7 @@ const int kMinWebHeight = 50; NSView* oldDevToolsContentsView = [subviews objectAtIndex:1]; // Store split offset when hiding devtools window only. int splitOffset = NSHeight([oldDevToolsContentsView frame]); - - profile->GetPrefs()->SetInteger( + g_browser_process->local_state()->SetInteger( prefs::kDevToolsSplitLocation, splitOffset); [oldDevToolsContentsView removeFromSuperview]; [splitView_ adjustSubviews]; diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc index a4b5c0b..6b18b39 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.cc +++ b/chrome/browser/ui/gtk/browser_window_gtk.cc @@ -1273,8 +1273,8 @@ void BrowserWindowGtk::UpdateDevToolsForContents(TabContents* contents) { } else if (should_hide) { // Store split offset when hiding devtools window only. gint divider_offset = gtk_paned_get_position(GTK_PANED(contents_split_)); - browser_->profile()->GetPrefs()-> - SetInteger(prefs::kDevToolsSplitLocation, divider_offset); + g_browser_process->local_state()->SetInteger( + prefs::kDevToolsSplitLocation, divider_offset); gtk_widget_hide(devtools_container_->widget()); } } @@ -1597,8 +1597,8 @@ void BrowserWindowGtk::InitWidgets() { FALSE, TRUE); gtk_box_pack_end(GTK_BOX(render_area_vbox_), contents_split_, TRUE, TRUE, 0); // Restore split offset. - int split_offset = browser_->profile()->GetPrefs()-> - GetInteger(prefs::kDevToolsSplitLocation); + int split_offset = g_browser_process->local_state()->GetInteger( + prefs::kDevToolsSplitLocation); if (split_offset != -1) { if (split_offset < kMinDevToolsHeight) split_offset = kMinDevToolsHeight; @@ -1758,13 +1758,13 @@ void BrowserWindowGtk::SaveWindowPosition() { // We also need to save the placement for startup. // This is a web of calls between views and delegates on Windows, but the // crux of the logic follows. See also cocoa/browser_window_controller.mm. - if (!browser_->profile()->GetPrefs()) + if (!g_browser_process->local_state()) return; std::string window_name = browser_->GetWindowPlacementKey(); DictionaryValue* window_preferences = - browser_->profile()->GetPrefs()-> - GetMutableDictionary(window_name.c_str()); + g_browser_process->local_state()->GetMutableDictionary( + window_name.c_str()); // Note that we store left/top for consistency with Windows, but that we // *don't* obey them; we only use them for computing width/height. See // comments in SetGeometryHints(). diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc index 8f3cd43..86faf4c 100644 --- a/chrome/browser/ui/views/chrome_views_delegate.cc +++ b/chrome/browser/ui/views/chrome_views_delegate.cc @@ -8,7 +8,6 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/views/accessibility_event_router_views.h" #include "chrome/browser/ui/window_sizer.h" #include "gfx/rect.h" @@ -28,12 +27,12 @@ ui::Clipboard* ChromeViewsDelegate::GetClipboard() const { void ChromeViewsDelegate::SaveWindowPlacement(const std::wstring& window_name, const gfx::Rect& bounds, bool maximized) { - if (!g_browser_process->profile_manager()) + if (!g_browser_process->local_state()) return; DictionaryValue* window_preferences = - g_browser_process->profile_manager()->GetDefaultProfile()->GetPrefs()-> - GetMutableDictionary(WideToUTF8(window_name).c_str()); + g_browser_process->local_state()->GetMutableDictionary( + WideToUTF8(window_name).c_str()); window_preferences->SetInteger("left", bounds.x()); window_preferences->SetInteger("top", bounds.y()); window_preferences->SetInteger("right", bounds.right()); @@ -52,12 +51,12 @@ void ChromeViewsDelegate::SaveWindowPlacement(const std::wstring& window_name, bool ChromeViewsDelegate::GetSavedWindowBounds(const std::wstring& window_name, gfx::Rect* bounds) const { - if (!g_browser_process->profile_manager()) + if (!g_browser_process->local_state()) return false; const DictionaryValue* dictionary = - g_browser_process->profile_manager()->GetDefaultProfile()->GetPrefs()-> - GetDictionary(WideToUTF8(window_name).c_str()); + g_browser_process->local_state()->GetDictionary( + WideToUTF8(window_name).c_str()); int left, top, right, bottom; if (!dictionary || !dictionary->GetInteger("left", &left) || !dictionary->GetInteger("top", &top) || @@ -72,13 +71,12 @@ bool ChromeViewsDelegate::GetSavedWindowBounds(const std::wstring& window_name, bool ChromeViewsDelegate::GetSavedMaximizedState( const std::wstring& window_name, bool* maximized) const { - if (!g_browser_process->profile_manager()) + if (!g_browser_process->local_state()) return false; const DictionaryValue* dictionary = - g_browser_process->profile_manager()->GetDefaultProfile()->GetPrefs()-> - GetDictionary(WideToUTF8(window_name).c_str()); - + g_browser_process->local_state()->GetDictionary( + WideToUTF8(window_name).c_str()); return dictionary && dictionary->GetBoolean("maximized", maximized) && maximized; } diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index b09fccb2..1637c7a 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -2102,8 +2102,8 @@ void BrowserView::UpdateDevToolsForContents(TabContentsWrapper* wrapper) { } // Restore split offset. - int split_offset = browser_->profile()->GetPrefs()-> - GetInteger(prefs::kDevToolsSplitLocation); + int split_offset = g_browser_process->local_state()->GetInteger( + prefs::kDevToolsSplitLocation); if (split_offset == -1) { // Initial load, set to default value. split_offset = 2 * contents_split_->height() / 3; @@ -2119,8 +2119,8 @@ void BrowserView::UpdateDevToolsForContents(TabContentsWrapper* wrapper) { Layout(); } else if (should_hide) { // Store split offset when hiding devtools window only. - browser_->profile()->GetPrefs()->SetInteger(prefs::kDevToolsSplitLocation, - contents_split_->divider_offset()); + g_browser_process->local_state()->SetInteger( + prefs::kDevToolsSplitLocation, contents_split_->divider_offset()); // Restore focus to the last focused view when hiding devtools window. devtools_focus_tracker_->FocusLastFocusedExternalView(); diff --git a/chrome/browser/ui/window_sizer.cc b/chrome/browser/ui/window_sizer.cc index e1dd834..292f5fc 100644 --- a/chrome/browser/ui/window_sizer.cc +++ b/chrome/browser/ui/window_sizer.cc @@ -6,7 +6,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" @@ -17,9 +16,9 @@ // and persistent state from the browser window and the user's profile. class DefaultStateProvider : public WindowSizer::StateProvider { public: - explicit DefaultStateProvider(const std::string& app_name, - const Browser* browser) : app_name_(app_name), - browser_(browser) { + explicit DefaultStateProvider(const std::string& app_name, Browser* browser) + : app_name_(app_name), + browser_(browser) { } // Overridden from WindowSizer::StateProvider: @@ -34,11 +33,11 @@ class DefaultStateProvider : public WindowSizer::StateProvider { key.append(app_name_); } - if (!browser_->profile()->GetPrefs()) + if (!g_browser_process->local_state()) return false; const DictionaryValue* wp_pref = - browser_->profile()->GetPrefs()->GetDictionary(key.c_str()); + g_browser_process->local_state()->GetDictionary(key.c_str()); int top = 0, left = 0, bottom = 0, right = 0; bool has_prefs = wp_pref && @@ -75,9 +74,9 @@ class DefaultStateProvider : public WindowSizer::StateProvider { // If a reference browser is set, use its window. Otherwise find last // active. BrowserWindow* window = NULL; - // Window may be null if browser is just starting up. - if (browser_ && browser_->window()) { + if (browser_) { window = browser_->window(); + DCHECK(window); } else { BrowserList::const_reverse_iterator it = BrowserList::begin_last_active(); BrowserList::const_reverse_iterator end = BrowserList::end_last_active(); @@ -103,7 +102,7 @@ class DefaultStateProvider : public WindowSizer::StateProvider { std::string app_name_; // If set, is used as the reference browser for GetLastActiveWindowState. - const Browser* browser_; + Browser* browser_; DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider); }; @@ -133,7 +132,7 @@ WindowSizer::~WindowSizer() { // static void WindowSizer::GetBrowserWindowBounds(const std::string& app_name, const gfx::Rect& specified_bounds, - const Browser* browser, + Browser* browser, gfx::Rect* window_bounds, bool* maximized) { const WindowSizer sizer(new DefaultStateProvider(app_name, browser), diff --git a/chrome/browser/ui/window_sizer.h b/chrome/browser/ui/window_sizer.h index a943f43..7d34399 100644 --- a/chrome/browser/ui/window_sizer.h +++ b/chrome/browser/ui/window_sizer.h @@ -121,7 +121,7 @@ class WindowSizer { // non-NULL value for |browser|. static void GetBrowserWindowBounds(const std::string& app_name, const gfx::Rect& specified_bounds, - const Browser* browser, + Browser* browser, gfx::Rect* window_bounds, bool* maximized); @@ -181,5 +181,4 @@ class WindowSizer { DISALLOW_COPY_AND_ASSIGN(WindowSizer); }; -#endif // CHROME_BROWSER_UI_WINDOW_SIZER_H_ - +#endif // CHROME_BROWSER_WINDOW_SIZER_H_ |