Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Investigate why page.PrintToPDF doesn't work sometimes #74

Closed
sfreiberg opened this issue Jun 13, 2017 · 11 comments
Closed

Investigate why page.PrintToPDF doesn't work sometimes #74

sfreiberg opened this issue Jun 13, 2017 · 11 comments
Milestone

Comments

@sfreiberg
Copy link

When I attempt to use page.PrintToPDF().Do() I get the following error:

2017/06/13 16:06:52 -> {"error":{"code":-32000,"message":"PrintToPDF is not implemented"},"id":87}
2017/06/13 16:06:52 PrintToPDF is not implemented (-32000)

I've tried this against Chrome build 59, Canary and the latest build. I was able to print to pdf from the cli with:

~/Downloads/chrome-mac/Chromium.app/Contents/MacOS/Chromium --headless --disable-gpu --print-to-pdf=test.pdf http://google.com/

@sfreiberg
Copy link
Author

I should add I have no idea where this is breaking down as Chrome seems like it supports it and the code looks fine in chromedp. I just don't understand enough about debugging the debug protocol to track down the issue.

@sfreiberg
Copy link
Author

This must have actually been an issue with some other piece of the code. When I stripped it down to the minimum I was able to get it to work.

@pescadosmith
Copy link

Can you explain how you got it to work?

@kenshaw
Copy link
Member

kenshaw commented Oct 6, 2017

@pescadosmith if this wasn't working properly before, it was likely due to a mismatch in the version of Chrome being used and the protocol version being generated. Because chromedp aims to be type-safe, the generated CDP protocol that gets generated tracks the master branch of the Chromium source code. This can cause problems from time to time, especially with "experimental" features in the Chrome Debugging Protocol such as the Page.printToPDF command. If you need chromedp to sync exactly to the version of Chrome you are using, you can generate a version of the underlying cdp/* domains that matches directly with your version of Chrome via the following:

  1. Checkout the latest chromedp source code in the normal way
  2. Change to the $GOPATH/src/github.com/knq/chromedp/cmd/chromedp-gen
  3. Execute the update.sh script supplying the version of Chrome you wish to use:
$ ./update.sh 61.0.3163.113
BROWSER_PROTO: https://chromium.googlesource.com/chromium/src/+/61.0.3163.113/third_party/WebKit/Source/core/inspector/browser_protocol.json?format=TEXT
JS_PROTO: https://chromium.googlesource.com/v8/v8/+/master/src/inspector/js_protocol.json?format=TEXT
  1. Run the build.sh script in order to regenerate the low level protocol/domain code:
$ ./build.sh 
go generate
qtc: 2017/10/06 17:03:05 Compiling *.qtpl template files in directory "templates"
qtc: 2017/10/06 17:03:05 Compiling "templates/domain.qtpl" to "templates/domain.qtpl.go"...
qtc: 2017/10/06 17:03:05 Compiling "templates/extra.qtpl" to "templates/extra.qtpl.go"...
qtc: 2017/10/06 17:03:05 Compiling "templates/file.qtpl" to "templates/file.qtpl.go"...
qtc: 2017/10/06 17:03:05 Compiling "templates/type.qtpl" to "templates/type.qtpl.go"...
qtc: 2017/10/06 17:03:05 Total files compiled: 4

go build

