Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: content/browser/renderer_host/media/audio_renderer_host_unittest.cc

Issue 2424163004: Factor out authorization from AudioRendererHost. (Closed)
Patch Set: Dale's comments. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/media/audio_renderer_host.h" 5 #include "content/browser/renderer_host/media/audio_renderer_host.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/run_loop.h" 14 #include "base/run_loop.h"
15 #include "base/sync_socket.h" 15 #include "base/sync_socket.h"
16 #include "content/browser/media/capture/audio_mirroring_manager.h" 16 #include "content/browser/media/capture/audio_mirroring_manager.h"
17 #include "content/browser/media/media_internals.h" 17 #include "content/browser/media/media_internals.h"
18 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 18 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
19 #include "content/browser/renderer_host/media/media_stream_manager.h" 19 #include "content/browser/renderer_host/media/media_stream_manager.h"
20 #include "content/common/media/audio_messages.h" 20 #include "content/common/media/audio_messages.h"
21 #include "content/public/common/content_switches.h" 21 #include "content/public/common/content_switches.h"
22 #include "content/public/test/mock_render_process_host.h"
23 #include "content/public/test/test_browser_context.h"
22 #include "content/public/test/test_browser_thread_bundle.h" 24 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "ipc/ipc_message_utils.h" 25 #include "ipc/ipc_message_utils.h"
24 #include "media/audio/audio_manager.h" 26 #include "media/audio/audio_manager.h"
25 #include "media/base/bind_to_current_loop.h" 27 #include "media/base/bind_to_current_loop.h"
26 #include "media/base/media_switches.h" 28 #include "media/base/media_switches.h"
27 #include "testing/gmock/include/gmock/gmock.h" 29 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/gtest/include/gtest/gtest.h"
29 31
30 using ::testing::_; 32 using ::testing::_;
31 using ::testing::Assign; 33 using ::testing::Assign;
32 using ::testing::AtLeast; 34 using ::testing::AtLeast;
33 using ::testing::DoAll; 35 using ::testing::DoAll;
34 using ::testing::NotNull; 36 using ::testing::NotNull;
35 37
36 namespace content { 38 namespace content {
37 39
38 namespace { 40 namespace {
39 const int kRenderProcessId = 1;
40 const int kRenderFrameId = 5; 41 const int kRenderFrameId = 5;
41 const int kStreamId = 50; 42 const int kStreamId = 50;
42 const char kSecurityOrigin[] = "http://localhost"; 43 const char kSecurityOrigin[] = "http://localhost";
43 const char kBadSecurityOrigin[] = "about:about"; 44 const char kBadSecurityOrigin[] = "about:about";
44 const char kDefaultDeviceId[] = ""; 45 const char kDefaultDeviceId[] = "";
45 const char kNondefaultDeviceId[] = 46 const char kNondefaultDeviceId[] =
46 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; 47 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
47 const char kBadDeviceId[] = 48 const char kBadDeviceId[] =
48 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1"; 49 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1";
49 const char kInvalidDeviceId[] = "invalid-device-id"; 50 const char kInvalidDeviceId[] = "invalid-device-id";
50 51
51 void ValidateRenderFrameId(int render_process_id, 52 void ValidateRenderFrameId(int render_process_id,
52 int render_frame_id, 53 int render_frame_id,
53 const base::Callback<void(bool)>& callback) { 54 const base::Callback<void(bool)>& callback) {
54 DCHECK_CURRENTLY_ON(BrowserThread::UI); 55 DCHECK_CURRENTLY_ON(BrowserThread::UI);
55 const bool frame_exists = (render_process_id == kRenderProcessId && 56 const bool frame_exists = (render_frame_id == kRenderFrameId);
56 render_frame_id == kRenderFrameId);
57 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 57 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
58 base::Bind(callback, frame_exists)); 58 base::Bind(callback, frame_exists));
59 } 59 }
60 60
61 } // namespace 61 } // namespace
62 62
63 class MockAudioMirroringManager : public AudioMirroringManager { 63 class MockAudioMirroringManager : public AudioMirroringManager {
64 public: 64 public:
65 MockAudioMirroringManager() {} 65 MockAudioMirroringManager() {}
66 virtual ~MockAudioMirroringManager() {} 66 virtual ~MockAudioMirroringManager() {}
67 67
68 MOCK_METHOD3(AddDiverter, 68 MOCK_METHOD3(AddDiverter,
69 void(int render_process_id, 69 void(int render_process_id,
70 int render_frame_id, 70 int render_frame_id,
71 Diverter* diverter)); 71 Diverter* diverter));
72 MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter)); 72 MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter));
73 73
74 private: 74 private:
75 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager); 75 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
76 }; 76 };
77 77
78 class MockAudioRendererHost : public AudioRendererHost { 78 class MockAudioRendererHost : public AudioRendererHost {
79 public: 79 public:
80 MockAudioRendererHost(base::RunLoop* auth_run_loop, 80 MockAudioRendererHost(base::RunLoop* auth_run_loop,
81 int render_process_id,
81 media::AudioManager* audio_manager, 82 media::AudioManager* audio_manager,
82 AudioMirroringManager* mirroring_manager, 83 AudioMirroringManager* mirroring_manager,
83 MediaInternals* media_internals, 84 MediaInternals* media_internals,
84 MediaStreamManager* media_stream_manager, 85 MediaStreamManager* media_stream_manager,
85 const std::string& salt) 86 const std::string& salt)
86 : AudioRendererHost(kRenderProcessId, 87 : AudioRendererHost(render_process_id,
87 audio_manager, 88 audio_manager,
88 mirroring_manager, 89 mirroring_manager,
89 media_internals, 90 media_internals,
90 media_stream_manager, 91 media_stream_manager,
91 salt), 92 salt),
92 shared_memory_length_(0), 93 shared_memory_length_(0),
93 auth_run_loop_(auth_run_loop) { 94 auth_run_loop_(auth_run_loop) {
94 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId); 95 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId);
95 } 96 }
96 97
97 // A list of mock methods. 98 // A list of mock methods.
98 MOCK_METHOD0(ShutdownForBadMessage, void());
99 MOCK_METHOD4(OnDeviceAuthorized, 99 MOCK_METHOD4(OnDeviceAuthorized,
100 void(int stream_id, 100 void(int stream_id,
101 media::OutputDeviceStatus device_status, 101 media::OutputDeviceStatus device_status,
102 const media::AudioParameters& output_params, 102 const media::AudioParameters& output_params,
103 const std::string& matched_device_id)); 103 const std::string& matched_device_id));
104 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); 104 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
105 MOCK_METHOD1(OnStreamError, void(int stream_id)); 105 MOCK_METHOD1(OnStreamError, void(int stream_id));
106 106
107 void ShutdownForBadMessage() override { bad_msg_count++; }
108
109 int bad_msg_count = 0;
110
107 private: 111 private:
108 virtual ~MockAudioRendererHost() { 112 virtual ~MockAudioRendererHost() {
109 // Make sure all audio streams have been deleted. 113 // Make sure all audio streams have been deleted.
110 EXPECT_TRUE(audio_entries_.empty()); 114 EXPECT_TRUE(audio_entries_.empty());
111 } 115 }
112 116
113 // This method is used to dispatch IPC messages to the renderer. We intercept 117 // This method is used to dispatch IPC messages to the renderer. We intercept
114 // these messages here and dispatch to our mock methods to verify the 118 // these messages here and dispatch to our mock methods to verify the
115 // conversation between this object and the renderer. 119 // conversation between this object and the renderer.
116 // Note: this means that file descriptors won't be duplicated, 120 // Note: this means that file descriptors won't be duplicated,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 void OnNotifyStreamError(int stream_id) { OnStreamError(stream_id); } 172 void OnNotifyStreamError(int stream_id) { OnStreamError(stream_id); }
169 173
170 std::unique_ptr<base::SharedMemory> shared_memory_; 174 std::unique_ptr<base::SharedMemory> shared_memory_;
171 std::unique_ptr<base::SyncSocket> sync_socket_; 175 std::unique_ptr<base::SyncSocket> sync_socket_;
172 uint32_t shared_memory_length_; 176 uint32_t shared_memory_length_;
173 base::RunLoop* auth_run_loop_; // Used to wait for authorization. 177 base::RunLoop* auth_run_loop_; // Used to wait for authorization.
174 178
175 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); 179 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
176 }; 180 };
177 181
182 class MockRenderProcessHostWithSignaling : public MockRenderProcessHost {
183 public:
184 MockRenderProcessHostWithSignaling(BrowserContext* context,
185 base::RunLoop* auth_run_loop)
186 : MockRenderProcessHost(context), auth_run_loop_(auth_run_loop) {}
187
188 void ShutdownForBadMessage(CrashReportMode crash_report_mode) override {
189 MockRenderProcessHost::ShutdownForBadMessage(crash_report_mode);
190 auth_run_loop_->Quit();
191 }
192
193 private:
194 base::RunLoop* auth_run_loop_; // Used to wait for authorization.
195 };
196
178 class AudioRendererHostTest : public testing::Test { 197 class AudioRendererHostTest : public testing::Test {
179 public: 198 public:
180 AudioRendererHostTest() { 199 AudioRendererHostTest()
200 : render_process_host_(&browser_context_, &auth_run_loop_) {
181 audio_manager_ = media::AudioManager::CreateForTesting( 201 audio_manager_ = media::AudioManager::CreateForTesting(
182 base::ThreadTaskRunnerHandle::Get()); 202 base::ThreadTaskRunnerHandle::Get());
183 base::CommandLine::ForCurrentProcess()->AppendSwitch( 203 base::CommandLine::ForCurrentProcess()->AppendSwitch(
184 switches::kUseFakeDeviceForMediaStream); 204 switches::kUseFakeDeviceForMediaStream);
185 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 205 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
186 host_ = new MockAudioRendererHost( 206 host_ = new MockAudioRendererHost(
187 &auth_run_loop_, audio_manager_.get(), &mirroring_manager_, 207 &auth_run_loop_, render_process_host_.GetID(), audio_manager_.get(),
188 MediaInternals::GetInstance(), media_stream_manager_.get(), 208 &mirroring_manager_, MediaInternals::GetInstance(),
189 std::string()); 209 media_stream_manager_.get(), std::string());
190
191 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(0);
192 210
193 // Simulate IPC channel connected. 211 // Simulate IPC channel connected.
194 host_->set_peer_process_for_testing(base::Process::Current()); 212 host_->set_peer_process_for_testing(base::Process::Current());
195 } 213 }
196 214
197 ~AudioRendererHostTest() override { 215 ~AudioRendererHostTest() override {
198 // Simulate closing the IPC channel and give the audio thread time to close 216 // Simulate closing the IPC channel and give the audio thread time to close
199 // the underlying streams. 217 // the underlying streams.
200 host_->OnChannelClosing(); 218 host_->OnChannelClosing();
201 SyncWithAudioThread(); 219 SyncWithAudioThread();
202 220
203 // Release the reference to the mock object. The object will be destructed 221 // Release the reference to the mock object. The object will be destructed
204 // on message_loop_. 222 // on message_loop_.
205 host_ = NULL; 223 host_ = NULL;
206 } 224 }
207 225
208 protected: 226 protected:
209 void Create() { 227 void Create() {
210 Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 228 Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true,
229 true);
211 } 230 }
212 231
213 void Create(bool unified_stream, 232 void Create(bool unified_stream,
214 const std::string& device_id, 233 const std::string& device_id,
215 const url::Origin& security_origin, 234 const url::Origin& security_origin,
216 bool wait_for_auth) { 235 bool wait_for_auth,
236 bool expect_onauthorized) {
217 media::OutputDeviceStatus expected_device_status = 237 media::OutputDeviceStatus expected_device_status =
218 device_id == kDefaultDeviceId 238 device_id == kDefaultDeviceId
219 ? media::OUTPUT_DEVICE_STATUS_OK 239 ? media::OUTPUT_DEVICE_STATUS_OK
220 : device_id == kBadDeviceId 240 : device_id == kBadDeviceId
221 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED 241 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED
222 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; 242 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND;
223 243
224 EXPECT_CALL(*host_.get(), 244 if (expect_onauthorized)
225 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); 245 EXPECT_CALL(*host_.get(),
246 OnDeviceAuthorized(kStreamId, expected_device_status, _, _));
226 247
227 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 248 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
228 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); 249 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
229 EXPECT_CALL(mirroring_manager_, 250 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(),
230 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull())) 251 kRenderFrameId, NotNull()))
231 .RetiresOnSaturation(); 252 .RetiresOnSaturation();
232 } 253 }
233 254
234 // Send a create stream message to the audio output stream and wait until 255 // Send a create stream message to the audio output stream and wait until
235 // we receive the created message. 256 // we receive the created message.
236 media::AudioParameters params( 257 media::AudioParameters params(
237 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 258 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
238 media::AudioParameters::kAudioCDSampleRate, 16, 259 media::AudioParameters::kAudioCDSampleRate, 16,
239 media::AudioParameters::kAudioCDSampleRate / 10); 260 media::AudioParameters::kAudioCDSampleRate / 10);
240 int session_id = 0; 261 int session_id = 0;
(...skipping 21 matching lines...) Expand all
262 283
263 void RequestDeviceAuthorizationWithBadOrigin(const std::string& device_id) { 284 void RequestDeviceAuthorizationWithBadOrigin(const std::string& device_id) {
264 int session_id = 0; 285 int session_id = 0;
265 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 286 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
266 device_id, 287 device_id,
267 url::Origin(GURL(kBadSecurityOrigin))); 288 url::Origin(GURL(kBadSecurityOrigin)));
268 SyncWithAudioThread(); 289 SyncWithAudioThread();
269 } 290 }
270 291
271 void CreateWithoutWaitingForAuth(const std::string& device_id) { 292 void CreateWithoutWaitingForAuth(const std::string& device_id) {
272 Create(false, device_id, url::Origin(GURL(kSecurityOrigin)), false); 293 Create(false, device_id, url::Origin(GURL(kSecurityOrigin)), false, true);
273 } 294 }
274 295
275 void CreateWithInvalidRenderFrameId() { 296 void CreateWithInvalidRenderFrameId() {
276 // When creating a stream with an invalid render frame ID, the host will 297 // When creating a stream with an invalid render frame ID, the host will
277 // reply with a stream error message. 298 // reply with a stream error message.
278 EXPECT_CALL(*host_, OnStreamError(kStreamId)); 299 EXPECT_CALL(*host_, OnStreamError(kStreamId));
279 300
280 // However, validation does not block stream creation, so these method calls 301 // However, validation does not block stream creation, so these method calls
281 // might be made: 302 // might be made:
282 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0)); 303 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 // closing an audio stream. 358 // closing an audio stream.
338 void SyncWithAudioThread() { 359 void SyncWithAudioThread() {
339 base::RunLoop().RunUntilIdle(); 360 base::RunLoop().RunUntilIdle();
340 361
341 base::RunLoop run_loop; 362 base::RunLoop run_loop;
342 audio_manager_->GetTaskRunner()->PostTask( 363 audio_manager_->GetTaskRunner()->PostTask(
343 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 364 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
344 run_loop.Run(); 365 run_loop.Run();
345 } 366 }
346 367
347 void ExpectShutdown() { 368 void AssertBadMsgReported() {
348 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(1); 369 // Bad messages can be reported either directly to the RPH or through the
370 // ARH, so we check both of them.
371 EXPECT_EQ(render_process_host_.bad_msg_count() + host_->bad_msg_count, 1);
349 } 372 }
350 373
351 private: 374 private:
352 // MediaStreamManager uses a DestructionObserver, so it must outlive the 375 // MediaStreamManager uses a DestructionObserver, so it must outlive the
353 // TestBrowserThreadBundle. 376 // TestBrowserThreadBundle.
354 std::unique_ptr<MediaStreamManager> media_stream_manager_; 377 std::unique_ptr<MediaStreamManager> media_stream_manager_;
355 TestBrowserThreadBundle thread_bundle_; 378 TestBrowserThreadBundle thread_bundle_;
356 media::ScopedAudioManagerPtr audio_manager_; 379 media::ScopedAudioManagerPtr audio_manager_;
357 MockAudioMirroringManager mirroring_manager_; 380 MockAudioMirroringManager mirroring_manager_;
381 TestBrowserContext browser_context_;
382 MockRenderProcessHostWithSignaling render_process_host_;
358 scoped_refptr<MockAudioRendererHost> host_; 383 scoped_refptr<MockAudioRendererHost> host_;
359 base::RunLoop auth_run_loop_; 384 base::RunLoop auth_run_loop_;
360 385
361 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 386 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
362 }; 387 };
363 388
364 TEST_F(AudioRendererHostTest, CreateAndClose) { 389 TEST_F(AudioRendererHostTest, CreateAndClose) {
365 Create(); 390 Create();
366 Close(); 391 Close();
367 } 392 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 // the audio device is closed but the render process try to close the 440 // the audio device is closed but the render process try to close the
416 // audio stream again. 441 // audio stream again.
417 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { 442 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
418 Create(); 443 Create();
419 Play(); 444 Play();
420 SimulateError(); 445 SimulateError();
421 Close(); 446 Close();
422 } 447 }
423 448
424 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { 449 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
425 Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 450 Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true,
451 true);
426 Close(); 452 Close();
427 } 453 }
428 454
429 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) { 455 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) {
430 Create(false, kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 456 Create(false, kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true, true);
431 Close(); 457 Close();
432 } 458 }
433 459
434 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) { 460 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) {
435 ExpectShutdown();
436 CreateWithoutWaitingForAuth(kBadDeviceId); 461 CreateWithoutWaitingForAuth(kBadDeviceId);
437 Close(); 462 Close();
463 AssertBadMsgReported();
438 } 464 }
439 465
440 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) { 466 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) {
441 ExpectShutdown();
442 RequestDeviceAuthorizationWithBadOrigin(kNondefaultDeviceId); 467 RequestDeviceAuthorizationWithBadOrigin(kNondefaultDeviceId);
443 Close(); 468 Close();
469 AssertBadMsgReported();
444 } 470 }
445 471
446 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 472 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
447 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 473 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true,
474 false);
448 Close(); 475 Close();
476 AssertBadMsgReported();
449 } 477 }
450 478
451 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { 479 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) {
452 CreateWithInvalidRenderFrameId(); 480 CreateWithInvalidRenderFrameId();
453 Close(); 481 Close();
454 } 482 }
455 483
456 // TODO(hclam): Add tests for data conversation in low latency mode. 484 // TODO(hclam): Add tests for data conversation in low latency mode.
457 485
458 } // namespace content 486 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698