1bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/metrics/nacl_histogram.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/tabs/default_tab_handler.h" 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/tabs/tab_strip_model.h" 84a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//////////////////////////////////////////////////////////////////////////////// 11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// DefaultTabHandler, public: 12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenDefaultTabHandler::DefaultTabHandler(TabHandlerDelegate* delegate) 14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen : delegate_(delegate), 15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST( 16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch model_(new TabStripModel(this, delegate->GetProfile()))) { 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UmaNaclHistogramEnumeration(FIRST_TAB_NACL_BASELINE); 18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen model_->AddObserver(this); 19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenDefaultTabHandler::~DefaultTabHandler() { 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The tab strip should not have any tabs at this point. 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(model_->empty()); 24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen model_->RemoveObserver(this); 25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//////////////////////////////////////////////////////////////////////////////// 28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// DefaultTabHandler, TabHandler implementation: 29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenTabStripModel* DefaultTabHandler::GetTabStripModel() const { 31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return model_.get(); 32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//////////////////////////////////////////////////////////////////////////////// 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// DefaultTabHandler, TabStripModelDelegate implementation: 36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 37201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContentsWrapper* DefaultTabHandler::AddBlankTab(bool foreground) { 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UmaNaclHistogramEnumeration(NEW_TAB_NACL_BASELINE); 39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->AddBlankTab(foreground); 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContentsWrapper* DefaultTabHandler::AddBlankTabAt(int index, 43201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool foreground) { 44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->AddBlankTabAt(index, foreground); 45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBrowser* DefaultTabHandler::CreateNewStripWithContents( 48201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* detached_contents, 49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const gfx::Rect& window_bounds, 50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const DockInfo& dock_info, 51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool maximize) { 52bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CreateNewStripWithContents(detached_contents, 53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen window_bounds, 54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen dock_info, 55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen maximize); 56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenint DefaultTabHandler::GetDragActions() const { 59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->GetDragActions(); 60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 62201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTabContentsWrapper* DefaultTabHandler::CreateTabContentsForURL( 63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const GURL& url, 64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const GURL& referrer, 65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Profile* profile, 66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen PageTransition::Type transition, 67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool defer_load, 68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen SiteInstance* instance) const { 69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CreateTabContentsForURL(url, 70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen referrer, 71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile, 72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen transition, 73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen defer_load, 74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen instance); 75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::CanDuplicateContentsAt(int index) { 78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CanDuplicateContentsAt(index); 79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid DefaultTabHandler::DuplicateContentsAt(int index) { 82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->DuplicateContentsAt(index); 83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 84bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 85bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid DefaultTabHandler::CloseFrameAfterDragSession() { 86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->CloseFrameAfterDragSession(); 87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 89201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DefaultTabHandler::CreateHistoricalTab(TabContentsWrapper* contents) { 90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->CreateHistoricalTab(contents); 91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 93201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool DefaultTabHandler::RunUnloadListenerBeforeClosing( 94201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents) { 95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->RunUnloadListenerBeforeClosing(contents); 96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::CanCloseContentsAt(int index) { 99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CanCloseContentsAt(index); 100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::CanBookmarkAllTabs() const { 103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CanBookmarkAllTabs(); 104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid DefaultTabHandler::BookmarkAllTabs() { 107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->BookmarkAllTabs(); 108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::CanCloseTab() const { 111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CanCloseTab(); 112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid DefaultTabHandler::ToggleUseVerticalTabs() { 115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->ToggleUseVerticalTabs(); 116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::CanRestoreTab() { 119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->CanRestoreTab(); 120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid DefaultTabHandler::RestoreTab() { 123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->RestoreTab(); 124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::LargeIconsPermitted() const { 127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->LargeIconsPermitted(); 128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool DefaultTabHandler::UseVerticalTabs() const { 131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return delegate_->AsBrowser()->UseVerticalTabs(); 132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//////////////////////////////////////////////////////////////////////////////// 135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// DefaultTabHandler, TabStripModelObserver implementation: 136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DefaultTabHandler::TabInsertedAt(TabContentsWrapper* contents, 138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int index, 139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool foreground) { 140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->TabInsertedAt(contents, index, foreground); 141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid DefaultTabHandler::TabClosingAt(TabStripModel* tab_strip_model, 144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents, 145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int index) { 146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick delegate_->AsBrowser()->TabClosingAt(tab_strip_model, contents, index); 147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DefaultTabHandler::TabDetachedAt(TabContentsWrapper* contents, int index) { 150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->TabDetachedAt(contents, index); 151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid DefaultTabHandler::TabDeselected(TabContentsWrapper* contents) { 154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delegate_->AsBrowser()->TabDeselected(contents); 155bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DefaultTabHandler::TabSelectedAt(TabContentsWrapper* old_contents, 158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* new_contents, 159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int index, 160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool user_gesture) { 161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->TabSelectedAt(old_contents, 162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen new_contents, 163bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen index, 164bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen user_gesture); 165bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DefaultTabHandler::TabMoved(TabContentsWrapper* contents, 168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int from_index, 169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int to_index) { 170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->TabMoved(contents, from_index, to_index); 171bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 172bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DefaultTabHandler::TabReplacedAt(TabStripModel* tab_strip_model, 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen TabContentsWrapper* old_contents, 175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* new_contents, 176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int index) { 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delegate_->AsBrowser()->TabReplacedAt(tab_strip_model, old_contents, 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen new_contents, index); 179bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid DefaultTabHandler::TabPinnedStateChanged(TabContentsWrapper* contents, 182bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int index) { 183bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->TabPinnedStateChanged(contents, index); 184bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 185bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 186bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid DefaultTabHandler::TabStripEmpty() { 187bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delegate_->AsBrowser()->TabStripEmpty(); 188bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 189bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 190bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//////////////////////////////////////////////////////////////////////////////// 191bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// TabHandler, public: 192bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 193bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 194bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenTabHandler* TabHandler::CreateTabHandler(TabHandlerDelegate* delegate) { 195bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return new DefaultTabHandler(delegate); 196bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 197bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 198