1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/devtools/embedded_worker_devtools_manager.h" 6 7#include "base/memory/scoped_ptr.h" 8#include "base/message_loop/message_loop.h" 9#include "base/run_loop.h" 10#include "content/browser/browser_thread_impl.h" 11#include "content/browser/devtools/devtools_agent_host_impl.h" 12#include "content/browser/devtools/embedded_worker_devtools_agent_host.h" 13#include "content/browser/shared_worker/shared_worker_instance.h" 14#include "content/browser/shared_worker/worker_storage_partition.h" 15#include "content/public/test/test_browser_context.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18namespace content { 19namespace { 20 21class TestDevToolsClientHost : public DevToolsAgentHostClient { 22 public: 23 TestDevToolsClientHost() {} 24 virtual ~TestDevToolsClientHost() {} 25 virtual void DispatchProtocolMessage( 26 DevToolsAgentHost* agent_host, const std::string& message) OVERRIDE {} 27 virtual void AgentHostClosed( 28 DevToolsAgentHost* agent_host, bool replaced) OVERRIDE {} 29 30 void InspectAgentHost(DevToolsAgentHost* agent_host) { 31 if (agent_host_.get()) 32 agent_host_->DetachClient(); 33 agent_host_ = agent_host; 34 if (agent_host_.get()) 35 agent_host_->AttachClient(this); 36 } 37 private: 38 scoped_refptr<DevToolsAgentHost> agent_host_; 39 DISALLOW_COPY_AND_ASSIGN(TestDevToolsClientHost); 40}; 41} 42 43class EmbeddedWorkerDevToolsManagerTest : public testing::Test { 44 public: 45 typedef EmbeddedWorkerDevToolsAgentHost::WorkerState WorkerState; 46 47 EmbeddedWorkerDevToolsManagerTest() 48 : ui_thread_(BrowserThread::UI, &message_loop_), 49 browser_context_(new TestBrowserContext()), 50 partition_( 51 new WorkerStoragePartition(browser_context_->GetRequestContext(), 52 NULL, 53 NULL, 54 NULL, 55 NULL, 56 NULL, 57 NULL, 58 NULL)), 59 partition_id_(*partition_.get()) {} 60 61 protected: 62 virtual void SetUp() OVERRIDE { 63 manager_ = EmbeddedWorkerDevToolsManager::GetInstance(); 64 } 65 virtual void TearDown() OVERRIDE { 66 EmbeddedWorkerDevToolsManager::GetInstance()->ResetForTesting(); 67 } 68 69 void CheckWorkerState(int worker_process_id, 70 int worker_route_id, 71 WorkerState state) { 72 const EmbeddedWorkerDevToolsManager::WorkerId id(worker_process_id, 73 worker_route_id); 74 EmbeddedWorkerDevToolsManager::AgentHostMap::iterator it = 75 manager_->workers_.find(id); 76 EXPECT_TRUE(manager_->workers_.end() != it); 77 EXPECT_EQ(state, it->second->state_); 78 } 79 80 void CheckWorkerNotExist(int worker_process_id, int worker_route_id) { 81 const EmbeddedWorkerDevToolsManager::WorkerId id(worker_process_id, 82 worker_route_id); 83 EXPECT_TRUE(manager_->workers_.end() == manager_->workers_.find(id)); 84 } 85 86 void CheckWorkerCount(size_t size) { 87 EXPECT_EQ(size, manager_->workers_.size()); 88 } 89 90 base::MessageLoopForIO message_loop_; 91 BrowserThreadImpl ui_thread_; 92 scoped_ptr<TestBrowserContext> browser_context_; 93 scoped_ptr<WorkerStoragePartition> partition_; 94 const WorkerStoragePartitionId partition_id_; 95 EmbeddedWorkerDevToolsManager* manager_; 96}; 97 98TEST_F(EmbeddedWorkerDevToolsManagerTest, BasicTest) { 99 scoped_refptr<DevToolsAgentHostImpl> agent_host; 100 101 SharedWorkerInstance instance1(GURL("http://example.com/w.js"), 102 base::string16(), 103 base::string16(), 104 blink::WebContentSecurityPolicyTypeReport, 105 browser_context_->GetResourceContext(), 106 partition_id_); 107 108 agent_host = manager_->GetDevToolsAgentHostForWorker(1, 1); 109 EXPECT_FALSE(agent_host.get()); 110 111 // Created -> Started -> Destroyed 112 CheckWorkerNotExist(1, 1); 113 manager_->SharedWorkerCreated(1, 1, instance1); 114 CheckWorkerState(1, 1, WorkerState::WORKER_UNINSPECTED); 115 manager_->WorkerReadyForInspection(1, 1); 116 CheckWorkerState(1, 1, WorkerState::WORKER_UNINSPECTED); 117 manager_->WorkerContextStarted(1, 1); 118 CheckWorkerState(1, 1, WorkerState::WORKER_UNINSPECTED); 119 manager_->WorkerDestroyed(1, 1); 120 CheckWorkerNotExist(1, 1); 121 122 // Created -> GetDevToolsAgentHost -> Started -> Destroyed 123 CheckWorkerNotExist(1, 2); 124 manager_->SharedWorkerCreated(1, 2, instance1); 125 CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); 126 agent_host = manager_->GetDevToolsAgentHostForWorker(1, 2); 127 EXPECT_TRUE(agent_host.get()); 128 CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); 129 EXPECT_EQ(agent_host.get(), manager_->GetDevToolsAgentHostForWorker(1, 2)); 130 manager_->WorkerReadyForInspection(1, 2); 131 CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); 132 manager_->WorkerContextStarted(1, 2); 133 CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED); 134 manager_->WorkerDestroyed(1, 2); 135 CheckWorkerState(1, 2, WorkerState::WORKER_TERMINATED); 136 agent_host = NULL; 137 CheckWorkerNotExist(1, 2); 138 139 // Created -> Started -> GetDevToolsAgentHost -> Destroyed 140 CheckWorkerNotExist(1, 3); 141 manager_->SharedWorkerCreated(1, 3, instance1); 142 CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); 143 manager_->WorkerReadyForInspection(1, 3); 144 CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); 145 manager_->WorkerContextStarted(1, 3); 146 CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); 147 agent_host = manager_->GetDevToolsAgentHostForWorker(1, 3); 148 EXPECT_TRUE(agent_host.get()); 149 CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED); 150 manager_->WorkerDestroyed(1, 3); 151 CheckWorkerState(1, 3, WorkerState::WORKER_TERMINATED); 152 agent_host = NULL; 153 CheckWorkerNotExist(1, 3); 154 155 // Created -> Destroyed 156 CheckWorkerNotExist(1, 4); 157 manager_->SharedWorkerCreated(1, 4, instance1); 158 CheckWorkerState(1, 4, WorkerState::WORKER_UNINSPECTED); 159 manager_->WorkerDestroyed(1, 4); 160 CheckWorkerNotExist(1, 4); 161 162 // Created -> GetDevToolsAgentHost -> Destroyed 163 CheckWorkerNotExist(1, 5); 164 manager_->SharedWorkerCreated(1, 5, instance1); 165 CheckWorkerState(1, 5, WorkerState::WORKER_UNINSPECTED); 166 agent_host = manager_->GetDevToolsAgentHostForWorker(1, 5); 167 EXPECT_TRUE(agent_host.get()); 168 CheckWorkerState(1, 5, WorkerState::WORKER_UNINSPECTED); 169 manager_->WorkerDestroyed(1, 5); 170 CheckWorkerState(1, 5, WorkerState::WORKER_TERMINATED); 171 agent_host = NULL; 172 CheckWorkerNotExist(1, 5); 173 174 // Created -> GetDevToolsAgentHost -> Free agent_host -> Destroyed 175 CheckWorkerNotExist(1, 6); 176 manager_->SharedWorkerCreated(1, 6, instance1); 177 CheckWorkerState(1, 6, WorkerState::WORKER_UNINSPECTED); 178 agent_host = manager_->GetDevToolsAgentHostForWorker(1, 6); 179 EXPECT_TRUE(agent_host.get()); 180 CheckWorkerState(1, 6, WorkerState::WORKER_UNINSPECTED); 181 agent_host = NULL; 182 manager_->WorkerDestroyed(1, 6); 183 CheckWorkerNotExist(1, 6); 184} 185 186TEST_F(EmbeddedWorkerDevToolsManagerTest, AttachTest) { 187 scoped_refptr<DevToolsAgentHostImpl> agent_host1; 188 scoped_refptr<DevToolsAgentHostImpl> agent_host2; 189 190 SharedWorkerInstance instance1(GURL("http://example.com/w1.js"), 191 base::string16(), 192 base::string16(), 193 blink::WebContentSecurityPolicyTypeReport, 194 browser_context_->GetResourceContext(), 195 partition_id_); 196 SharedWorkerInstance instance2(GURL("http://example.com/w2.js"), 197 base::string16(), 198 base::string16(), 199 blink::WebContentSecurityPolicyTypeReport, 200 browser_context_->GetResourceContext(), 201 partition_id_); 202 203 // Created -> GetDevToolsAgentHost -> Register -> Started -> Destroyed 204 scoped_ptr<TestDevToolsClientHost> client_host1(new TestDevToolsClientHost()); 205 CheckWorkerNotExist(2, 1); 206 manager_->SharedWorkerCreated(2, 1, instance1); 207 CheckWorkerState(2, 1, WorkerState::WORKER_UNINSPECTED); 208 agent_host1 = manager_->GetDevToolsAgentHostForWorker(2, 1); 209 EXPECT_TRUE(agent_host1.get()); 210 CheckWorkerState(2, 1, WorkerState::WORKER_UNINSPECTED); 211 EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 1)); 212 client_host1->InspectAgentHost(agent_host1.get()); 213 CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED); 214 manager_->WorkerReadyForInspection(2, 1); 215 CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED); 216 manager_->WorkerContextStarted(2, 1); 217 CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED); 218 manager_->WorkerDestroyed(2, 1); 219 CheckWorkerState(2, 1, WorkerState::WORKER_TERMINATED); 220 EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 1)); 221 222 // Created -> Started -> GetDevToolsAgentHost -> Register -> Destroyed 223 scoped_ptr<TestDevToolsClientHost> client_host2(new TestDevToolsClientHost()); 224 manager_->SharedWorkerCreated(2, 2, instance2); 225 CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); 226 manager_->WorkerReadyForInspection(2, 2); 227 CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); 228 manager_->WorkerContextStarted(2, 2); 229 CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); 230 agent_host2 = manager_->GetDevToolsAgentHostForWorker(2, 2); 231 EXPECT_TRUE(agent_host2.get()); 232 EXPECT_NE(agent_host1.get(), agent_host2.get()); 233 EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 2)); 234 CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED); 235 client_host2->InspectAgentHost(agent_host2.get()); 236 CheckWorkerState(2, 2, WorkerState::WORKER_INSPECTED); 237 manager_->WorkerDestroyed(2, 2); 238 CheckWorkerState(2, 2, WorkerState::WORKER_TERMINATED); 239 EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 2)); 240 241 // Re-created -> Started -> ClientHostClosing -> Destroyed 242 CheckWorkerState(2, 1, WorkerState::WORKER_TERMINATED); 243 manager_->SharedWorkerCreated(2, 3, instance1); 244 CheckWorkerNotExist(2, 1); 245 CheckWorkerState(2, 3, WorkerState::WORKER_PAUSED_FOR_REATTACH); 246 EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 3)); 247 manager_->WorkerReadyForInspection(2, 3); 248 CheckWorkerState(2, 3, WorkerState::WORKER_INSPECTED); 249 manager_->WorkerContextStarted(2, 3); 250 CheckWorkerState(2, 3, WorkerState::WORKER_INSPECTED); 251 client_host1->InspectAgentHost(NULL); 252 manager_->WorkerDestroyed(2, 3); 253 CheckWorkerState(2, 3, WorkerState::WORKER_TERMINATED); 254 agent_host1 = NULL; 255 CheckWorkerNotExist(2, 3); 256 257 // Re-created -> Destroyed 258 CheckWorkerState(2, 2, WorkerState::WORKER_TERMINATED); 259 manager_->SharedWorkerCreated(2, 4, instance2); 260 CheckWorkerNotExist(2, 2); 261 CheckWorkerState(2, 4, WorkerState::WORKER_PAUSED_FOR_REATTACH); 262 EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 4)); 263 manager_->WorkerDestroyed(2, 4); 264 CheckWorkerNotExist(2, 2); 265 CheckWorkerState(2, 4, WorkerState::WORKER_TERMINATED); 266 267 // Re-created -> ClientHostClosing -> Destroyed 268 manager_->SharedWorkerCreated(2, 5, instance2); 269 CheckWorkerNotExist(2, 2); 270 CheckWorkerState(2, 5, WorkerState::WORKER_PAUSED_FOR_REATTACH); 271 EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 5)); 272 client_host2->InspectAgentHost(NULL); 273 CheckWorkerCount(1); 274 agent_host2 = NULL; 275 CheckWorkerCount(1); 276 manager_->WorkerDestroyed(2, 5); 277 CheckWorkerCount(0); 278} 279 280TEST_F(EmbeddedWorkerDevToolsManagerTest, ReattachTest) { 281 SharedWorkerInstance instance(GURL("http://example.com/w3.js"), 282 base::string16(), 283 base::string16(), 284 blink::WebContentSecurityPolicyTypeReport, 285 browser_context_->GetResourceContext(), 286 partition_id_); 287 scoped_ptr<TestDevToolsClientHost> client_host(new TestDevToolsClientHost()); 288 // Created -> GetDevToolsAgentHost -> Register -> Destroyed 289 manager_->SharedWorkerCreated(3, 1, instance); 290 CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED); 291 scoped_refptr<DevToolsAgentHost> agent_host( 292 manager_->GetDevToolsAgentHostForWorker(3, 1)); 293 EXPECT_TRUE(agent_host.get()); 294 CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED); 295 client_host->InspectAgentHost(agent_host.get()); 296 CheckWorkerState(3, 1, WorkerState::WORKER_INSPECTED); 297 manager_->WorkerDestroyed(3, 1); 298 CheckWorkerState(3, 1, WorkerState::WORKER_TERMINATED); 299 // ClientHostClosing -> Re-created -> release agent_host -> Destroyed 300 client_host->InspectAgentHost(NULL); 301 CheckWorkerState(3, 1, WorkerState::WORKER_TERMINATED); 302 manager_->SharedWorkerCreated(3, 2, instance); 303 CheckWorkerState(3, 2, WorkerState::WORKER_UNINSPECTED); 304 agent_host = NULL; 305 CheckWorkerState(3, 2, WorkerState::WORKER_UNINSPECTED); 306 manager_->WorkerDestroyed(3, 2); 307 CheckWorkerNotExist(3, 2); 308 CheckWorkerCount(0); 309} 310 311} // namespace content 312