time ./chromedp-gen $@
2017/10/06 17:03:06 skipping command Page.addScriptToEvaluateOnLoad [deprecated]
2017/10/06 17:03:06 skipping command Page.removeScriptToEvaluateOnLoad [deprecated]
2017/10/06 17:03:06 skipping command Page.getCookies [redirect:Network]
2017/10/06 17:03:06 skipping command Page.deleteCookie [redirect:Network]
2017/10/06 17:03:06 skipping command Page.setDeviceMetricsOverride [redirect:Emulation]
2017/10/06 17:03:06 skipping command Page.clearDeviceMetricsOverride [redirect:Emulation]
2017/10/06 17:03:06 skipping command Page.setGeolocationOverride [redirect:Emulation]
2017/10/06 17:03:06 skipping command Page.clearGeolocationOverride [redirect:Emulation]
2017/10/06 17:03:06 skipping command Page.setDeviceOrientationOverride [redirect:DeviceOrientation]
2017/10/06 17:03:06 skipping command Page.clearDeviceOrientationOverride [redirect:DeviceOrientation]
2017/10/06 17:03:06 skipping command Page.setTouchEmulationEnabled [redirect:Emulation]
2017/10/06 17:03:06 skipping command Emulation.setVisibleSize [deprecated]
2017/10/06 17:03:06 skipping command DOM.highlightRect [redirect:Overlay]
2017/10/06 17:03:06 skipping command DOM.highlightNode [redirect:Overlay]
2017/10/06 17:03:06 skipping command DOM.hideHighlight [redirect:Overlay]
2017/10/06 17:03:06 skipping event param Target.detachedFromTarget.targetId [deprecated]
2017/10/06 17:03:06 skipping event param Target.receivedMessageFromTarget.targetId [deprecated]
2017/10/06 17:03:06 skipping command param Target.sendMessageToTarget.targetId [deprecated]
2017/10/06 17:03:06 skipping command param Target.detachFromTarget.targetId [deprecated]
2017/10/06 17:03:06 skipping command param Tracing.start.categories [deprecated]
2017/10/06 17:03:06 skipping command param Tracing.start.options [deprecated]
2017/10/06 17:03:06 skipping domain Console (console) [deprecated]
2017/10/06 17:03:06 running goimports
2017/10/06 17:03:26 running easyjson (stubs)
2017/10/06 17:03:26 running easyjson
2017/10/06 17:03:35 running gofmt
2017/10/06 17:03:35 done.

real	0m28.516s
user	1m27.528s
sys	1m11.184s

go install ../../cdp/...

Note that the main action/task code defined in the root chromedp package does not use any experimental or deprecated APIs, so the chromedp-gen command should be able to be used all the way back to I believe Chromium 48, which is now over 2 years old.

@sfreiberg
Copy link
Author

I don't recall exactly what I was doing but I think I did something with the DOM and once I did that Chrome wouldn't render PDFs via github.com/knq/chromedp or even if I manually triggered it via the browser. I was only doing a POC so I don't have the original code around anymore.

@mc0
Copy link

mc0 commented Oct 7, 2017

@kenshaw Thanks 😄 ! It looks like that may have been part of the issue but in addition to that PrintToPDF is not implemented for Chrome when the headless arg isn't passed. I don't know if this could be helped by some documentation as Puppeteer explains this here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagepdfoptions

@mh-cbon
Copy link

mh-cbon commented Nov 12, 2018

for some reasons none will work for me. the solution posted by kenshaw does not work for me. The solution provided by mc0 did help, however my program hangs just before returning the pdf bytes buffer.

the ouput with logs enabled is similar to

