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

Side by Side Diff: ppapi/tests/test_url_loader.cc

Issue 6899055: PPAPI: Force async callback invocation option. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "ppapi/tests/test_url_loader.h" 5 #include "ppapi/tests/test_url_loader.h"
6 6
7 #include <stdio.h> 7 #include <stdio.h>
8 #include <string.h> 8 #include <string.h>
9 #include <string> 9 #include <string>
10 10
(...skipping 23 matching lines...) Expand all
34 bool TestURLLoader::Init() { 34 bool TestURLLoader::Init() {
35 file_io_trusted_interface_ = static_cast<const PPB_FileIOTrusted_Dev*>( 35 file_io_trusted_interface_ = static_cast<const PPB_FileIOTrusted_Dev*>(
36 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_DEV_INTERFACE)); 36 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_DEV_INTERFACE));
37 if (!file_io_trusted_interface_) { 37 if (!file_io_trusted_interface_) {
38 instance_->AppendError("FileIOTrusted interface not available"); 38 instance_->AppendError("FileIOTrusted interface not available");
39 } 39 }
40 return InitTestingInterface() && EnsureRunningOverHTTP(); 40 return InitTestingInterface() && EnsureRunningOverHTTP();
41 } 41 }
42 42
43 void TestURLLoader::RunTest() { 43 void TestURLLoader::RunTest() {
44 RUN_TEST(BasicGET); 44 RUN_ASYNC_TEST(BasicGET);
45 RUN_TEST(BasicPOST); 45 RUN_ASYNC_TEST(BasicPOST);
46 RUN_TEST(CompoundBodyPOST); 46 RUN_ASYNC_TEST(CompoundBodyPOST);
47 RUN_TEST(EmptyDataPOST); 47 RUN_ASYNC_TEST(EmptyDataPOST);
48 RUN_TEST(BinaryDataPOST); 48 RUN_ASYNC_TEST(BinaryDataPOST);
49 RUN_TEST(CustomRequestHeader); 49 RUN_ASYNC_TEST(CustomRequestHeader);
50 RUN_TEST(IgnoresBogusContentLength); 50 RUN_ASYNC_TEST(IgnoresBogusContentLength);
51 RUN_TEST(SameOriginRestriction); 51 RUN_ASYNC_TEST(SameOriginRestriction);
52 RUN_TEST(CrossOriginRequest); 52 RUN_ASYNC_TEST(CrossOriginRequest);
53 RUN_TEST(StreamToFile); 53 RUN_ASYNC_TEST(StreamToFile);
54 RUN_TEST(AuditURLRedirect); 54 RUN_ASYNC_TEST(AuditURLRedirect);
55 RUN_TEST(AbortCalls); 55 RUN_ASYNC_TEST(AbortCalls);
56 } 56 }
57 57
58 std::string TestURLLoader::ReadEntireFile(pp::FileIO_Dev* file_io, 58 std::string TestURLLoader::ReadEntireFile(pp::FileIO_Dev* file_io,
59 std::string* data) { 59 std::string* data) {
60 TestCompletionCallback callback(instance_->pp_instance()); 60 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
61 char buf[256]; 61 char buf[256];
62 int64_t offset = 0; 62 int64_t offset = 0;
63 63
64 for (;;) { 64 for (;;) {
65 int32_t rv = file_io->Read(offset, buf, sizeof(buf), callback); 65 int32_t rv = file_io->Read(offset, buf, sizeof(buf), callback);
66 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
67 return ReportError("FileIO::Read force_async failed", rv);
66 if (rv == PP_OK_COMPLETIONPENDING) 68 if (rv == PP_OK_COMPLETIONPENDING)
67 rv = callback.WaitForResult(); 69 rv = callback.WaitForResult();
68 if (rv < 0) 70 if (rv < 0)
69 return ReportError("FileIO::Read", rv); 71 return ReportError("FileIO::Read", rv);
70 if (rv == 0) 72 if (rv == 0)
71 break; 73 break;
72 offset += rv; 74 offset += rv;
73 data->append(buf, rv); 75 data->append(buf, rv);
74 } 76 }
75 77
76 PASS(); 78 PASS();
77 } 79 }
78 80
79 std::string TestURLLoader::ReadEntireResponseBody(pp::URLLoader* loader, 81 std::string TestURLLoader::ReadEntireResponseBody(pp::URLLoader* loader,
80 std::string* body) { 82 std::string* body) {
81 TestCompletionCallback callback(instance_->pp_instance()); 83 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
82 char buf[2]; // Small so that multiple reads are needed. 84 char buf[2]; // Small so that multiple reads are needed.
83 85
84 for (;;) { 86 for (;;) {
85 int32_t rv = loader->ReadResponseBody(buf, sizeof(buf), callback); 87 int32_t rv = loader->ReadResponseBody(buf, sizeof(buf), callback);
88 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
89 return ReportError("URLLoader::ReadResponseBody force_async failed", rv);
86 if (rv == PP_OK_COMPLETIONPENDING) 90 if (rv == PP_OK_COMPLETIONPENDING)
87 rv = callback.WaitForResult(); 91 rv = callback.WaitForResult();
88 if (rv < 0) 92 if (rv < 0)
89 return ReportError("URLLoader::ReadResponseBody", rv); 93 return ReportError("URLLoader::ReadResponseBody", rv);
90 if (rv == 0) 94 if (rv == 0)
91 break; 95 break;
92 body->append(buf, rv); 96 body->append(buf, rv);
93 } 97 }
94 98
95 PASS(); 99 PASS();
96 } 100 }
97 101
98 std::string TestURLLoader::LoadAndCompareBody( 102 std::string TestURLLoader::LoadAndCompareBody(
99 const pp::URLRequestInfo& request, 103 const pp::URLRequestInfo& request,
100 const std::string& expected_body) { 104 const std::string& expected_body) {
101 TestCompletionCallback callback(instance_->pp_instance()); 105 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
102 106
103 pp::URLLoader loader(*instance_); 107 pp::URLLoader loader(*instance_);
104 int32_t rv = loader.Open(request, callback); 108 int32_t rv = loader.Open(request, callback);
109 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
110 return ReportError("URLLoader::Open force_async failed", rv);
105 if (rv == PP_OK_COMPLETIONPENDING) 111 if (rv == PP_OK_COMPLETIONPENDING)
106 rv = callback.WaitForResult(); 112 rv = callback.WaitForResult();
107 if (rv != PP_OK) 113 if (rv != PP_OK)
108 return ReportError("URLLoader::Open", rv); 114 return ReportError("URLLoader::Open", rv);
109 115
110 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 116 pp::URLResponseInfo response_info(loader.GetResponseInfo());
111 if (response_info.is_null()) 117 if (response_info.is_null())
112 return "URLLoader::GetResponseInfo returned null"; 118 return "URLLoader::GetResponseInfo returned null";
113 int32_t status_code = response_info.GetStatusCode(); 119 int32_t status_code = response_info.GetStatusCode();
114 if (status_code != 200) 120 if (status_code != 200)
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 std::string postdata("postdata"); 194 std::string postdata("postdata");
189 request.AppendDataToBody(postdata.data(), postdata.length()); 195 request.AppendDataToBody(postdata.data(), postdata.length());
190 return LoadAndCompareBody(request, postdata); 196 return LoadAndCompareBody(request, postdata);
191 } 197 }
192 198
193 std::string TestURLLoader::TestStreamToFile() { 199 std::string TestURLLoader::TestStreamToFile() {
194 pp::URLRequestInfo request(instance_); 200 pp::URLRequestInfo request(instance_);
195 request.SetURL("test_url_loader_data/hello.txt"); 201 request.SetURL("test_url_loader_data/hello.txt");
196 request.SetStreamToFile(true); 202 request.SetStreamToFile(true);
197 203
198 TestCompletionCallback callback(instance_->pp_instance()); 204 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
199 205
200 pp::URLLoader loader(*instance_); 206 pp::URLLoader loader(*instance_);
201 int32_t rv = loader.Open(request, callback); 207 int32_t rv = loader.Open(request, callback);
208 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
209 return ReportError("URLLoader::Open force_async failed", rv);
202 if (rv == PP_OK_COMPLETIONPENDING) 210 if (rv == PP_OK_COMPLETIONPENDING)
203 rv = callback.WaitForResult(); 211 rv = callback.WaitForResult();
204 if (rv != PP_OK) 212 if (rv != PP_OK)
205 return ReportError("URLLoader::Open", rv); 213 return ReportError("URLLoader::Open", rv);
206 214
207 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 215 pp::URLResponseInfo response_info(loader.GetResponseInfo());
208 if (response_info.is_null()) 216 if (response_info.is_null())
209 return "URLLoader::GetResponseInfo returned null"; 217 return "URLLoader::GetResponseInfo returned null";
210 int32_t status_code = response_info.GetStatusCode(); 218 int32_t status_code = response_info.GetStatusCode();
211 if (status_code != 200) 219 if (status_code != 200)
212 return "Unexpected HTTP status code"; 220 return "Unexpected HTTP status code";
213 221
214 pp::FileRef_Dev body(response_info.GetBodyAsFileRef()); 222 pp::FileRef_Dev body(response_info.GetBodyAsFileRef());
215 if (body.is_null()) 223 if (body.is_null())
216 return "URLResponseInfo::GetBody returned null"; 224 return "URLResponseInfo::GetBody returned null";
217 225
218 rv = loader.FinishStreamingToFile(callback); 226 rv = loader.FinishStreamingToFile(callback);
227 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
228 return ReportError("URLLoader::FinishStreamingToFile force_async failed",
229 rv);
219 if (rv == PP_OK_COMPLETIONPENDING) 230 if (rv == PP_OK_COMPLETIONPENDING)
220 rv = callback.WaitForResult(); 231 rv = callback.WaitForResult();
221 if (rv != PP_OK) 232 if (rv != PP_OK)
222 return ReportError("URLLoader::FinishStreamingToFile", rv); 233 return ReportError("URLLoader::FinishStreamingToFile", rv);
223 234
224 pp::FileIO_Dev reader(instance_); 235 pp::FileIO_Dev reader(instance_);
225 rv = reader.Open(body, PP_FILEOPENFLAG_READ, callback); 236 rv = reader.Open(body, PP_FILEOPENFLAG_READ, callback);
237 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
238 return ReportError("FileIO::Open force_async failed", rv);
226 if (rv == PP_OK_COMPLETIONPENDING) 239 if (rv == PP_OK_COMPLETIONPENDING)
227 rv = callback.WaitForResult(); 240 rv = callback.WaitForResult();
228 if (rv != PP_OK) 241 if (rv != PP_OK)
229 return ReportError("FileIO::Open", rv); 242 return ReportError("FileIO::Open", rv);
230 243
231 std::string data; 244 std::string data;
232 std::string error = ReadEntireFile(&reader, &data); 245 std::string error = ReadEntireFile(&reader, &data);
233 if (!error.empty()) 246 if (!error.empty())
234 return error; 247 return error;
235 248
236 std::string expected_body = "hello\n"; 249 std::string expected_body = "hello\n";
237 if (data.size() != expected_body.size()) 250 if (data.size() != expected_body.size())
238 return "ReadEntireFile returned unexpected content length"; 251 return "ReadEntireFile returned unexpected content length";
239 if (data != expected_body) 252 if (data != expected_body)
240 return "ReadEntireFile returned unexpected content"; 253 return "ReadEntireFile returned unexpected content";
241 254
242 int32_t file_descriptor = file_io_trusted_interface_->GetOSFileDescriptor( 255 int32_t file_descriptor = file_io_trusted_interface_->GetOSFileDescriptor(
243 reader.pp_resource()); 256 reader.pp_resource());
244 if (file_descriptor < 0) 257 if (file_descriptor < 0)
245 return "FileIO::GetOSFileDescriptor() returned a bad file descriptor."; 258 return "FileIO::GetOSFileDescriptor() returned a bad file descriptor.";
246 259
247 PASS(); 260 PASS();
248 } 261 }
249 262
250 std::string TestURLLoader::TestSameOriginRestriction() { 263 std::string TestURLLoader::TestSameOriginRestriction() {
251 pp::URLRequestInfo request(instance_); 264 pp::URLRequestInfo request(instance_);
252 request.SetURL("http://www.google.com/"); 265 request.SetURL("http://www.google.com/");
253 266
254 TestCompletionCallback callback(instance_->pp_instance()); 267 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
255 268
256 pp::URLLoader loader(*instance_); 269 pp::URLLoader loader(*instance_);
257 int32_t rv = loader.Open(request, callback); 270 int32_t rv = loader.Open(request, callback);
271 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
272 return ReportError("URLLoader::Open force_async failed", rv);
258 if (rv == PP_OK_COMPLETIONPENDING) 273 if (rv == PP_OK_COMPLETIONPENDING)
259 rv = callback.WaitForResult(); 274 rv = callback.WaitForResult();
260 275
261 // We expect a failure. 276 // We expect a failure.
262 if (rv != PP_ERROR_NOACCESS) { 277 if (rv != PP_ERROR_NOACCESS) {
263 if (rv == PP_OK) { 278 if (rv == PP_OK) {
264 return "URLLoader::Open() failed to block a cross-origin request."; 279 return "URLLoader::Open() failed to block a cross-origin request.";
265 } else { 280 } else {
266 return ReportError("URLLoader::Open()", rv); 281 return ReportError("URLLoader::Open()", rv);
267 } 282 }
268 } 283 }
269 284
270 PASS(); 285 PASS();
271 } 286 }
272 287
273 std::string TestURLLoader::TestCrossOriginRequest() { 288 std::string TestURLLoader::TestCrossOriginRequest() {
274 pp::URLRequestInfo request(instance_); 289 pp::URLRequestInfo request(instance_);
275 // Create a URL that will be considered to be a different origin. 290 // Create a URL that will be considered to be a different origin.
276 request.SetURL("http://127.0.0.1/test_url_loader_data/hello.txt"); 291 request.SetURL("http://127.0.0.1/test_url_loader_data/hello.txt");
277 request.SetAllowCrossOriginRequests(true); 292 request.SetAllowCrossOriginRequests(true);
278 293
279 TestCompletionCallback callback(instance_->pp_instance()); 294 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
280 295
281 pp::URLLoader loader(*instance_); 296 pp::URLLoader loader(*instance_);
282 int32_t rv = loader.Open(request, callback); 297 int32_t rv = loader.Open(request, callback);
283 if (rv == PP_ERROR_WOULDBLOCK) 298 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
299 return ReportError("URLLoader::Open force_async failed", rv);
300 if (rv == PP_OK_COMPLETIONPENDING)
284 rv = callback.WaitForResult(); 301 rv = callback.WaitForResult();
285 302
286 // We expect success since we allowed a cross-origin request. 303 // We expect success since we allowed a cross-origin request.
287 if (rv == PP_ERROR_NOACCESS) 304 if (rv == PP_ERROR_NOACCESS)
288 return ReportError("URLLoader::Open()", rv); 305 return ReportError("URLLoader::Open()", rv);
289 306
290 PASS(); 307 PASS();
291 } 308 }
292 309
293 // This test should cause a redirect and ensure that the loader runs 310 // This test should cause a redirect and ensure that the loader runs
294 // the callback, rather than following the redirect. 311 // the callback, rather than following the redirect.
295 std::string TestURLLoader::TestAuditURLRedirect() { 312 std::string TestURLLoader::TestAuditURLRedirect() {
296 pp::URLRequestInfo request(instance_); 313 pp::URLRequestInfo request(instance_);
297 // This path will cause the server to return a 301 redirect. 314 // This path will cause the server to return a 301 redirect.
298 request.SetURL("/server-redirect?www.google.com"); 315 request.SetURL("/server-redirect?www.google.com");
299 request.SetFollowRedirects(false); 316 request.SetFollowRedirects(false);
300 317
301 TestCompletionCallback callback(instance_->pp_instance()); 318 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
302 319
303 pp::URLLoader loader(*instance_); 320 pp::URLLoader loader(*instance_);
304 int32_t rv = loader.Open(request, callback); 321 int32_t rv = loader.Open(request, callback);
322 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
323 return ReportError("URLLoader::Open force_async failed", rv);
305 if (rv == PP_OK_COMPLETIONPENDING) 324 if (rv == PP_OK_COMPLETIONPENDING)
306 rv = callback.WaitForResult(); 325 rv = callback.WaitForResult();
307 if (rv != PP_OK) 326 if (rv != PP_OK)
308 return ReportError("URLLoader::Open", rv); 327 return ReportError("URLLoader::Open", rv);
309 328
310 // Checks that the response indicates a redirect, and that the URL 329 // Checks that the response indicates a redirect, and that the URL
311 // is correct. 330 // is correct.
312 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 331 pp::URLResponseInfo response_info(loader.GetResponseInfo());
313 if (response_info.is_null()) 332 if (response_info.is_null())
314 return "URLLoader::GetResponseInfo returned null"; 333 return "URLLoader::GetResponseInfo returned null";
315 int32_t status_code = response_info.GetStatusCode(); 334 int32_t status_code = response_info.GetStatusCode();
316 if (status_code != 301) 335 if (status_code != 301)
317 return "Response status should be 301"; 336 return "Response status should be 301";
318 if (response_info.GetRedirectURL().AsString() != "www.google.com") 337 if (response_info.GetRedirectURL().AsString() != "www.google.com")
319 return "Redirect URL should be www.google.com"; 338 return "Redirect URL should be www.google.com";
320 339
321 PASS(); 340 PASS();
322 } 341 }
323 342
324 std::string TestURLLoader::TestAbortCalls() { 343 std::string TestURLLoader::TestAbortCalls() {
325 pp::URLRequestInfo request(instance_); 344 pp::URLRequestInfo request(instance_);
326 request.SetURL("test_url_loader_data/hello.txt"); 345 request.SetURL("test_url_loader_data/hello.txt");
327 346
328 TestCompletionCallback callback(instance_->pp_instance()); 347 TestCompletionCallback callback(instance_->pp_instance(), force_async_);
329 int32_t rv; 348 int32_t rv;
330 349
331 // Abort |Open()|. 350 // Abort |Open()|.
332 { 351 {
333 callback.reset_run_count(); 352 callback.reset_run_count();
334 rv = pp::URLLoader(*instance_).Open(request, callback); 353 rv = pp::URLLoader(*instance_).Open(request, callback);
354 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
355 return ReportError("URLLoader::Open force_async failed", rv);
335 if (callback.run_count() > 0) 356 if (callback.run_count() > 0)
336 return "URLLoader::Open ran callback synchronously."; 357 return "URLLoader::Open ran callback synchronously.";
337 if (rv == PP_OK_COMPLETIONPENDING) { 358 if (rv == PP_OK_COMPLETIONPENDING) {
338 rv = callback.WaitForResult(); 359 rv = callback.WaitForResult();
339 if (rv != PP_ERROR_ABORTED) 360 if (rv != PP_ERROR_ABORTED)
340 return "URLLoader::Open not aborted."; 361 return "URLLoader::Open not aborted.";
341 } else if (rv != PP_OK) { 362 } else if (rv != PP_OK) {
342 return ReportError("URLLoader::Open", rv); 363 return ReportError("URLLoader::Open", rv);
343 } 364 }
344 } 365 }
345 366
346 // Abort |ReadResponseBody()|. 367 // Abort |ReadResponseBody()|.
347 { 368 {
348 char buf[2] = { 0 }; 369 char buf[2] = { 0 };
349 { 370 {
350 pp::URLLoader loader(*instance_); 371 pp::URLLoader loader(*instance_);
351 rv = loader.Open(request, callback); 372 rv = loader.Open(request, callback);
373 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
374 return ReportError("URLLoader::Open force_async failed", rv);
352 if (rv == PP_OK_COMPLETIONPENDING) 375 if (rv == PP_OK_COMPLETIONPENDING)
353 rv = callback.WaitForResult(); 376 rv = callback.WaitForResult();
354 if (rv != PP_OK) 377 if (rv != PP_OK)
355 return ReportError("URLLoader::Open", rv); 378 return ReportError("URLLoader::Open", rv);
356 379
357 callback.reset_run_count(); 380 callback.reset_run_count();
358 rv = loader.ReadResponseBody(buf, sizeof(buf), callback); 381 rv = loader.ReadResponseBody(buf, sizeof(buf), callback);
382 if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
383 return ReportError("URLLoader::ReadResponseBody force_async failed",
384 rv);
359 } // Destroy |loader|. 385 } // Destroy |loader|.
360 if (rv == PP_OK_COMPLETIONPENDING) { 386 if (rv == PP_OK_COMPLETIONPENDING) {
361 // Save a copy and make sure |buf| doesn't get written to. 387 // Save a copy and make sure |buf| doesn't get written to.
362 char buf_copy[2]; 388 char buf_copy[2];
363 memcpy(&buf_copy, &buf, sizeof(buf)); 389 memcpy(&buf_copy, &buf, sizeof(buf));
364 rv = callback.WaitForResult(); 390 rv = callback.WaitForResult();
365 if (rv != PP_ERROR_ABORTED) 391 if (rv != PP_ERROR_ABORTED)
366 return "URLLoader::ReadResponseBody not aborted."; 392 return "URLLoader::ReadResponseBody not aborted.";
367 if (memcmp(&buf_copy, &buf, sizeof(buf)) != 0) 393 if (memcmp(&buf_copy, &buf, sizeof(buf)) != 0)
368 return "URLLoader::ReadResponseBody wrote data after resource " 394 return "URLLoader::ReadResponseBody wrote data after resource "
369 "destruction."; 395 "destruction.";
370 } else if (rv != PP_OK) { 396 } else if (rv != PP_OK) {
371 return ReportError("URLLoader::ReadResponseBody", rv); 397 return ReportError("URLLoader::ReadResponseBody", rv);
372 } 398 }
373 } 399 }
374 400
375 // TODO(viettrungluu): More abort tests (but add basic tests first). 401 // TODO(viettrungluu): More abort tests (but add basic tests first).
376 // Also test that Close() aborts properly. crbug.com/69457 402 // Also test that Close() aborts properly. crbug.com/69457
377 403
378 PASS(); 404 PASS();
379 } 405 }
380 406
381 // TODO(viettrungluu): Add tests for FollowRedirect, 407 // TODO(viettrungluu): Add tests for FollowRedirect,
382 // Get{Upload,Download}Progress, Close (including abort tests if applicable). 408 // Get{Upload,Download}Progress, Close (including abort tests if applicable).
383 // TODO(darin): Add a test for GrantUniversalAccess. 409 // TODO(darin): Add a test for GrantUniversalAccess.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698