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.
- data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
- data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
- data/chrome/src/extension/background.js +64 -48
- data/chrome/src/extension/content_script.js +253 -132
- data/chrome/src/extension/manifest-nonwin.json +1 -1
- data/chrome/src/extension/manifest-win.json +1 -1
- data/chrome/src/extension/utils.js +8 -8
- data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +9 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +38 -280
- data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +119 -117
- data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +36 -26
- data/common/src/js/abstractcommandprocessor.js +9 -11
- data/common/src/js/command.js +159 -83
- data/common/src/js/core/RemoteRunner.html +2 -2
- data/common/src/js/core/TestRunner-splash.html +3 -3
- data/common/src/js/core/TestRunner.html +5 -17
- data/common/src/js/core/scripts/htmlutils.js +4208 -2506
- data/common/src/js/core/scripts/selenium-api.js +2 -2
- data/common/src/js/core/scripts/selenium-browserbot.js +66 -58
- data/common/src/js/core/scripts/selenium-version.js +1 -1
- data/common/src/js/localcommandprocessor.js +5 -19
- data/common/src/js/testcase.js +2 -0
- data/common/src/js/webdriver.js +63 -93
- data/common/src/js/webelement.js +40 -42
- data/common/src/rb/lib/selenium/webdriver.rb +23 -14
- data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +8 -35
- data/common/src/rb/lib/selenium/webdriver/child_process.rb +2 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +1 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/string.rb +5 -0
- data/common/src/rb/lib/selenium/webdriver/driver.rb +20 -15
- data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +7 -2
- data/common/src/rb/lib/selenium/webdriver/element.rb +11 -2
- data/common/src/rb/lib/selenium/webdriver/error.rb +9 -5
- data/common/src/rb/lib/selenium/webdriver/keys.rb +1 -2
- data/common/src/rb/lib/selenium/webdriver/navigation.rb +16 -0
- data/common/src/rb/lib/selenium/webdriver/options.rb +32 -0
- data/common/src/rb/lib/selenium/webdriver/platform.rb +17 -1
- data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
- data/firefox/src/extension/components/dispatcher.js +492 -0
- data/firefox/src/extension/components/driver-component.js +4 -1
- data/firefox/src/extension/components/errorcode.js +70 -0
- data/firefox/src/extension/components/firefoxDriver.js +173 -154
- data/firefox/src/extension/components/nsCommandProcessor.js +171 -132
- data/firefox/src/extension/components/promptService.js +5 -5
- data/firefox/src/extension/components/request.js +219 -0
- data/firefox/src/extension/components/response.js +276 -0
- data/firefox/src/extension/components/session.js +281 -0
- data/firefox/src/extension/components/sessionstore.js +226 -0
- data/firefox/src/extension/components/socketListener.js +350 -100
- data/firefox/src/extension/components/utils.js +166 -98
- data/firefox/src/extension/components/webdriverserver.js +9 -5
- data/firefox/src/extension/components/wrappedElement.js +189 -166
- data/firefox/src/extension/install.rdf +1 -1
- data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +2 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +39 -33
- data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +7 -421
- data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +7 -64
- data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +2 -3
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +54 -10
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +2 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +6 -0
- data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +2 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +38 -13
- data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +9 -2
- data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +5 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +2 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +42 -38
- data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +56 -47
- data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +26 -26
- data/remote/client/src/rb/lib/selenium/webdriver/remote/patron_http_client.rb +58 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +10 -12
- data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +2 -17
- metadata +44 -23
- data/common/src/js/context.js +0 -58
- data/firefox/src/extension/components/context.js +0 -37
Binary file
|
Binary file
|
@@ -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({
|
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({
|
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({
|
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({
|
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({
|
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 "
|
453
|
-
|
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.
|
473
|
+
switchToFrame(request.id);
|
460
474
|
break;
|
461
475
|
case "switchToWindow":
|
462
476
|
ChromeDriver.hasHwnd = false;
|
463
|
-
if (request.
|
464
|
-
setActivePortByWindowName(request.
|
477
|
+
if (request.name !== undefined) {
|
478
|
+
setActivePortByWindowName(request.name);
|
465
479
|
} else {
|
466
480
|
sendResponseToParsedRequest({
|
467
|
-
|
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({
|
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({
|
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({
|
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({
|
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({
|
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({
|
563
|
+
sendResponseToParsedRequest({status: 99}, false);
|
550
564
|
return;
|
551
565
|
}
|
552
566
|
var base64 = snapshotDataUrl.substring(index + 'base64,'.length);
|
553
|
-
sendResponseToParsedRequest({
|
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 = {
|
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 = {
|
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({
|
631
|
+
sendResponseToParsedRequest({status: 0}, true);
|
617
632
|
} else {
|
618
|
-
sendResponseToParsedRequest({
|
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
|
-
|
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({
|
648
|
+
sendResponseToParsedRequest({status: 0}, true);
|
634
649
|
} else {
|
635
|
-
sendResponseToParsedRequest({
|
650
|
+
sendResponseToParsedRequest({status: 99}, true);
|
636
651
|
}
|
637
652
|
} catch(e) {
|
638
|
-
sendResponseToParsedRequest({
|
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({
|
659
|
+
sendResponseToParsedRequest({status: 0}, true);
|
645
660
|
} else {
|
646
|
-
sendResponseToParsedRequest({
|
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
|
-
|
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 {
|
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: '
|
779
|
+
parseRequest({request: 'switchToFrame', id: 0});
|
765
780
|
} else {
|
766
781
|
ChromeDriver.activePort = ChromeDriver.tabs[tab].mainPort;
|
767
|
-
sendResponseToParsedRequest({
|
782
|
+
sendResponseToParsedRequest({status: 0}, false);
|
768
783
|
}
|
769
784
|
return;
|
770
785
|
}
|
771
786
|
}
|
772
787
|
}
|
773
788
|
|
774
|
-
function switchToFrame(
|
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 (
|
783
|
-
switchToFrameByName(
|
784
|
-
} else if (
|
785
|
-
getFrameNameFromIndex(
|
797
|
+
if (typeof id == 'string') {
|
798
|
+
switchToFrameByName(id);
|
799
|
+
} else if (typeof id == 'number') {
|
800
|
+
getFrameNameFromIndex(id);
|
786
801
|
} else {
|
787
802
|
sendResponseToParsedRequest({
|
788
|
-
|
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({
|
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({
|
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({
|
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({
|
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({
|
990
|
+
sendResponseToParsedRequest({status: 0}, false);
|
976
991
|
return;
|
977
992
|
}
|
978
993
|
}
|
979
|
-
sendResponseToParsedRequest({
|
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.
|
55
|
-
//If it seems an
|
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.
|
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.
|
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){}", {
|
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.
|
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.
|
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.
|
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
|
-
|
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:
|
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:
|
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:
|
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
|
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
|
-
|
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
|
-
|
512
|
+
toReturn = {
|
513
|
+
'ELEMENT': addElementToInternalArray(elements[0]).toString()
|
514
|
+
};
|
503
515
|
}
|
504
|
-
return {statusCode: 0, value:
|
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",
|
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",
|
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,
|
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(
|
834
|
-
|
835
|
-
|
836
|
-
var
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
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
|
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
|
873
|
-
* @param passedArgs array of arguments to pass to the
|
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
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
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
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
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
|
-
|
935
|
-
|
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
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
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
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
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
|
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",
|