"Page.frameStoppedLoading","params":{"frameId":"7E6D3A2D9963D5C2D46F6F37B1445161"}}
2018/11/12 22:02:25 <- {"id":12,"method":"Page.printToPDF","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"Page.frameResized","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"Page.frameResized","params":{}}
2018/11/12 22:02:25 -> {"id":12,"result":{"data":"JVBER...AwNjgwNiAwMDAwMCBuIAowMDAwMDA2ODkxIDAwMDAwIG4gCjAwMDAwMDY5NzYgMDAwMDAgbiAKMDAwMDAwNzA2MSAwMDAwMCBuIAowMDAwMDA3MjA1IDAwMDAwIG4gCjAwMDAwMDc4NDcgMDAwMDAgbiAKMDAwMDAwODA0NCAwMDAwMCBuIAowMDAwMDE3MTYzIDAwMDAwIG4gCnRyYWlsZXIKPDwvU2l6ZSAxOAovUm9vdCA1IDAgUgovSW5mbyAxIDAgUj4+CnN0YXJ0eHJlZgoxNzY4OAolJUVPRg=="}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"Page.frameResized","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"CSS.mediaQueryResultChanged","params":{}}
2018/11/12 22:02:25 -> {"method":"Page.frameResized","params":{}}
2018/11/12 22:02:25 -> { "method": "Inspector.detached", "params": { "reason": "target_closed"} }
^Csignal: interrupt

The source program was

package main

import (
	"context"
	"flag"
	"io"
	"log"
	"os"
	"time"

	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

func main() {

	var url string
	var out string
	var wait time.Duration

	flag.StringVar(&url, "url", "", "set the url to fetch")
	flag.StringVar(&out, "out", "-", "set destination output, default to stdout")
	flag.DurationVar(&wait, "wait", 4*time.Second, "set a time to wait duration before the the page is captured")
	flag.Parse()

	var dst io.Writer
	{
		if out == "-" {
			dst = os.Stdout
		} else {
			f, err := os.Create(out)
			if err != nil {
				log.Fatal(err)
			}
			defer f.Close()
			dst = f
		}
	}

	var err error

	// create context
	ctxt, cancel := context.WithCancel(context.Background())
	def
```er cancel()

	// create chrome instance
	c, err := chromedp.New(ctxt,
		chromedp.WithLog(log.Printf),
		chromedp.WithRunnerOptions(func(opts map[string]interface{}) error {
			opts["headless"] = ""
			return nil
		}),
	)
	if err != nil {
		log.Fatal(err)
	}

	// run task list
	var buf []byte
	err = c.Run(ctxt, printToPDF(wait, url, &buf))
	if err != nil {
		log.Fatal(err)
	}

	// shutdown chrome
	err = c.Shutdown(ctxt)
	if err != nil {
		log.Fatal(err)
	}

	// wait for chrome to finish
	err = c.Wait()
	if err != nil {
		log.Fatal(err)
	}

	log.Println(len(buf))
	_, err = dst.Write(buf)
	if err != nil {
		log.Fatal(err)
	}
}

func printToPDF(wait time.Duration, urlstr string, res *[]byte) chromedp.Tasks {
	return chromedp.Tasks{
		chromedp.Navigate(urlstr),
		chromedp.Sleep(wait),
		pdf(res),
	}
}

func pdf(pdfbuf *[]byte) chromedp.Action {
	if pdfbuf == nil {
		panic("pdfbuf cannot be nil")
	}

	return chromedp.ActionFunc(func(ctx context.Context, h cdp.Executor) error {
		// take page screenshot
		buf, err := page.PrintToPDF().Do(ctx, h)
		if err != nil {
			return err
		}
		*pdfbuf = buf
		return nil
	})
}

i ended using pupeteer :/

@SuddenGunter
Copy link

is this implemented now?
We're using pupeeter and nodejs in same container with chrome only for pdf printing purposes. It would be nice to use chromedp for this

@mvdan
Copy link
Contributor

mvdan commented Jun 19, 2019

Reopening temporarily in case there's a bug here.

For what it's worth, there's no implementation required here. All the examples above use https://godoc.org/github.com/chromedp/cdproto/page#PrintToPDF, which should work fine with the latest chromedp version. If it doesn't, there may be a bug to investigate.

@mvdan mvdan reopened this Jun 19, 2019
@mvdan mvdan changed the title PrintToPDF is not implemented Investigate why page.PrintToPDF doesn't work sometimes Jun 19, 2019
@SuddenGunter
Copy link

will try to use, possibly next week.
will notify you in case I see any errors

@SuddenGunter
Copy link

@mvdan everything works fine
https://github.com/SuddenGunter/pandaren/blob/master/cmd/main.go
thank you for this awesome library!

@kenshaw kenshaw added this to the v0.4.0 milestone Jul 2, 2019
@mvdan mvdan closed this as completed in d151ece Jul 2, 2019
@mvdan mvdan modified the milestones: v0.5.0, v0.4.0 Aug 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants