selenium-webdriver 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  2. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  3. data/chrome/src/extension/background.js +64 -48
  4. data/chrome/src/extension/content_script.js +253 -132
  5. data/chrome/src/extension/manifest-nonwin.json +1 -1
  6. data/chrome/src/extension/manifest-win.json +1 -1
  7. data/chrome/src/extension/utils.js +8 -8
  8. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +9 -0
  9. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +38 -280
  10. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +119 -117
  11. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +36 -26
  12. data/common/src/js/abstractcommandprocessor.js +9 -11
  13. data/common/src/js/command.js +159 -83
  14. data/common/src/js/core/RemoteRunner.html +2 -2
  15. data/common/src/js/core/TestRunner-splash.html +3 -3
  16. data/common/src/js/core/TestRunner.html +5 -17
  17. data/common/src/js/core/scripts/htmlutils.js +4208 -2506
  18. data/common/src/js/core/scripts/selenium-api.js +2 -2
  19. data/common/src/js/core/scripts/selenium-browserbot.js +66 -58
  20. data/common/src/js/core/scripts/selenium-version.js +1 -1
  21. data/common/src/js/localcommandprocessor.js +5 -19
  22. data/common/src/js/testcase.js +2 -0
  23. data/common/src/js/webdriver.js +63 -93
  24. data/common/src/js/webelement.js +40 -42
  25. data/common/src/rb/lib/selenium/webdriver.rb +23 -14
  26. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +8 -35
  27. data/common/src/rb/lib/selenium/webdriver/child_process.rb +2 -0
  28. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +1 -0
  29. data/common/src/rb/lib/selenium/webdriver/core_ext/string.rb +5 -0
  30. data/common/src/rb/lib/selenium/webdriver/driver.rb +20 -15
  31. data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +7 -2
  32. data/common/src/rb/lib/selenium/webdriver/element.rb +11 -2
  33. data/common/src/rb/lib/selenium/webdriver/error.rb +9 -5
  34. data/common/src/rb/lib/selenium/webdriver/keys.rb +1 -2
  35. data/common/src/rb/lib/selenium/webdriver/navigation.rb +16 -0
  36. data/common/src/rb/lib/selenium/webdriver/options.rb +32 -0
  37. data/common/src/rb/lib/selenium/webdriver/platform.rb +17 -1
  38. data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
  39. data/firefox/src/extension/components/dispatcher.js +492 -0
  40. data/firefox/src/extension/components/driver-component.js +4 -1
  41. data/firefox/src/extension/components/errorcode.js +70 -0
  42. data/firefox/src/extension/components/firefoxDriver.js +173 -154
  43. data/firefox/src/extension/components/nsCommandProcessor.js +171 -132
  44. data/firefox/src/extension/components/promptService.js +5 -5
  45. data/firefox/src/extension/components/request.js +219 -0
  46. data/firefox/src/extension/components/response.js +276 -0
  47. data/firefox/src/extension/components/session.js +281 -0
  48. data/firefox/src/extension/components/sessionstore.js +226 -0
  49. data/firefox/src/extension/components/socketListener.js +350 -100
  50. data/firefox/src/extension/components/utils.js +166 -98
  51. data/firefox/src/extension/components/webdriverserver.js +9 -5
  52. data/firefox/src/extension/components/wrappedElement.js +189 -166
  53. data/firefox/src/extension/install.rdf +1 -1
  54. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +2 -0
  55. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +39 -33
  56. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +7 -421
  57. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +7 -64
  58. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +2 -3
  59. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +54 -10
  60. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +2 -0
  61. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +6 -0
  62. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  63. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  64. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +2 -0
  65. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +38 -13
  66. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +9 -2
  67. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +5 -0
  68. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +2 -0
  69. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +42 -38
  70. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +56 -47
  71. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +26 -26
  72. data/remote/client/src/rb/lib/selenium/webdriver/remote/patron_http_client.rb +58 -0
  73. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +10 -12
  74. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +2 -17
  75. metadata +44 -23
  76. data/common/src/js/context.js +0 -58
  77. data/firefox/src/extension/components/context.js +0 -37
@@ -297,7 +297,7 @@ chrome.extension.onConnect.addListener(function(port) {
297
297
  }
298
298
  if (ChromeDriver.isClosingTab) {
299
299
  //We are actively closing the tab, and expect a response to this
300
- sendResponseToParsedRequest({statusCode: 0}, false)
300
+ sendResponseToParsedRequest({status: 0}, false)
301
301
  ChromeDriver.isClosingTab = false;
302
302
  if (ChromeDriver.tabs.length == 0) {
303
303
  chrome.windows.getAll({}, function(windows) {
@@ -365,6 +365,7 @@ function sendResponseToParsedRequest(toSend, wait) {
365
365
  ChromeDriver.isBlockedWaitingForResponse = false;
366
366
  ChromeDriver.lastRequestToBeSentWhichHasntBeenAnsweredYet = null;
367
367
  console.log("SENDING RESPOND TO PARSED REQUEST");
368
+ toSend['sessionId'] = 'static_session_id';
368
369
  sendResponseByXHR(JSON.stringify(toSend), wait);
369
370
  setExtensionBusyIndicator(false);
370
371
  }
@@ -383,7 +384,7 @@ function handleXmlHttpRequestReadyStateChange() {
383
384
  if (request.request == "quit") {
384
385
  //We're only allowed to send a response if we're blocked waiting for one, so pretend
385
386
  console.log("SENDING QUIT XHR");
386
- sendResponseByXHR(JSON.stringify({statusCode: 0}), false);
387
+ sendResponseByXHR(JSON.stringify({status: 0}), false);
387
388
  } else {
388
389
  console.log("Got request to execute from XHR: " + this.responseText);
389
390
  parseRequest(request);
@@ -408,6 +409,17 @@ function parseRequest(request) {
408
409
  setExtensionBusyIndicator(true);
409
410
 
410
411
  switch (request.request) {
412
+ case "newSession":
413
+ sendResponseToParsedRequest({
414
+ status: 0,
415
+ value: {
416
+ 'browserName': 'chrome',
417
+ 'version': navigator.appVersion.replace(/.*Chrome\/(\d(\.\d+)*\b).*/, "$1"),
418
+ 'platform': navigator.platform,
419
+ 'javascriptEnabled': true,
420
+ }
421
+ });
422
+ break;
411
423
  case "get":
412
424
  getUrl(request.url);
413
425
  break;
@@ -424,7 +436,7 @@ function parseRequest(request) {
424
436
  var len = ChromeDriver.tabs.length;
425
437
  for (var i = 0; i < len; i++) {
426
438
  if (ChromeDriver.tabs[i].selected) {
427
- sendResponseToParsedRequest({statusCode: 0, value: ChromeDriver.tabs[i].windowName}, false);
439
+ sendResponseToParsedRequest({status: 0, value: ChromeDriver.tabs[i].id}, false);
428
440
  }
429
441
  }
430
442
 
@@ -434,7 +446,7 @@ function parseRequest(request) {
434
446
  var len = ChromeDriver.tabs.length;
435
447
  for (var i = 0; i < len; i++) {
436
448
  if (ChromeDriver.tabs[i].tabId == tab.id) {
437
- sendResponseToParsedRequest({statusCode: 0, value: ChromeDriver.tabs[i].windowName}, false);
449
+ sendResponseToParsedRequest({status: 0, value: ChromeDriver.tabs[i].tabId}, false);
438
450
  return;
439
451
  }
440
452
  }
@@ -443,28 +455,30 @@ function parseRequest(request) {
443
455
  } else {
444
456
  // Wow. I can't see this being error prone in the slightest
445
457
  var handle = ChromeDriver.windowHandlePrefix + "_" + ChromeDriver.activePort.sender.tab.id;
446
- sendResponseToParsedRequest({statusCode: 0, value: handle}, false);
458
+ sendResponseToParsedRequest({status: 0, value: handle}, false);
447
459
  };
448
460
  break;
449
461
  case "getWindowHandles":
450
462
  sendResponseToParsedRequest(getWindowHandles(), false);
451
463
  break;
452
- case "switchToDefaultContent":
453
- switchToDefaultContent();
464
+ case "switchToFrame":
465
+ if (request.id === undefined || request.id === null) {
466
+ switchToDefaultContent();
467
+ } else {
468
+ switchToFrame(request.id);
469
+ }
454
470
  break;
455
471
  case "switchToFrameByIndex":
456
- switchToFrame(null, request.index);
457
- break;
458
472
  case "switchToFrameByName":
459
- switchToFrame(request.name, null);
473
+ switchToFrame(request.id);
460
474
  break;
461
475
  case "switchToWindow":
462
476
  ChromeDriver.hasHwnd = false;
463
- if (request.windowName !== undefined) {
464
- setActivePortByWindowName(request.windowName);
477
+ if (request.name !== undefined) {
478
+ setActivePortByWindowName(request.name);
465
479
  } else {
466
480
  sendResponseToParsedRequest({
467
- statusCode: 3,
481
+ status: 23,
468
482
  value: {
469
483
  message: 'Window to switch to was not given'
470
484
  }
@@ -488,7 +502,7 @@ function parseRequest(request) {
488
502
  case "getTitle":
489
503
  if (hasNoPage()) {
490
504
  console.log("Not got a page, but asked for string, so sending empty string");
491
- sendResponseToParsedRequest({statusCode: 0, value: ''});
505
+ sendResponseToParsedRequest({status: 0, value: ''});
492
506
  break;
493
507
  }
494
508
  // Falling through, as if we do have a page, we want to treat this like a
@@ -497,7 +511,7 @@ function parseRequest(request) {
497
511
  case "findChildElement":
498
512
  if (hasNoPage()) {
499
513
  console.log("Not got a page, but asked for element, so throwing NoSuchElementException");
500
- sendResponseToParsedRequest({statusCode: 7, value: {message: 'Was not on a page, so could not find elements'}});
514
+ sendResponseToParsedRequest({status: 7, value: {message: 'Was not on a page, so could not find elements'}});
501
515
  break;
502
516
  }
503
517
  // Falling through, as if we do have a page, we want to treat this like a
@@ -506,7 +520,7 @@ function parseRequest(request) {
506
520
  case "findChildElements":
507
521
  if (hasNoPage()) {
508
522
  console.log("Not got a page, but asked for elements, so returning no elements");
509
- sendResponseToParsedRequest({statusCode: 0, value: []});
523
+ sendResponseToParsedRequest({status: 0, value: []});
510
524
  break;
511
525
  }
512
526
  // Falling through, as if we do have a page, we want to treat this like a
@@ -515,7 +529,7 @@ function parseRequest(request) {
515
529
  case "deleteCookie":
516
530
  if (hasNoPage()) {
517
531
  console.log("Not got a page, but asked to delete cookies, so returning ok");
518
- sendResponseToParsedRequest({statusCode: 0});
532
+ sendResponseToParsedRequest({status: 0});
519
533
  break;
520
534
  }
521
535
  // Falling through, as if we do have a page, we want to treat this like a
@@ -523,7 +537,7 @@ function parseRequest(request) {
523
537
  case "executeScript":
524
538
  if (hasNoPage()) {
525
539
  console.log("Not got a page, but asked to execute script, so sending error 17");
526
- sendResponseToParsedRequest({statusCode: 17, value: {message: 'Was not on a page, so could not execute javascript'}});
540
+ sendResponseToParsedRequest({status: 17, value: {message: 'Was not on a page, so could not execute javascript'}});
527
541
  break;
528
542
  }
529
543
  // Falling through, as if we do have a page, we want to treat this like a
@@ -546,11 +560,11 @@ function getScreenshot() {
546
560
  function getScreenshotResult(snapshotDataUrl) {
547
561
  var index = snapshotDataUrl.indexOf('base64,');
548
562
  if (index == -1) {
549
- sendResponseToParsedRequest({statusCode: 99}, false);
563
+ sendResponseToParsedRequest({status: 99}, false);
550
564
  return;
551
565
  }
552
566
  var base64 = snapshotDataUrl.substring(index + 'base64,'.length);
553
- sendResponseToParsedRequest({statusCode: 0, value: base64}, false);
567
+ sendResponseToParsedRequest({status: 0, value: base64}, false);
554
568
  }
555
569
 
556
570
  function sendMessageOnActivePortAndAlsoKeepTrackOfIt(message) {
@@ -582,14 +596,12 @@ function parsePortMessage(message) {
582
596
  console.log("Got invalid response from the content script.");
583
597
  return;
584
598
  }
585
- var toSend = {statusCode: 12};
599
+ var toSend = {status: 12};
586
600
  ChromeDriver.lastRequestToBeSentWhichHasntBeenAnsweredYet = null;
587
601
  switch (message.response.value.statusCode) {
588
602
  // Error codes are loosely based on native exception codes, see
589
603
  // common/src/cpp/webdriver-interactions/errorcodes.h
590
604
  case 0:
591
- case 2: //org.openqa.selenium.WebDriverException [Cookies]
592
- case 3: //org.openqa.selenium.NoSuchWindowException
593
605
  case 7: //org.openqa.selenium.NoSuchElementException
594
606
  case 8: //org.openqa.selenium.NoSuchFrameException
595
607
  case 9: //java.lang.UnsupportedOperationException [Unknown command]
@@ -599,8 +611,11 @@ function parsePortMessage(message) {
599
611
  case 13: //org.openqa.selenium.WebDriverException [Unhandled error]
600
612
  case 17: //org.openqa.selenium.WebDriverException [Bad javascript]
601
613
  case 19: //org.openqa.selenium.XPathLookupException
614
+ case 23: //org.openqa.selenium.NoSuchWindowException
615
+ case 24: //org.openqa.selenium.InvalidCookieDomainException
616
+ case 25: //org.openqa.selenium.UnableToSetCookieException
602
617
  case 99: //org.openqa.selenium.WebDriverException [Native event]
603
- toSend = {statusCode: message.response.value.statusCode, value: null};
618
+ toSend = {status: message.response.value.statusCode, value: null};
604
619
  if (message.response.value !== undefined && message.response.value !== null &&
605
620
  message.response.value.value !== undefined) {
606
621
  toSend.value = message.response.value.value;
@@ -613,16 +628,16 @@ function parsePortMessage(message) {
613
628
  case "clickElement":
614
629
  try {
615
630
  if (document.embeds[0].clickAt(message.response.value.x, message.response.value.y)) {
616
- sendResponseToParsedRequest({statusCode: 0}, true);
631
+ sendResponseToParsedRequest({status: 0}, true);
617
632
  } else {
618
- sendResponseToParsedRequest({statusCode: 99}, true);
633
+ sendResponseToParsedRequest({status: 99}, true);
619
634
  }
620
635
  } catch(e) {
621
636
  console.log("Error natively clicking. Trying non-native.");
622
637
  ChromeDriver.isBlockedWaitingForResponse = false;
623
638
  parseRequest({
624
639
  request: 'nonNativeClickElement',
625
- elementId: message.response.value.elementId
640
+ id: message.response.value.id
626
641
  });
627
642
  }
628
643
  break;
@@ -630,27 +645,27 @@ function parsePortMessage(message) {
630
645
  try {
631
646
  var points = message.response.value;
632
647
  if (document.embeds[0].mouseMoveTo(15, points.oldX, points.oldY, points.newX, points.newY)) {
633
- sendResponseToParsedRequest({statusCode: 0}, true);
648
+ sendResponseToParsedRequest({status: 0}, true);
634
649
  } else {
635
- sendResponseToParsedRequest({statusCode: 99}, true);
650
+ sendResponseToParsedRequest({status: 99}, true);
636
651
  }
637
652
  } catch(e) {
638
- sendResponseToParsedRequest({statusCode: 99}, true);
653
+ sendResponseToParsedRequest({status: 99}, true);
639
654
  }
640
655
  break;
641
656
  case "sendKeysToElement":
642
657
  try {
643
658
  if (document.embeds[0].sendKeys(message.response.value.keys)) {
644
- sendResponseToParsedRequest({statusCode: 0}, true);
659
+ sendResponseToParsedRequest({status: 0}, true);
645
660
  } else {
646
- sendResponseToParsedRequest({statusCode: 99}, true);
661
+ sendResponseToParsedRequest({status: 99}, true);
647
662
  }
648
663
  } catch(e) {
649
664
  console.log("Error natively sending keys. Trying non-native.");
650
665
  ChromeDriver.isBlockedWaitingForResponse = false;
651
666
  parseRequest({
652
667
  request: 'sendElementNonNativeKeys',
653
- elementId: message.response.value.elementId,
668
+ id: message.response.value.id,
654
669
  keys: message.response.value.keys
655
670
  });
656
671
  }
@@ -733,7 +748,7 @@ function getWindowHandles() {
733
748
  for (var tab in ChromeDriver.tabs) {
734
749
  windowHandles.push(ChromeDriver.tabs[tab].windowName);
735
750
  }
736
- return {statusCode: 0, value: windowHandles}
751
+ return {status: 0, value: windowHandles}
737
752
  }
738
753
 
739
754
  function resetActiveTabDetails() {
@@ -761,17 +776,17 @@ function switchToDefaultContent() {
761
776
  if (ChromeDriver.tabs[tab].tabId == ChromeDriver.activeTabId) {
762
777
  if (ChromeDriver.tabs[tab].isFrameset) {
763
778
  ChromeDriver.isBlockedWaitingForResponse = false;
764
- parseRequest({request: 'switchToFrameByIndex', index: 0});
779
+ parseRequest({request: 'switchToFrame', id: 0});
765
780
  } else {
766
781
  ChromeDriver.activePort = ChromeDriver.tabs[tab].mainPort;
767
- sendResponseToParsedRequest({statusCode: 0}, false);
782
+ sendResponseToParsedRequest({status: 0}, false);
768
783
  }
769
784
  return;
770
785
  }
771
786
  }
772
787
  }
773
788
 
774
- function switchToFrame(name, index) {
789
+ function switchToFrame(id) {
775
790
  ChromeDriver.hasHwnd = false;
776
791
  for (var tab in ChromeDriver.tabs) {
777
792
  if (ChromeDriver.tabs[tab].tabId == ChromeDriver.activeTabId) {
@@ -779,13 +794,13 @@ function switchToFrame(name, index) {
779
794
  break;
780
795
  }
781
796
  }
782
- if (name !== undefined && name !== null) {
783
- switchToFrameByName(name);
784
- } else if (index !== undefined && index !== null) {
785
- getFrameNameFromIndex(index);
797
+ if (typeof id == 'string') {
798
+ switchToFrameByName(id);
799
+ } else if (typeof id == 'number') {
800
+ getFrameNameFromIndex(id);
786
801
  } else {
787
802
  sendResponseToParsedRequest({
788
- statusCode: 9,
803
+ status: 9,
789
804
  value: {
790
805
  message: "Switching frames other than by name or id is unsupported"
791
806
  }
@@ -806,7 +821,7 @@ function switchToFrameByName(name) {
806
821
  ChromeDriver.activePort =
807
822
  ChromeDriver.tabs[tab].frames[frame].framePort;
808
823
  ChromeDriver.restOfCurrentFramePath = [];
809
- sendResponseToParsedRequest({statusCode: 0}, false);
824
+ sendResponseToParsedRequest({status: 0}, false);
810
825
  return;
811
826
  }
812
827
  }
@@ -819,7 +834,7 @@ function switchToFrameByName(name) {
819
834
  names.shift();
820
835
  ChromeDriver.restOfCurrentFramePath = names;
821
836
  if (names.length == 0) {
822
- sendResponseToParsedRequest({statusCode: 0}, false);
837
+ sendResponseToParsedRequest({status: 0}, false);
823
838
  return;
824
839
  } else {
825
840
  switchToFrameByName(names.join("."));
@@ -930,7 +945,7 @@ function getUrlCallback(tab) {
930
945
  if (ChromeDriver.isGettingUrlButOnlyChangingByFragment) {
931
946
  ChromeDriver.urlBeingLoaded = null;
932
947
  resetCurrentlyWaitingOnContentScriptTime();
933
- sendResponseToParsedRequest({statusCode: 0}, false);
948
+ sendResponseToParsedRequest({status: 0}, false);
934
949
  ChromeDriver.isGettingUrlButOnlyChangingByFragment = false;
935
950
  }
936
951
  }
@@ -947,7 +962,7 @@ function sendEmptyResponseWhenTabIsLoaded(tab) {
947
962
  } else {
948
963
  if (!ChromeDriver.hasSentResponseToThisPageLoading) {
949
964
  ChromeDriver.urlBeingLoaded = null;
950
- sendResponseToParsedRequest({statusCode: 0}, false);
965
+ sendResponseToParsedRequest({status: 0}, false);
951
966
  }
952
967
  }
953
968
  } else {
@@ -972,11 +987,11 @@ function setActivePortByWindowName(handle) {
972
987
  ChromeDriver.activePort = ChromeDriver.tabs[tab].mainPort;
973
988
  chrome.tabs.get(ChromeDriver.tabs[tab].tabId, setActiveTabDetails);
974
989
  chrome.tabs.update(ChromeDriver.tabs[tab].tabId, {selected: true});
975
- sendResponseToParsedRequest({statusCode: 0}, false);
990
+ sendResponseToParsedRequest({status: 0}, false);
976
991
  return;
977
992
  }
978
993
  }
979
- sendResponseToParsedRequest({statusCode: 3, value: {message: 'Could not find window to switch to by handle: ' + handle}}, false);
994
+ sendResponseToParsedRequest({status: 23, value: {message: 'Could not find window to switch to by handle: ' + handle}}, false);
980
995
  }
981
996
 
982
997
 
@@ -990,6 +1005,7 @@ function hasNoPage() {
990
1005
  }
991
1006
 
992
1007
  function resetCurrentlyWaitingOnContentScriptTime() {
1008
+ console.log('resetting current content script wait time');
993
1009
  ChromeDriver.currentlyWaitingUntilGiveUpOnContentScriptLoading =
994
1010
  ChromeDriver.timeoutUntilGiveUpOnContentScriptLoading;
995
1011
  }
@@ -51,10 +51,10 @@ function parsePortMessage(message) {
51
51
  console.log("Received request: " + JSON.stringify(message) + " (" + window.name + ")");
52
52
  //wait indicates whether this is a potentially page-changing change (see background.js's sendResponseByXHR)
53
53
  var response = {response: message.request.request, value: null, wait: true};
54
- if (message.request.elementId !== undefined && message.request.elementId != null) {
55
- //If it seems an elementId has been passed, try to resolve that to an element
54
+ if (message.request.id !== undefined && message.request.id != null) {
55
+ //If it seems an id has been passed, try to resolve that to an element
56
56
  try {
57
- var element = internalGetElement(message.request.elementId);
57
+ var element = internalGetElement(message.request.id);
58
58
  } catch(e) {
59
59
  response.value = e;
60
60
  ChromeDriverContentScript.port.postMessage({response: response, sequenceNumber: message.sequenceNumber});
@@ -71,7 +71,7 @@ function parsePortMessage(message) {
71
71
  response.value = clearElement(element);
72
72
  break;
73
73
  case "clickElement":
74
- response.value = clickElement(element, message.request.elementId);
74
+ response.value = clickElement(element, message.request.id);
75
75
  break;
76
76
  case "nonNativeClickElement":
77
77
  //TODO(danielwh): Focus/blur events for non-native clicking
@@ -87,7 +87,9 @@ function parsePortMessage(message) {
87
87
 
88
88
  if (element.click) {
89
89
  console.log("click");
90
- execute("try { arguments[0].click(); } catch(e){}", {type: "ELEMENT", value: addElementToInternalArray(element)});
90
+ execute("try { arguments[0].click(); } catch(e){}", [{
91
+ type: "ELEMENT", value: addElementToInternalArray(element)
92
+ }]);
91
93
  }
92
94
  response.value = {statusCode: 0};
93
95
  break;
@@ -128,11 +130,11 @@ function parsePortMessage(message) {
128
130
  response.wait = false;
129
131
  break;
130
132
  case "getElementAttribute":
131
- response.value = getElementAttribute(element, message.request.attribute);
133
+ response.value = getElementAttribute(element, message.request.name);
132
134
  response.wait = false;
133
135
  break;
134
136
  case "getElementValueOfCssProperty":
135
- response.value = {statusCode: 0, value: getStyle(element, message.request.css)};
137
+ response.value = {statusCode: 0, value: getStyle(element, message.request.propertyName)};
136
138
  response.wait = false;
137
139
  break;
138
140
  case "getElementLocation":
@@ -186,7 +188,7 @@ function parsePortMessage(message) {
186
188
  response.value = {statusCode: 0};
187
189
  break;
188
190
  case "hoverOverElement":
189
- response.value = hoverElement(element, message.request.elementId);
191
+ response.value = hoverElement(element, message.request.id);
190
192
  break;
191
193
  case "injectEmbed":
192
194
  injectEmbed();
@@ -208,7 +210,12 @@ function parsePortMessage(message) {
208
210
  response.value = {statusCode: 0};
209
211
  break;
210
212
  case "sendKeysToElement":
211
- response.value = sendElementKeys(element, message.request.keys, message.request.elementId);
213
+ if (typeof message.request.value.splice == 'function' &&
214
+ typeof message.request.value.join == 'function') {
215
+ // Looks like we were given an array of strings. Join them together.
216
+ message.request.value = message.request.value.join('');
217
+ }
218
+ response.value = sendElementKeys(element, message.request.value, message.request.id);
212
219
  response.wait = false;
213
220
  break;
214
221
  case "sendElementNonNativeKeys":
@@ -219,7 +226,7 @@ function parsePortMessage(message) {
219
226
  response.value = selectElement(element);
220
227
  break;
221
228
  case "getActiveElement":
222
- response.value = {statusCode: 0, value: [addElementToInternalArray(ChromeDriverContentScript.currentDocument.activeElement).toString()]};
229
+ response.value = {statusCode: 0, value: {'ELEMENT':addElementToInternalArray(ChromeDriverContentScript.currentDocument.activeElement).toString()}};
223
230
  response.wait = false;
224
231
  break;
225
232
  case "switchToNamedIFrameIfOneExists":
@@ -284,7 +291,7 @@ function deleteCookie(cookieName) {
284
291
  var fullpath = cookieDocument.location.pathname;
285
292
  }
286
293
  var hostParts = cookieDocument.location.hostname.split(".");
287
-
294
+
288
295
  fullpath = fullpath.split('/');
289
296
  fullpath.pop(); //Get rid of the file
290
297
  //TODO(danielwh): Tidy up these loops and this repeated code
@@ -297,17 +304,17 @@ function deleteCookie(cookieName) {
297
304
  cookieDocument.cookie = cookieName + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/' + path;
298
305
  //Delete cookie without trailing /
299
306
  cookieDocument.cookie = cookieName + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/' + path.substring(0, path.length - 1);
300
-
307
+
301
308
  var domain = "";
302
309
  for (var i = hostParts.length - 1; i >= 0; --i) {
303
310
  domain = "." + hostParts[i] + domain;
304
311
  //Delete cookie with trailing /
305
312
  cookieDocument.cookie = cookieName + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/' + path + ";domain=" + domain;
306
-
313
+
307
314
  cookieDocument.cookie = cookieName + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/' + path + ";domain=" + domain;
308
315
  //Delete cookie without trailing /
309
316
  cookieDocument.cookie = cookieName + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/' + path.substring(0, path.length - 1) + ";domain=" + domain;
310
-
317
+
311
318
  cookieDocument.cookie = cookieName + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/' + path.substring(0, path.length - 1) + ";domain=" + domain.substring(1);
312
319
  }
313
320
  }
@@ -392,15 +399,15 @@ function setCookie(cookie) {
392
399
  var currLocation = ChromeDriverContentScript.currentDocument.location;
393
400
  var currDomain = currLocation.host;
394
401
  }
395
-
402
+
396
403
  if (currLocation.port != 80) { currDomain += ":" + currLocation.port; }
397
404
  if (cookie.domain != null && cookie.domain !== undefined &&
398
405
  currDomain.indexOf(cookie.domain) == -1) {
399
406
  // Not quite right, but close enough. (See r783)
400
- return {statusCode: 2, value: {
407
+ return {statusCode: 24, value: {
401
408
  message: "You may only set cookies for the current domain"}};
402
409
  } else if (guessPageType() != "html") {
403
- return {statusCode: 2, value: {
410
+ return {statusCode: 25, value: {
404
411
  message: "You may only set cookies on html documents"}};
405
412
  } else {
406
413
  cookieDocument.cookie = cookie.name + '=' + escape(cookie.value) +
@@ -486,12 +493,15 @@ function getElement(plural, lookupBy, lookupValue, id) {
486
493
  message: "Unable to find element with " + lookupBy + " " + lookupValue}};
487
494
  }
488
495
  } else {
489
- var elementsToReturnArray = [];
496
+ var toReturn;
490
497
  if (plural) {
498
+ toReturn = [];
491
499
  //Add all found elements to the page's elements, and push each to the array to return
492
500
  var addedElements = addElementsToInternalArray(elements);
493
501
  for (var addedElement in addedElements) {
494
- elementsToReturnArray.push(addedElements[addedElement].toString());
502
+ toReturn.push({
503
+ 'ELEMENT': addedElements[addedElement].toString()
504
+ });
495
505
  }
496
506
  } else {
497
507
  if (!elements[0]) {
@@ -499,9 +509,11 @@ function getElement(plural, lookupBy, lookupValue, id) {
499
509
  message: "Unable to find element with " + lookupBy + " " + lookupValue}};
500
510
  }
501
511
  //Add the first found elements to the page's elements, and push it to the array to return
502
- elementsToReturnArray.push(addElementToInternalArray(elements[0]).toString());
512
+ toReturn = {
513
+ 'ELEMENT': addElementToInternalArray(elements[0]).toString()
514
+ };
503
515
  }
504
- return {statusCode: 0, value: elementsToReturnArray};
516
+ return {statusCode: 0, value: toReturn};
505
517
  }
506
518
  }
507
519
 
@@ -565,7 +577,7 @@ function clickElement(element, elementId) {
565
577
  element.scrollIntoView(true);
566
578
  var size = getOffsetSizeFromSubElements(element);
567
579
  var coords = getElementCoords(element);
568
- return {statusCode: "no-op", elementId: elementId,
580
+ return {statusCode: "no-op", id: elementId,
569
581
  x: parseInt(coords[0] - ChromeDriverContentScript.currentDocument.body.scrollLeft + (size.width ? size.width / 2 : 0)),
570
582
  y: parseInt(coords[1] - ChromeDriverContentScript.currentDocument.body.scrollTop + (size.height ? size.height / 2 : 0))};
571
583
  }
@@ -584,7 +596,7 @@ function hoverElement(element, elementId) {
584
596
  var size = getOffsetSizeFromSubElements(element)
585
597
  var coords = getElementCoords(element);
586
598
  console.log("element.clientX: " + element.clientX);
587
- return {statusCode: "no-op", elementId: elementId,
599
+ return {statusCode: "no-op", id: elementId,
588
600
  oldX: 0,
589
601
  oldY: 0,
590
602
  newX: coords[0] - ChromeDriverContentScript.currentDocument.body.scrollLeft + (size.width ? size.width / 2 : 0),
@@ -722,7 +734,7 @@ function sendElementKeys(element, keys, elementId) {
722
734
  Utils.fireHtmlEventAndConditionallyPerformAction(oldFocusedElement, "blur", function() {oldFocusedElement.blur();});
723
735
  Utils.fireHtmlEventAndConditionallyPerformAction(element, "focus", function() {element.focus();});
724
736
  }
725
- return {statusCode: "no-op", keys: keys, elementId: elementId};
737
+ return {statusCode: "no-op", keys: keys, id: elementId};
726
738
  }
727
739
 
728
740
  /**
@@ -791,7 +803,7 @@ function toggleElement(element) {
791
803
  return e;
792
804
  }
793
805
  console.log("New value: " + newValue);
794
-
806
+
795
807
  if (changed) {
796
808
  //TODO: Work out a way of firing events,
797
809
  //now that synthesising them gives appendMessage errors
@@ -830,38 +842,60 @@ function sniffForMetaRedirects() {
830
842
  return {statusCode: "no-op", value: false};
831
843
  }
832
844
 
833
- function parseWrappedArguments(argument) {
834
- //Parse the arguments into actual values (which are wrapped up in JSON)
835
- if (argument.length !== undefined) {
836
- var array = [];
837
- for (var i = 0; i < argument.length; ++i) {
838
- array.push(parseWrappedArguments(argument[i]));
839
- }
840
- return {success: true, value: array};
841
- }
842
- switch (argument.type) {
843
- case "ELEMENT":
844
- //Wrap up as a special object with the element's canonical xpath, which the page can work out
845
- var element_id = argument.value;
846
- var element = null;
847
- try {
848
- element = internalGetElement(element_id);
849
- } catch (e) {
850
- return {success: false, value: {response: "execute", value:
851
- {statusCode: 10,
852
- message: "Tried use obsolete element as argument when executing javascript."}}};
845
+ function parseWrappedArguments(wrappedArguments) {
846
+ var converted = [];
847
+ while (wrappedArguments && wrappedArguments.length > 0) {
848
+ var t = wrappedArguments.shift();
849
+ switch (typeof t) {
850
+ case 'number':
851
+ case 'string':
852
+ case 'boolean':
853
+ converted.push(t);
854
+ break;
855
+
856
+ case 'object':
857
+ if (t == null) {
858
+ converted.push(null);
859
+
860
+ } else if (typeof t.length === 'number' &&
861
+ !(t.propertyIsEnumerable('length'))) {
862
+ converted.push(parseWrappedArguments(t));
863
+
864
+ } else if (typeof t['ELEMENT'] === 'string' ||
865
+ typeof t['ELEMENT'] === 'number') {
866
+ //Wrap up as a special object with the element's canonical xpath,
867
+ // which the page can work out
868
+ var element_id = t['ELEMENT'];
869
+ var element = null;
870
+ try {
871
+ element = internalGetElement(element_id);
872
+ } catch (e) {
873
+ throw {
874
+ statusCode: 10,
875
+ message:'Tried to use obsolete element as a JavaScript argument.'
876
+ };
877
+ }
878
+ converted.push({
879
+ webdriverElementXPath: getXPathOfElement(element)
880
+ });
881
+
882
+ } else {
883
+ var convertedObj = {};
884
+ for (var prop in t) {
885
+ convertedObj[prop] = parseWrappedArguments(t[prop]);
886
+ }
887
+ converted.push(convertedObj);
888
+ }
889
+ break;
890
+
891
+ default:
892
+ throw {
893
+ statusCode: 17,
894
+ message: 'Bad javascript argument: ' + (typeof t)
895
+ };
853
896
  }
854
- return {success: true, value: {webdriverElementXPath: getXPathOfElement(element)}};
855
- break;
856
- //Intentional falling through because Javascript will parse things properly
857
- case "STRING":
858
- case "BOOLEAN":
859
- case "NUMBER":
860
- return {success: true, value: argument.value};
861
- break;
862
897
  }
863
- return {success: false, value: {statusCode: 17,
864
- message: "Bad argument to javascript."}}
898
+ return converted;
865
899
  }
866
900
 
867
901
  /**
@@ -869,70 +903,137 @@ function parseWrappedArguments(argument) {
869
903
  * Returns by callback to returnFromJavascriptInPage.
870
904
  * Yes, this is *horribly* hacky.
871
905
  * We can't share objects between content script and page, so have to wrap up arguments as JSON
872
- * @param script script to execute as a string
873
- * @param passedArgs array of arguments to pass to the script
906
+ * @param {string} script The javascript snippet to execute in the current page.
907
+ * @param {Array.<*>} passedArgs An array of JSON arguments to pass to the
908
+ * injected script. DOMElements should be specified as JSON objects of the
909
+ * form {ELEMENT: string}.
874
910
  * @param callback function to call when the result is returned. Passed a DOMAttrModified event which should be parsed as returnFromJavascriptInPage
875
911
  * TODO: Make the callback be passed the parsed result.
876
912
  */
877
913
  function execute_(script, passedArgs, callback) {
878
914
  console.log("executing " + script + ", args: " + JSON.stringify(passedArgs));
879
915
  var func = "function(){" + script + "}";
880
- var args = [];
881
- for (var i = 0; i < passedArgs.length; ++i) {
882
- console.log("Parsing: " + JSON.stringify(passedArgs[i]));
883
- var value = parseWrappedArguments(passedArgs[i]);
884
- if (value.success) {
885
- args.push(value.value);
886
- } else {
887
- ChromeDriverContentScript.port.postMessage({response: value.value, sequenceNumber: ChromeDriverContentScript.currentSequenceNumber});
888
- return;
889
- }
916
+ var args;
917
+ try {
918
+ args = parseWrappedArguments(passedArgs);
919
+ } catch (ex) {
920
+ ChromeDriverContentScript.port.postMessage({
921
+ response: {
922
+ statusCode: (ex.statusCode || 17),
923
+ message: (ex.message || ex.toString())
924
+ },
925
+ sequenceNumber: ChromeDriverContentScript.currentSequenceNumber
926
+ });
927
+ return;
890
928
  }
929
+
891
930
  //Add a script tag to the page, containing the script we wish to execute
892
931
  var scriptTag = ChromeDriverContentScript.currentDocument.createElement('script');
893
932
  var argsString = JSON.stringify(args).replace(/"/g, "\\\"");
894
- scriptTag.innerText = 'var e = document.createEvent("MutationEvent");' +
895
- //Dump our arguments in an array
896
- 'var args = JSON.parse("' + argsString + '");' +
897
- 'var element = null;' +
898
- 'for (var i = 0; i < args.length; ++i) {' +
899
- 'if (args[i] && typeof(args[i]) == "object" && args[i].webdriverElementXPath) {' +
900
- //If this is an element (because it has the proper xpath), turn it into an actual element object
901
- 'args[i] = document.evaluate(args[i].webdriverElementXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;' +
902
- '}' +
903
- '}' +
904
- 'try {' +
905
- 'var val = eval(' + func + ').apply(window, args);' +
906
- 'if (typeof(val) == "string") { val = JSON.stringify(val); }' +
907
- //TODO(danielwh): Deal with the undefined != null case better
908
- 'else if (val === undefined) { val = null; }' +
909
- 'else if (typeof(val) == "object" && val && val.nodeType == 1) {' +
910
- //If we're returning an element, turn it into a special xpath-containing object
911
- 'var path = "";' +
912
- 'for (; val && val.nodeType == 1; val = val.parentNode) {' +
913
- 'var index = 1;' +
914
- 'for (var sibling = val.previousSibling; sibling; sibling = sibling.previousSibling) {' +
915
- 'if (sibling.nodeType == 1 && sibling.tagName && sibling.tagName == val.tagName) {' +
916
- 'index++;' +
917
- '}' +
918
- '}' +
919
- 'path = "/" + val.tagName + "[" + index + "]" + path;' +
920
- '}' +
921
- 'val = JSON.stringify({webdriverElementXPath: path});' +
922
- '} else {' +
923
- 'val = JSON.stringify(val);' +
924
- '}' +
925
- //Fire mutation event with newValue set to the JSON of our return value
926
- 'e.initMutationEvent("DOMAttrModified", true, false, null, null, "{value: " + val + "}", null, 0);' +
927
- '} catch (exn) {' +
928
- //Fire mutation event with prevValue set to EXCEPTION to indicate an error in the script
929
- 'e.initMutationEvent("DOMAttrModified", true, false, null, "EXCEPTION", null, null, 0);' +
930
- '}' +
931
- 'document.getElementsByTagName("script")[document.getElementsByTagName("script").length - 1].dispatchEvent(e);' +
932
- 'document.getElementsByTagName("html")[0].removeChild(document.getElementsByTagName("script")[document.getElementsByTagName("script").length - 1]);';
933
+
934
+ // We use the fact that Function.prototype.toString() will decompile this to
935
+ // its source code so we can inject it into the page in a SCRIPT tag.
936
+ function executeInjectedScript(fn, argsAsString) {
937
+ var e = document.createEvent("MutationEvent");
938
+ var args = JSON.parse(argsAsString);
939
+ var element = null;
940
+ for (var i = 0; i < args.length; i++) {
941
+ if (args[i] && typeof args[i] == 'object' &&
942
+ args[i].webdriverElementXPath) {
943
+ //If this is an element (because it has the proper xpath), turn it into
944
+ //an actual element object
945
+ args[i] = document.evaluate(args[i].webdriverElementXPath, document,
946
+ null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
947
+ }
948
+ }
949
+ try {
950
+ var val = fn.apply(window, args);
951
+
952
+ // prepares the injected script result to be converted to json to be sent
953
+ // back to the content script.
954
+ function convertResultToJson(result) {
955
+ switch (typeof result) {
956
+ case 'string':
957
+ case 'number':
958
+ case 'boolean':
959
+ return result;
960
+ case 'undefined':
961
+ return null;
962
+ case 'object':
963
+ if (result == null) {
964
+ return result;
965
+ }
966
+ // Result was an array.
967
+ if (typeof result.length === 'number' &&
968
+ !(result.propertyIsEnumerable('length'))) {
969
+ var converted = [];
970
+ for (var i = 0; i < result.length; i++) {
971
+ converted.push(convertResultToJson(result[i]));
972
+ }
973
+ return converted;
974
+ }
975
+ // Result is a DOMNode; make sure it's a DOMElement
976
+ if (typeof result.nodeType == 'number') {
977
+ if (result.nodeType != 1) {
978
+ // Non-valid JSON value; we'll fail over when trying to
979
+ // stringify this, so fail early.
980
+ throw Error('Invalid script return type: result.nodeType == ' +
981
+ result.nodeType);
982
+ }
983
+ var path = '';
984
+ for (; result && result.nodeType == 1;
985
+ result = result.parentNode) {
986
+ var index = 1;
987
+ for (var sibling = result.previousSibling; sibling;
988
+ sibling = sibling.previousSibling) {
989
+ if (sibling.nodeType == 1 && sibling.tagName &&
990
+ sibling.tagName == result.tagName) {
991
+ index++;
992
+ }
993
+ }
994
+ path = '/' + result.tagName + '[' + index + ']' + path;
995
+ }
996
+ return {webdriverElementXPath: path};
997
+ }
998
+ // Result is an object; convert each property.
999
+ var converted = {};
1000
+ for (var prop in result) {
1001
+ converted[prop] = convertResultToJson(result[prop]);
1002
+ }
1003
+ return converted;
1004
+
1005
+ case 'function':
1006
+ default:
1007
+ throw Error('Invalid script return type: ' + (typeof result));
1008
+ } // switch
1009
+ }
1010
+
1011
+ val = JSON.stringify({
1012
+ value: convertResultToJson(val)
1013
+ });
1014
+ console.info('returning from injected script: ' + val);
1015
+ //Fire mutation event with newValue set to the JSON of our return value
1016
+ e.initMutationEvent(
1017
+ "DOMAttrModified", true, false, null, null, val, null, 0);
1018
+ } catch (ex) {
1019
+ //Fire mutation event with prevValue set to EXCEPTION to indicate an error
1020
+ //in the script
1021
+ console.error('injected script failed: ' + ex.toString());
1022
+ e.initMutationEvent("DOMAttrModified", true, false, null, "EXCEPTION",
1023
+ null, null, 0);
1024
+ }
1025
+ var scriptTags = document.getElementsByTagName("script");
1026
+ var scriptTag = scriptTags[scriptTags.length - 1];
1027
+ scriptTag.dispatchEvent(e);
1028
+ document.documentElement.removeChild(scriptTag);
1029
+ }
1030
+
1031
+ scriptTag.innerHTML =
1032
+ '(' + executeInjectedScript + ')(' + func + ', "' + argsString + '");';
1033
+
933
1034
  scriptTag.addEventListener('DOMAttrModified', callback, false);
934
- console.log("Injecting script element");
935
- ChromeDriverContentScript.currentDocument.getElementsByTagName("html")[0].appendChild(scriptTag);
1035
+ ChromeDriverContentScript.currentDocument.documentElement.
1036
+ appendChild(scriptTag);
936
1037
  }
937
1038
 
938
1039
  function execute(script, passedArgs) {
@@ -940,29 +1041,49 @@ function execute(script, passedArgs) {
940
1041
  }
941
1042
 
942
1043
  function parseReturnValueFromScript(result) {
943
- console.log("Parsing: " + JSON.stringify(result));
944
- var value = {"type":"NULL"};
945
- if (result !== undefined && result != null && typeof(result) == "object") {
946
- if (result.webdriverElementXPath) {
947
- //If we're returning an element, turn it into an actual element object
948
- value = {value: addElementToInternalArray(getElementsByXPath(result.webdriverElementXPath)[0]).toString(), type:"ELEMENT"};
949
- } else if (result.length !== undefined) {
950
- value = [];
951
- for (var i = 0; i < result.length; ++i) {
952
- value.push(parseReturnValueFromScript(result[i]));
1044
+ switch (typeof result) {
1045
+ case 'string':
1046
+ case 'number':
1047
+ case 'boolean':
1048
+ return result;
1049
+
1050
+ case 'object':
1051
+ if (result == null) {
1052
+ return result;
953
1053
  }
954
- }
955
- } else if (result !== undefined && result != null) {
956
- switch (typeof(result)) {
957
- //Intentional falling through because we treat all "VALUE"s the same
958
- case "string":
959
- case "number":
960
- case "boolean":
961
- value = {value: result, type: "VALUE"};
962
- break;
963
- }
1054
+
1055
+ // Received an array, parse each element.
1056
+ if (typeof result.length === 'number' &&
1057
+ !(result.propertyIsEnumerable('length'))) {
1058
+ var converted = [];
1059
+ for (var i = 0; i < result.length; i++) {
1060
+ converted.push(parseReturnValueFromScript(result[i]));
1061
+ }
1062
+ return converted;
1063
+ }
1064
+
1065
+ // Script returned an element; return it's cached ID.
1066
+ if (typeof result.webdriverElementXPath === 'string') {
1067
+ //If we're returning an element, turn it into an actual element object
1068
+ var element = getElementsByXPath(result.webdriverElementXPath)[0];
1069
+ return {'ELEMENT': addElementToInternalArray(element).toString()};
1070
+ }
1071
+
1072
+ // We were given a plain-old JSON object. Parse each property.
1073
+ var convertedObj = {};
1074
+ for (var prop in result) {
1075
+ convertedObj[prop] = parseReturnValueFromScript(result[prop]);
1076
+ }
1077
+ return convertedObj;
1078
+
1079
+ // The script we inject to the page should never give us a result of type
1080
+ // 'function' or 'undefined', so we do not need to check for those, but
1081
+ // just go ahead and return null for completeness.
1082
+ case 'function':
1083
+ case 'undefined':
1084
+ default:
1085
+ return null;
964
1086
  }
965
- return value;
966
1087
  }
967
1088
 
968
1089
  /**
@@ -972,11 +1093,11 @@ function returnFromJavascriptInPage(e) {
972
1093
  if (e.prevValue == "EXCEPTION") {
973
1094
  ChromeDriverContentScript.port.postMessage({sequenceNumber: ChromeDriverContentScript.currentSequenceNumber,
974
1095
  response: {response: "execute", value: {statusCode: 17,
975
- message: "Tried to execute bad javascript."}}});
1096
+ value: {message: "Tried to execute bad javascript."}}}});
976
1097
  return;
977
1098
  }
978
1099
  console.log("Got result");
979
- console.log("Result was: " + e.newValue.value);
1100
+ console.log("Result was: " + e.newValue);
980
1101
  var result = JSON.parse(e.newValue).value;
981
1102
  var value = parseReturnValueFromScript(result);
982
1103
  console.log("Return value: " + JSON.stringify(value));
@@ -1013,7 +1134,7 @@ function returnFromGetFrameNameFromIndexJavascriptInPage(e) {
1013
1134
  if (e.prevValue == "EXCEPTION") {
1014
1135
  ChromeDriverContentScript.port.postMessage({sequenceNumber: ChromeDriverContentScript.currentSequenceNumber,
1015
1136
  response: {response: "getFrameNameFromIndex", value: {statusCode: 8,
1016
- message: "No such frame"}}});
1137
+ value: {message: "No such frame"}}}});
1017
1138
  } else {
1018
1139
  ChromeDriverContentScript.port.postMessage({sequenceNumber: ChromeDriverContentScript.currentSequenceNumber,
1019
1140
  response: {response: "getFrameNameFromIndex", value: {statusCode: "no-op",