Open Bug 1471262 Opened 6 years ago Updated 1 year ago

WebDriver:TakeScreenshot returns empty string

Categories

(Remote Protocol :: Marionette, defect, P3)

59 Branch
defect

Tracking

(Not tracked)

People

(Reporter: aclvaz, Unassigned)

References

(Blocks 1 open bug)

Details

User Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36

Steps to reproduce:

using Selenium in C#:

return ((ITakesScreenshot)_driver).GetScreenshot();

for a WebDriver configured like this:

        private void CreateWebDriver()
        {
            FirefoxProfile customProfile = new FirefoxProfile();
            customProfile.SetPreference("dom.disable_beforeunload", true); // disable want to leave page question.
            customProfile.SetPreference("full-screen-api.approval-required", false); // disable maximize firefox question
            customProfile.SetPreference("network.http.connection-timeout", 25); // connection time-out.
            customProfile.SetPreference("dom.max_chrome_script_run_time", 0);
            customProfile.SetPreference("dom.max_script_run_time", 0);
            // for some pesky sites
            customProfile.SetPreference("browser.download.folderList", 2);
            customProfile.SetPreference("browser.download.dir", Directory.GetCurrentDirectory());
            customProfile.SetPreference("browser.helperApps.neverAsk.saveToDisk", "text/vnd.wap.wml,application/x-trash,httpd/unix-directory,application/vnd.framemaker,application/octet-stream"); // ex: dgj.com, yld.com, zpo.com?, cwb.net, kuke.com
            customProfile.SetPreference("media.volume_scale", "0.0");
            customProfile.SetPreference("dom.successive_dialog_time_limit", 1);

            FirefoxOptions fo = new FirefoxOptions();
            fo.Profile = customProfile;
            fo.SetPreference("security.sandbox.content.level", 5);
            fo.AddAdditionalCapability("acceptInsecureCerts", true, true);
            fo.AcceptInsecureCertificates = true;
            fo.Profile.AcceptUntrustedCertificates = true;
            fo.Profile.AssumeUntrustedCertificateIssuer = true;
            fo.Profile.DeleteAfterUse = true;
            fo.UnhandledPromptBehavior = UnhandledPromptBehavior.Dismiss;
            fo.LogLevel = FirefoxDriverLogLevel.Trace;
            fo.SetPreference("webdriver.log.file", "d:\\selenium\\driver.log");
            _driver = new FirefoxDriver(FirefoxDriverService.CreateDefaultService(), fo, TimeSpan.FromSeconds(60));
            _driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(40);
        }


accessing URL www.ypl.com (or www.pbo.com, or www.mjl.com, etc)

gets an empty string.

using:
* GeckoDriver Version: 0.21.0
* Platform: Windows 7 Enterprise Edition 64 bits
* Firefox: 59.0.2 (64-bit)
* Selenium: 3.12.1



Actual results:

got an empty string on Selenium where there should be a base64 encoded string with the web page image:

1530016396134   webdriver::server       DEBUG   -> POST /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/window/rect {"width":1024,"height":768}
1530016396141   webdriver::server       DEBUG   <- 200 OK {"value": {"height":768,"width":1024,"x":4,"y":4}}
1530016396142   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/window
1530016396147   webdriver::server       DEBUG   <- 200 OK {"value":"4294967297"}
1530016396626   webdriver::server       DEBUG   -> POST /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/url {"url":"http://www.ypl.com"}
1530016397592   webdriver::server       DEBUG   <- 200 OK {"value": null}
1530016398311   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/alert/text
1530016398315   webdriver::server       DEBUG   <- 404 Not Found {"value":{"error":"no such alert","message":"No modal dialog is currently open","stac
ktrace":"WebDriverError@chrome://marionette/content/error.js:178:5\nNoSuchAlertError@chrome://marionette/content/error.js:423:5\nGeckoDriver.prototype
._checkIfAlertIsPresent@chrome://marionette/content/driver.js:3197:11\nGeckoDriver.prototype.getTextFromDialog@chrome://marionette/content/driver.js:3
160:3\ndespatch@chrome://marionette/content/server.js:293:20\nexecute@chrome://marionette/content/server.js:267:11\nonPacket/<@chrome://marionette/con
tent/server.js:242:15\nonPacket@chrome://marionette/content/server.js:241:8\n_onJSONObjectReady/<@chrome://marionette/content/transport.js:500:9\n"}}
1530016399054   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/window/handles
1530016399057   webdriver::server       DEBUG   <- 200 OK {"value":["4294967297"]}
1530016399103   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/window/handles
1530016399107   webdriver::server       DEBUG   <- 200 OK {"value":["4294967297"]}
1530016399749   webdriver::server       DEBUG   -> POST /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/execute/sync {"script":"return (document.readySt
ate == 'complete' && ((window.jQuery === undefined) || jQuery.active == 0))","args":[]}
1530016399759   webdriver::server       DEBUG   <- 200 OK {"value":true}
1530016400485   webdriver::server       DEBUG   -> POST /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/elements {"using":"xpath","value":"//meta[@http-
equiv='refresh']"}
1530016400492   webdriver::server       DEBUG   <- 200 OK {"value":[]}
1530016407499   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/url
1530016407502   webdriver::server       DEBUG   <- 200 OK {"value":"http://www.ypl.com/"}
1530016407542   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/url
1530016407545   webdriver::server       DEBUG   <- 200 OK {"value":"http://www.ypl.com/"}
1530016433263   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/screenshot
1530016433275   webdriver::server       DEBUG   <- 200 OK {"value":""}
1530016433275   webdriver::server       DEBUG   -> GET /session/01e446d4-a1f6-47db-8958-bd6a9ffbbc83/url
1530016433278   webdriver::server       DEBUG   <- 200 OK {"value":"http://www.ypl.com/"}



Expected results:

should have returned a base64 encoded string with the snapshot image
Triaging this issue to testing::geeckodriver as it seems to me the correct component.
Component: Untriaged → geckodriver
Product: Firefox → Testing
This is an issue with Marionette. We will have to look into it at some point. 

Tonecas, if you want to help us investigating please let us know.
Status: UNCONFIRMED → NEW
Component: geckodriver → Marionette
Ever confirmed: true
Priority: -- → P3
From Andreas via the Github issue:

> That said, the return value from takeScreenshot is an empty string, which we would not expect for https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg. I expect there is an issue somewhere dealing with the correct document type, since the document is an XML file.
(In reply to Henrik Skupin (:whimboo) from comment #2)
> This is an issue with Marionette. We will have to look into it at some
> point. 
> 
> Tonecas, if you want to help us investigating please let us know.

Yes I can help if I can. I am not familiarized how to debug Mozilla code from another project (in my case, my own code and Selenium code). I use Visual Studio and i'm using ReSharper to help bind external code to a project, but did not get yet on how to be able to make breakpoints on Geckodriver/Marionette code. if you have any info/help page on this I surely can make a more in depth debug.
I would propose that you read through the following document first:
https://firefox-source-docs.mozilla.org/testing/marionette/marionette/NewContributors.html

Once done feel free to contact me or Andreas (ato) in the #ateam channel. We are happy to help further! Also thank you for your interest to help.
I haven’t been able to confirm yet if this is related to the GitHub
issue quoted, as that is specifically about XHTML/XML documents.
This is an HTML document which appears to exhibit the same problem.
Perhaps my initial suspicion was wrong.

In any case, I reproduced this with the Marionette client against
Nightly:

> >>> m.navigate("http://www.ypl.com")
> 1530629481160	Marionette	TRACE	0 -> [0,2,"WebDriver:Navigate",{"url":"http://www.ypl.com"}]
> 1530629481170	Marionette	DEBUG	[7] Received DOM event beforeunload for about:blank
> 1530629481473	Marionette	DEBUG	[7] Received DOM event pagehide for about:blank
> 1530629481524	Marionette	DEBUG	[7] Received DOM event DOMContentLoaded for http://www.ypl.com/
> 1530629481784	Marionette	DEBUG	[7] Received DOM event pageshow for http://www.ypl.com/
> 1530629481802	Marionette	TRACE	0 <- [1,2,null,{"value":null}]
> >>> m.screenshot()
> 1530629487629	Marionette	TRACE	0 -> [0,3,"WebDriver:TakeScreenshot",{"highlights":null,"full":true,"hash":false,"id":null,"scroll":true}]
> u''
> >>> 1530629487636	Marionette	TRACE	0 <- [1,3,null,{"value":""}]
Blocks: webdriver
Summary: Take a screenshot returns empty value on GeckoDriver/Marionette → WebDriver:TakeScreenshot returns empty string
Also happening on http://creppy.hu/.
Quoting Sule Tamas over on https://bugzilla.mozilla.org/show_bug.cgi?id=1500117:

(In reply to Sule Tamas from comment #2)
> The bug can be reproduced with the following code on a local html file:
> 
> <!DOCTYPE html>
> <html>
>     <head>
>         <style>
>             body {
>                 margin: 0
>             }
>         </style>
>     </head>
>     <body></body>
> </html>
I feel that this should be the same underlying issue as I have described on bug 1492357 comment 1.
See Also: → 1492357
I compiled a nightly from source and tracked the issue i mentioned before. I solved my problem and created a workaround.

in /mozilla-unified/testing/marionette/listener.js:
in function takeScreenshot:
if the "full" flag has true value "win.document.documentElement" is passed to the capture.element function. 

in /mozilla-unified/testing/marionette/capture.js
in function capture.element

The necessary dimensions for the rendering are queried by node.getBoundingClientRect() where node is the passed "win.document.documentElement". Of course the size object returned contains zero height.

I found out this works ok for any element, except for win.document.documentElement if the document has 0 height. 
http://creppy.hu/ and some other websites uses one absolute positioned div in the body, so the body and the documentElement has zero height.


While trying to get a correct solution, i checked the inbuilt screenshot function (right click menu: take screenshot)
in /mozilla-unified/browser/extensions/screenshots/selector/uicontrol.js

following functions are used to determine the correct size when the user selects full screen screenshot:

function getDocumentWidth() {
    return Math.max(
      document.body && document.body.clientWidth,
      document.documentElement.clientWidth,
      document.body && document.body.scrollWidth,
      document.documentElement.scrollWidth);
}
function getDocumentHeight() {
    return Math.max(
      document.body && document.body.clientHeight,
      document.documentElement.clientHeight,
      document.body && document.body.scrollHeight,
      document.documentElement.scrollHeight);
}

So, my suggested solution is:

in /mozilla-unified/testing/marionette/capture.js
in function capture.element

Adding a condition helped me:

capture.element = function(node, highlights = []) {
  let win = node.ownerGlobal;
  console.log(node);
  let rect = node.getBoundingClientRect();

  if (win.document.documentElement === node) {
        rect.height=Math.max(win.document.body && win.document.body.scrollHeight,win.document.documentElement.scrollHeight);
        rect.width=Math.max(win.document.body && win.document.body.scrollWidth,win.document.documentElement.scrollWidth);
  }

  return capture.canvas(
      win,
      rect.left,
      rect.top,
      rect.width,
      rect.height,
      {highlights});
};

I'm not familiar with mozilla related codes. Please, check my suggestion.
Sule, thanks a lot for the proposed fix! I know that you aren't familiar with the code, but would you feel confident enough, and have interest to maybe try to fix it yourself when I mentor you through the whole process? I would really like doing that if you are up for it.
Flags: needinfo?(suletom)
Sorry for the late answer, i am working on a full time company project.
I'm still interested in solving this problem. If my other project allows some free time, i will contact on irc.

Merry Christmas,

suletom
Flags: needinfo?(suletom)

Thank you very much Sule and Henrik. I also experience this problem at different websites that rely on absolute positioned divs. Best regards, Kees

1547028339137 Marionette TRACE 0 -> [0,4,"WebDriver:ExecuteScript",{"args":[],"newSandbox":false,"script":"return document.readyState","specialPowers":false}]
1547028339139 Marionette TRACE 0 <- [1,4,null,{"value":"complete"}]
1547028339139 webdriver::server DEBUG <- 200 OK {"value":"complete"}
1547028339142 webdriver::server DEBUG -> GET /session/e05d0cee-6db5-4aa2-ae00-7ee75a4a1a0e/screenshot
1547028339143 Marionette TRACE 0 -> [0,5,"WebDriver:TakeScreenshot",{"full":false,"highlights":[],"id":null}]
1547028339145 Marionette TRACE 0 <- [1,5,null,{"value":""}]
1547028339145 webdriver::server DEBUG <- 200 OK {"value":""}

Severity: normal → S3
Product: Testing → Remote Protocol
You need to log in before you can comment on or make changes to this bug.