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 3 // found in the LICENSE file. 4 5 #include "base/strings/stringprintf.h" 6 #include "chrome/browser/browser_process.h" 7 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/extensions/api/notifications/notifications_api.h" 9 #include "chrome/browser/extensions/extension_apitest.h" 10 #include "chrome/browser/extensions/extension_function_test_utils.h" 11 #include "chrome/common/extensions/features/feature.h" 12 #include "content/public/browser/notification_service.h" 13 #include "content/public/test/test_utils.h" 14 #include "ui/message_center/message_center.h" 15 #include "ui/message_center/message_center_switches.h" 16 #include "ui/message_center/message_center_util.h" 17 18 using extensions::Extension; 19 20 namespace utils = extension_function_test_utils; 21 22 namespace { 23 24 class NotificationsApiTest : public ExtensionApiTest { 25 public: 26 const extensions::Extension* LoadExtensionAndWait( 27 const std::string& test_name) { 28 base::FilePath extdir = test_data_dir_.AppendASCII(test_name); 29 content::WindowedNotificationObserver page_created( 30 chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, 31 content::NotificationService::AllSources()); 32 const extensions::Extension* extension = LoadExtension(extdir); 33 if (extension) { 34 page_created.Wait(); 35 } 36 return extension; 37 } 38 }; 39 40 } // namespace 41 42 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestIdUsage) { 43 // Create a new notification. A lingering output of this block is the 44 // notifications ID, which we'll use in later parts of this test. 45 std::string notification_id; 46 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 47 { 48 scoped_refptr<extensions::NotificationsCreateFunction> 49 notification_function( 50 new extensions::NotificationsCreateFunction()); 51 52 notification_function->set_extension(empty_extension.get()); 53 notification_function->set_has_callback(true); 54 55 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 56 notification_function.get(), 57 "[\"\", " // Empty string: ask API to generate ID 58 "{" 59 "\"type\": \"basic\"," 60 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 61 "\"title\": \"Attention!\"," 62 "\"message\": \"Check out Cirque du Soleil\"" 63 "}]", 64 browser(), 65 utils::NONE)); 66 67 ASSERT_EQ(base::Value::TYPE_STRING, result->GetType()); 68 ASSERT_TRUE(result->GetAsString(¬ification_id)); 69 ASSERT_TRUE(notification_id.length() > 0); 70 } 71 72 // Update the existing notification. 73 { 74 scoped_refptr<extensions::NotificationsUpdateFunction> 75 notification_function( 76 new extensions::NotificationsUpdateFunction()); 77 78 notification_function->set_extension(empty_extension.get()); 79 notification_function->set_has_callback(true); 80 81 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 82 notification_function.get(), 83 "[\"" + notification_id + 84 "\", " 85 "{" 86 "\"type\": \"basic\"," 87 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 88 "\"title\": \"Attention!\"," 89 "\"message\": \"Too late! The show ended yesterday\"" 90 "}]", 91 browser(), 92 utils::NONE)); 93 94 ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 95 bool copy_bool_value = false; 96 ASSERT_TRUE(result->GetAsBoolean(©_bool_value)); 97 ASSERT_TRUE(copy_bool_value); 98 99 // TODO(miket): add a testing method to query the message from the 100 // displayed notification, and assert it matches the updated message. 101 // 102 // TODO(miket): add a method to count the number of outstanding 103 // notifications, and confirm it remains at one at this point. 104 } 105 106 // Update a nonexistent notification. 107 { 108 scoped_refptr<extensions::NotificationsUpdateFunction> 109 notification_function( 110 new extensions::NotificationsUpdateFunction()); 111 112 notification_function->set_extension(empty_extension.get()); 113 notification_function->set_has_callback(true); 114 115 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 116 notification_function.get(), 117 "[\"xxxxxxxxxxxx\", " 118 "{" 119 "\"type\": \"basic\"," 120 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 121 "\"title\": \"!\"," 122 "\"message\": \"!\"" 123 "}]", 124 browser(), 125 utils::NONE)); 126 127 ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 128 bool copy_bool_value = false; 129 ASSERT_TRUE(result->GetAsBoolean(©_bool_value)); 130 ASSERT_FALSE(copy_bool_value); 131 } 132 133 // Clear a nonexistent notification. 134 { 135 scoped_refptr<extensions::NotificationsClearFunction> 136 notification_function( 137 new extensions::NotificationsClearFunction()); 138 139 notification_function->set_extension(empty_extension.get()); 140 notification_function->set_has_callback(true); 141 142 scoped_ptr<base::Value> result( 143 utils::RunFunctionAndReturnSingleResult(notification_function.get(), 144 "[\"xxxxxxxxxxx\"]", 145 browser(), 146 utils::NONE)); 147 148 ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 149 bool copy_bool_value = false; 150 ASSERT_TRUE(result->GetAsBoolean(©_bool_value)); 151 ASSERT_FALSE(copy_bool_value); 152 } 153 154 // Clear the notification we created. 155 { 156 scoped_refptr<extensions::NotificationsClearFunction> 157 notification_function( 158 new extensions::NotificationsClearFunction()); 159 160 notification_function->set_extension(empty_extension.get()); 161 notification_function->set_has_callback(true); 162 163 scoped_ptr<base::Value> result( 164 utils::RunFunctionAndReturnSingleResult(notification_function.get(), 165 "[\"" + notification_id + "\"]", 166 browser(), 167 utils::NONE)); 168 169 ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 170 bool copy_bool_value = false; 171 ASSERT_TRUE(result->GetAsBoolean(©_bool_value)); 172 ASSERT_TRUE(copy_bool_value); 173 } 174 } 175 176 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestBaseFormatNotification) { 177 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 178 179 // Create a new notification with the minimum required properties. 180 { 181 scoped_refptr<extensions::NotificationsCreateFunction> 182 notification_create_function( 183 new extensions::NotificationsCreateFunction()); 184 notification_create_function->set_extension(empty_extension.get()); 185 notification_create_function->set_has_callback(true); 186 187 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 188 notification_create_function.get(), 189 "[\"\", " 190 "{" 191 "\"type\": \"basic\"," 192 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 193 "\"title\": \"Attention!\"," 194 "\"message\": \"Check out Cirque du Soleil\"" 195 "}]", 196 browser(), 197 utils::NONE)); 198 199 std::string notification_id; 200 ASSERT_EQ(base::Value::TYPE_STRING, result->GetType()); 201 ASSERT_TRUE(result->GetAsString(¬ification_id)); 202 ASSERT_TRUE(notification_id.length() > 0); 203 } 204 205 // Create another new notification with more than the required properties. 206 { 207 scoped_refptr<extensions::NotificationsCreateFunction> 208 notification_create_function( 209 new extensions::NotificationsCreateFunction()); 210 notification_create_function->set_extension(empty_extension.get()); 211 notification_create_function->set_has_callback(true); 212 213 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 214 notification_create_function.get(), 215 "[\"\", " 216 "{" 217 "\"type\": \"basic\"," 218 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 219 "\"title\": \"Attention!\"," 220 "\"message\": \"Check out Cirque du Soleil\"," 221 "\"priority\": 1," 222 "\"eventTime\": 1234567890.12345678," 223 "\"buttons\": [" 224 " {" 225 " \"title\": \"Up\"," 226 " \"iconUrl\":\"http://www.google.com/logos/2012/\"" 227 " }," 228 " {" 229 " \"title\": \"Down\"" // note: no iconUrl 230 " }" 231 "]," 232 "\"expandedMessage\": \"This is a longer expanded message.\"," 233 "\"imageUrl\": \"http://www.google.com/logos/2012/election12-hp.jpg\"" 234 "}]", 235 browser(), 236 utils::NONE)); 237 238 std::string notification_id; 239 ASSERT_EQ(base::Value::TYPE_STRING, result->GetType()); 240 ASSERT_TRUE(result->GetAsString(¬ification_id)); 241 ASSERT_TRUE(notification_id.length() > 0); 242 } 243 244 // Error case: missing type property. 245 { 246 scoped_refptr<extensions::NotificationsCreateFunction> 247 notification_create_function( 248 new extensions::NotificationsCreateFunction()); 249 notification_create_function->set_extension(empty_extension.get()); 250 notification_create_function->set_has_callback(true); 251 252 utils::RunFunction( 253 notification_create_function.get(), 254 "[\"\", " 255 "{" 256 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 257 "\"title\": \"Attention!\"," 258 "\"message\": \"Check out Cirque du Soleil\"" 259 "}]", 260 browser(), 261 utils::NONE); 262 263 EXPECT_FALSE(notification_create_function->GetError().empty()); 264 } 265 266 // Error case: missing iconUrl property. 267 { 268 scoped_refptr<extensions::NotificationsCreateFunction> 269 notification_create_function( 270 new extensions::NotificationsCreateFunction()); 271 notification_create_function->set_extension(empty_extension.get()); 272 notification_create_function->set_has_callback(true); 273 274 utils::RunFunction( 275 notification_create_function.get(), 276 "[\"\", " 277 "{" 278 "\"type\": \"basic\"," 279 "\"title\": \"Attention!\"," 280 "\"message\": \"Check out Cirque du Soleil\"" 281 "}]", 282 browser(), 283 utils::NONE); 284 285 EXPECT_FALSE(notification_create_function->GetError().empty()); 286 } 287 288 // Error case: missing title property. 289 { 290 scoped_refptr<extensions::NotificationsCreateFunction> 291 notification_create_function( 292 new extensions::NotificationsCreateFunction()); 293 notification_create_function->set_extension(empty_extension.get()); 294 notification_create_function->set_has_callback(true); 295 296 utils::RunFunction( 297 notification_create_function.get(), 298 "[\"\", " 299 "{" 300 "\"type\": \"basic\"," 301 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 302 "\"message\": \"Check out Cirque du Soleil\"" 303 "}]", 304 browser(), 305 utils::NONE); 306 307 EXPECT_FALSE(notification_create_function->GetError().empty()); 308 } 309 310 // Error case: missing message property. 311 { 312 scoped_refptr<extensions::NotificationsCreateFunction> 313 notification_create_function( 314 new extensions::NotificationsCreateFunction()); 315 notification_create_function->set_extension(empty_extension.get()); 316 notification_create_function->set_has_callback(true); 317 318 utils::RunFunction( 319 notification_create_function.get(), 320 "[\"\", " 321 "{" 322 "\"type\": \"basic\"," 323 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 324 "\"title\": \"Attention!\"" 325 "}]", 326 browser(), 327 utils::NONE); 328 329 EXPECT_FALSE(notification_create_function->GetError().empty()); 330 } 331 } 332 333 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestMultipleItemNotification) { 334 scoped_refptr<extensions::NotificationsCreateFunction> 335 notification_create_function( 336 new extensions::NotificationsCreateFunction()); 337 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 338 339 notification_create_function->set_extension(empty_extension.get()); 340 notification_create_function->set_has_callback(true); 341 342 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 343 notification_create_function.get(), 344 "[\"\", " 345 "{" 346 "\"type\": \"list\"," 347 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 348 "\"title\": \"Multiple Item Notification Title\"," 349 "\"message\": \"Multiple item notification message.\"," 350 "\"items\": [" 351 " {\"title\": \"Brett Boe\"," 352 " \"message\": \"This is an important message!\"}," 353 " {\"title\": \"Carla Coe\"," 354 " \"message\": \"Just took a look at the proposal\"}," 355 " {\"title\": \"Donna Doe\"," 356 " \"message\": \"I see that you went to the conference\"}," 357 " {\"title\": \"Frank Foe\"," 358 " \"message\": \"I ate Harry's sandwich!\"}," 359 " {\"title\": \"Grace Goe\"," 360 " \"message\": \"I saw Frank steal a sandwich :-)\"}" 361 "]," 362 "\"priority\": 1," 363 "\"eventTime\": 1361488019.9999999" 364 "}]", 365 browser(), 366 utils::NONE)); 367 // TODO(dharcourt): [...], items = [{title: foo, message: bar}, ...], [...] 368 369 std::string notification_id; 370 ASSERT_EQ(base::Value::TYPE_STRING, result->GetType()); 371 ASSERT_TRUE(result->GetAsString(¬ification_id)); 372 ASSERT_TRUE(notification_id.length() > 0); 373 } 374 375 #if defined(OS_LINUX) 376 #define MAYBE_TestGetAll DISABLED_TestGetAll 377 #else 378 #define MAYBE_TestGetAll TestGetAll 379 #endif 380 381 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, MAYBE_TestGetAll) { 382 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 383 384 { 385 scoped_refptr<extensions::NotificationsGetAllFunction> 386 notification_get_all_function( 387 new extensions::NotificationsGetAllFunction()); 388 notification_get_all_function->set_extension(empty_extension.get()); 389 notification_get_all_function->set_has_callback(true); 390 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 391 notification_get_all_function.get(), "[]", browser(), utils::NONE)); 392 393 base::DictionaryValue* return_value; 394 ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType()); 395 ASSERT_TRUE(result->GetAsDictionary(&return_value)); 396 ASSERT_TRUE(return_value->size() == 0); 397 } 398 399 const unsigned int kNotificationsToCreate = 4; 400 401 for (unsigned int i = 0; i < kNotificationsToCreate; i++) { 402 scoped_refptr<extensions::NotificationsCreateFunction> 403 notification_create_function( 404 new extensions::NotificationsCreateFunction()); 405 406 notification_create_function->set_extension(empty_extension.get()); 407 notification_create_function->set_has_callback(true); 408 409 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 410 notification_create_function.get(), 411 base::StringPrintf("[\"identifier-%u\", " 412 "{" 413 "\"type\": \"basic\"," 414 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 415 "\"title\": \"Title\"," 416 "\"message\": \"Message.\"," 417 "\"priority\": 1," 418 "\"eventTime\": 1361488019.9999999" 419 "}]", 420 i), 421 browser(), 422 utils::NONE)); 423 } 424 425 { 426 scoped_refptr<extensions::NotificationsGetAllFunction> 427 notification_get_all_function( 428 new extensions::NotificationsGetAllFunction()); 429 notification_get_all_function->set_extension(empty_extension.get()); 430 notification_get_all_function->set_has_callback(true); 431 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 432 notification_get_all_function.get(), "[]", browser(), utils::NONE)); 433 434 base::DictionaryValue* return_value; 435 ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType()); 436 ASSERT_TRUE(result->GetAsDictionary(&return_value)); 437 ASSERT_EQ(return_value->size(), kNotificationsToCreate); 438 bool dictionary_bool = false; 439 for (unsigned int i = 0; i < kNotificationsToCreate; i++) { 440 std::string id = base::StringPrintf("identifier-%u", i); 441 ASSERT_TRUE(return_value->GetBoolean(id, &dictionary_bool)); 442 ASSERT_TRUE(dictionary_bool); 443 } 444 } 445 } 446 447 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestEvents) { 448 ASSERT_TRUE(RunExtensionTest("notifications/api/events")) << message_; 449 } 450 451 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestCSP) { 452 ASSERT_TRUE(RunExtensionTest("notifications/api/csp")) << message_; 453 } 454 455 // MessaceCenter-specific test. 456 #if defined(RUN_MESSAGE_CENTER_TESTS) 457 #define MAYBE_TestByUser TestByUser 458 #else 459 #define MAYBE_TestByUser DISABLED_TestByUser 460 #endif 461 462 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, MAYBE_TestByUser) { 463 ASSERT_TRUE(message_center::IsRichNotificationEnabled()); 464 465 const extensions::Extension* extension = 466 LoadExtensionAndWait("notifications/api/by_user"); 467 ASSERT_TRUE(extension) << message_; 468 469 { 470 ResultCatcher catcher; 471 g_browser_process->message_center()->RemoveNotification( 472 extension->id() + "-FOO", 473 false); 474 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 475 } 476 477 { 478 ResultCatcher catcher; 479 g_browser_process->message_center()->RemoveNotification( 480 extension->id() + "-BAR", 481 true); 482 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 483 } 484 } 485 486 487 #if defined(OS_LINUX) 488 #define MAYBE_TestProgressNotification DISABLED_TestProgressNotification 489 #else 490 #define MAYBE_TestProgressNotification TestProgressNotification 491 #endif 492 493 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, MAYBE_TestProgressNotification) { 494 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 495 496 // Create a new progress notification. 497 std::string notification_id; 498 { 499 scoped_refptr<extensions::NotificationsCreateFunction> 500 notification_create_function( 501 new extensions::NotificationsCreateFunction()); 502 notification_create_function->set_extension(empty_extension.get()); 503 notification_create_function->set_has_callback(true); 504 505 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 506 notification_create_function.get(), 507 "[\"\", " 508 "{" 509 "\"type\": \"progress\"," 510 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 511 "\"title\": \"Test!\"," 512 "\"message\": \"This is a progress notification.\"," 513 "\"priority\": 1," 514 "\"eventTime\": 1234567890.12345678," 515 "\"progress\": 30" 516 "}]", 517 browser(), 518 utils::NONE)); 519 520 EXPECT_EQ(base::Value::TYPE_STRING, result->GetType()); 521 EXPECT_TRUE(result->GetAsString(¬ification_id)); 522 EXPECT_TRUE(notification_id.length() > 0); 523 } 524 525 // Update the progress property only. 526 { 527 scoped_refptr<extensions::NotificationsUpdateFunction> 528 notification_function( 529 new extensions::NotificationsUpdateFunction()); 530 notification_function->set_extension(empty_extension.get()); 531 notification_function->set_has_callback(true); 532 533 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 534 notification_function.get(), 535 "[\"" + notification_id + 536 "\", " 537 "{" 538 "\"progress\": 60" 539 "}]", 540 browser(), 541 utils::NONE)); 542 543 EXPECT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 544 bool copy_bool_value = false; 545 EXPECT_TRUE(result->GetAsBoolean(©_bool_value)); 546 EXPECT_TRUE(copy_bool_value); 547 } 548 549 // Error case: progress value provided for non-progress type. 550 { 551 scoped_refptr<extensions::NotificationsCreateFunction> 552 notification_create_function( 553 new extensions::NotificationsCreateFunction()); 554 notification_create_function->set_extension(empty_extension.get()); 555 notification_create_function->set_has_callback(true); 556 557 utils::RunFunction( 558 notification_create_function.get(), 559 "[\"\", " 560 "{" 561 "\"type\": \"basic\"," 562 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 563 "\"title\": \"Test!\"," 564 "\"message\": \"This is a progress notification.\"," 565 "\"priority\": 1," 566 "\"eventTime\": 1234567890.12345678," 567 "\"progress\": 10" 568 "}]", 569 browser(), 570 utils::NONE); 571 EXPECT_FALSE(notification_create_function->GetError().empty()); 572 } 573 574 // Error case: progress value less than lower bound. 575 { 576 scoped_refptr<extensions::NotificationsCreateFunction> 577 notification_create_function( 578 new extensions::NotificationsCreateFunction()); 579 notification_create_function->set_extension(empty_extension.get()); 580 notification_create_function->set_has_callback(true); 581 582 utils::RunFunction( 583 notification_create_function.get(), 584 "[\"\", " 585 "{" 586 "\"type\": \"progress\"," 587 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 588 "\"title\": \"Test!\"," 589 "\"message\": \"This is a progress notification.\"," 590 "\"priority\": 1," 591 "\"eventTime\": 1234567890.12345678," 592 "\"progress\": -10" 593 "}]", 594 browser(), 595 utils::NONE); 596 EXPECT_FALSE(notification_create_function->GetError().empty()); 597 } 598 599 // Error case: progress value greater than upper bound. 600 { 601 scoped_refptr<extensions::NotificationsCreateFunction> 602 notification_create_function( 603 new extensions::NotificationsCreateFunction()); 604 notification_create_function->set_extension(empty_extension.get()); 605 notification_create_function->set_has_callback(true); 606 607 utils::RunFunction( 608 notification_create_function.get(), 609 "[\"\", " 610 "{" 611 "\"type\": \"progress\"," 612 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 613 "\"title\": \"Test!\"," 614 "\"message\": \"This is a progress notification.\"," 615 "\"priority\": 1," 616 "\"eventTime\": 1234567890.12345678," 617 "\"progress\": 101" 618 "}]", 619 browser(), 620 utils::NONE); 621 EXPECT_FALSE(notification_create_function->GetError().empty()); 622 } 623 } 624 625 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestPartialUpdate) { 626 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 627 628 // Create a new notification. 629 std::string notification_id; 630 { 631 scoped_refptr<extensions::NotificationsCreateFunction> 632 notification_function( 633 new extensions::NotificationsCreateFunction()); 634 notification_function->set_extension(empty_extension.get()); 635 notification_function->set_has_callback(true); 636 637 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 638 notification_function.get(), 639 "[\"\", " // Empty string: ask API to generate ID 640 "{" 641 "\"type\": \"basic\"," 642 "\"iconUrl\": \"an/image/that/does/not/exist.png\"," 643 "\"title\": \"Attention!\"," 644 "\"message\": \"Check out Cirque du Soleil\"" 645 "}]", 646 browser(), 647 utils::NONE)); 648 649 ASSERT_EQ(base::Value::TYPE_STRING, result->GetType()); 650 ASSERT_TRUE(result->GetAsString(¬ification_id)); 651 ASSERT_TRUE(notification_id.length() > 0); 652 } 653 654 // Update a few properties in the existing notification. 655 { 656 scoped_refptr<extensions::NotificationsUpdateFunction> 657 notification_function( 658 new extensions::NotificationsUpdateFunction()); 659 notification_function->set_extension(empty_extension.get()); 660 notification_function->set_has_callback(true); 661 662 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 663 notification_function.get(), 664 "[\"" + notification_id + 665 "\", " 666 "{" 667 "\"title\": \"Changed!\"," 668 "\"message\": \"Too late! The show ended yesterday\"" 669 "}]", 670 browser(), 671 utils::NONE)); 672 673 ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 674 bool copy_bool_value = false; 675 ASSERT_TRUE(result->GetAsBoolean(©_bool_value)); 676 ASSERT_TRUE(copy_bool_value); 677 } 678 679 // Update another property in the existing notification. 680 { 681 scoped_refptr<extensions::NotificationsUpdateFunction> 682 notification_function( 683 new extensions::NotificationsUpdateFunction()); 684 notification_function->set_extension(empty_extension.get()); 685 notification_function->set_has_callback(true); 686 687 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 688 notification_function.get(), 689 "[\"" + notification_id + 690 "\", " 691 "{" 692 "\"priority\": 2" 693 "}]", 694 browser(), 695 utils::NONE)); 696 697 ASSERT_EQ(base::Value::TYPE_BOOLEAN, result->GetType()); 698 bool copy_bool_value = false; 699 ASSERT_TRUE(result->GetAsBoolean(©_bool_value)); 700 ASSERT_TRUE(copy_bool_value); 701 } 702 } 703