15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/task_manager/task_manager_browsertest_util.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 79ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/run_loop.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string16.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/test/test_timeouts.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/timer/timer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/task_manager/resource_provider.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/task_manager/task_manager.h" 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/strings/grit/extensions_strings.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace task_manager { 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace browsertest_util { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ResourceChangeObserver : public TaskManagerModelObserver { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceChangeObserver(const TaskManagerModel* model, 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int required_count, 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& title_pattern) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : model_(model), 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) required_count_(required_count), 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) title_pattern_(title_pattern) {} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnModelChanged() OVERRIDE { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnResourceChange(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnItemsChanged(int start, int length) OVERRIDE { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnResourceChange(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnItemsAdded(int start, int length) OVERRIDE { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnResourceChange(); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnItemsRemoved(int start, int length) OVERRIDE { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnResourceChange(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void RunUntilSatisfied() { 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // See if the condition is satisfied without having to run the loop. This 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // check has to be placed after the installation of the 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TaskManagerModelObserver, because resources may change before that. 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsSatisfied()) 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timer_.Start(FROM_HERE, 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TestTimeouts::action_timeout(), 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &ResourceChangeObserver::OnTimeout); 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) run_loop_.Run(); 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If we succeeded normally (no timeout), check our post condition again 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // before returning control to the test. If it is no longer satisfied, the 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // test is likely flaky: we were waiting for a state that was only achieved 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // emphemerally), so treat this as a failure. 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsSatisfied() && timer_.IsRunning()) { 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FAIL() << "Wait condition satisfied only emphemerally. Likely test " 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "problem. Maybe wait instead for the state below?\n" 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << DumpTaskManagerModel(); 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timer_.Stop(); 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnResourceChange() { 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsSatisfied()) 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure()); 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool IsSatisfied() { return CountMatches() == required_count_; } 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int CountMatches() { 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int match_count = 0; 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i < model_->ResourceCount(); i++) { 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) task_manager::Resource::Type type = model_->GetResourceType(i); 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Skip system infrastructure resources. 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (type == task_manager::Resource::BROWSER || 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type == task_manager::Resource::NACL || 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type == task_manager::Resource::GPU || 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type == task_manager::Resource::UTILITY || 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type == task_manager::Resource::ZYGOTE || 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type == task_manager::Resource::SANDBOX_HELPER) { 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (MatchPattern(model_->GetResourceTitle(i), title_pattern_)) { 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) match_count++; 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return match_count; 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OnTimeout() { 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure()); 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FAIL() << "Timed out.\n" << DumpTaskManagerModel(); 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) testing::Message DumpTaskManagerModel() { 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) testing::Message task_manager_state_dump; 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) task_manager_state_dump << "Waiting for exactly " << required_count_ 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " matches of wildcard pattern \"" 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << base::UTF16ToASCII(title_pattern_) << "\"\n"; 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) task_manager_state_dump << "Currently there are " << CountMatches() 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " matches.\n"; 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) task_manager_state_dump << "Current Task Manager Model is:\n"; 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i < model_->ResourceCount(); i++) { 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) task_manager_state_dump 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " > " << base::UTF16ToASCII(model_->GetResourceTitle(i)) << "\n"; 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return task_manager_state_dump; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TaskManagerModel* model_; 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int required_count_; 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16 title_pattern_; 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::RunLoop run_loop_; 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::OneShotTimer<ResourceChangeObserver> timer_; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WaitForTaskManagerRows(int required_count, 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& title_pattern) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TaskManagerModel* model = TaskManager::GetInstance()->model(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ResourceChangeObserver observer(model, required_count, title_pattern); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->AddObserver(&observer); 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) observer.RunUntilSatisfied(); 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) model->RemoveObserver(&observer); 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchTab(const char* title) { 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX, 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ASCIIToUTF16(title)); 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchAnyTab() { return MatchTab("*"); } 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchAboutBlankTab() { return MatchTab("about:blank"); } 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchExtension(const char* title) { 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX, 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ASCIIToUTF16(title)); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchAnyExtension() { return MatchExtension("*"); } 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchApp(const char* title) { 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX, 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ASCIIToUTF16(title)); 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchAnyApp() { return MatchApp("*"); } 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchWebView(const char* title) { 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return l10n_util::GetStringFUTF16( 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX, 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ASCIIToUTF16(title)); 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchAnyWebView() { return MatchWebView("*"); } 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchBackground(const char* title) { 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX, 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::ASCIIToUTF16(title)); 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::string16 MatchAnyBackground() { return MatchBackground("*"); } 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbase::string16 MatchPrint(const char* title) { 189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX, 190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::ASCIIToUTF16(title)); 191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbase::string16 MatchAnyPrint() { return MatchPrint("*"); } 194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace browsertest_util 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace task_manager 197