2011 11-mozcamp-111115062121-phpapp02

135
PDF.JS Julian Viereck @jviereck [email protected]

Upload: arnwbl

Post on 03-Aug-2015

227 views

Category:

Technology


0 download

TRANSCRIPT

Page 2: 2011 11-mozcamp-111115062121-phpapp02
Page 3: 2011 11-mozcamp-111115062121-phpapp02

BespinSkywriter

Ace

Page 4: 2011 11-mozcamp-111115062121-phpapp02

BespinSkywriter

Ace

FirefoxDevTools

Page 5: 2011 11-mozcamp-111115062121-phpapp02

BespinSkywriter

Ace

FirefoxDevTools

ETH Zurich

Page 6: 2011 11-mozcamp-111115062121-phpapp02

BespinSkywriter

Ace

FirefoxDevTools

ETH Zurich

PDF.JS

?

Page 7: 2011 11-mozcamp-111115062121-phpapp02

Overview

• What is PDF.JS

• How PDF is structured

• Processing in PDF.JS

• Images & Fonts

• Infrastructure

• Problems & Todos

• Demo

Page 8: 2011 11-mozcamp-111115062121-phpapp02

What is PDF.JS

Page 9: 2011 11-mozcamp-111115062121-phpapp02

What is PDF.JS

• building faithful & efficient PDF renderer

Page 10: 2011 11-mozcamp-111115062121-phpapp02

What is PDF.JS

• building faithful & efficient PDF renderer

• HTML5 technology experiment

Page 11: 2011 11-mozcamp-111115062121-phpapp02

What is PDF.JS

• building faithful & efficient PDF renderer

• HTML5 technology experiment

• no native code

Page 12: 2011 11-mozcamp-111115062121-phpapp02

What is PDF.JS

• building faithful & efficient PDF renderer

• HTML5 technology experiment

• no native code

• secure (web sandbox)

Page 13: 2011 11-mozcamp-111115062121-phpapp02

What is PDF.JS

• building faithful & efficient PDF renderer

• HTML5 technology experiment

• no native code

• secure (web sandbox)

• Mozilla Labs Project - Open Source

Page 14: 2011 11-mozcamp-111115062121-phpapp02

Most vulnerable programs

Source: http://www.csis.dk/en/csis/news/3321

Page 15: 2011 11-mozcamp-111115062121-phpapp02

How PDF is structured

PDF file

Page 16: 2011 11-mozcamp-111115062121-phpapp02

How PDF is structuredHeader PDF version

PDF file

Page 17: 2011 11-mozcamp-111115062121-phpapp02

How PDF is structuredHeader

Body

[Objects]

sequence of objets

fonts, drawing cmds, images, words, bookmarks, form fields

PDF version

PDF file

Page 18: 2011 11-mozcamp-111115062121-phpapp02

How PDF is structuredHeader

Body

[Objects]

xRef Table

sequence of objets

fonts, drawing cmds, images, words, bookmarks, form fields

mapping objID ⇔ byte offset

PDF version

PDF file

Page 19: 2011 11-mozcamp-111115062121-phpapp02

root objID, xRef byte offset

root obj = ref to pages catalog

How PDF is structuredHeader

Body

[Objects]

xRef Table

Trailer

sequence of objets

fonts, drawing cmds, images, words, bookmarks, form fields

mapping objID ⇔ byte offset

PDF version

PDF file

Page 20: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

Page 21: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

Page 22: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

Page 23: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

Page 24: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

Page 25: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

• read & convert all PDF cmds ➟ IR

Page 26: 2011 11-mozcamp-111115062121-phpapp02

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

• read & convert all PDF cmds ➟ IR

IntermediateRepresentation

Page 27: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

• read & convert all PDF cmds ➟ IR

IntermediateRepresentation

Page 28: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

• read & convert all PDF cmds ➟ IR

• load required objects (fonts, images)

IntermediateRepresentation

Page 29: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

• read & convert all PDF cmds ➟ IR

• load required objects (fonts, images)

• graphics.executeIR(IR)

IntermediateRepresentation

Page 30: 2011 11-mozcamp-111115062121-phpapp02

CanvasGraphics

PartialEvaluator

Processing in PDF.JS

• get plain Uint8Array via XHR2, build Stream

• new PDFDoc(stream): read xRef, root object

• page = PDFDoc.getPage(N)

• page.startRendering(graphics)

• read & convert all PDF cmds ➟ IR

• load required objects (fonts, images)

• graphics.executeIR(IR)

IntermediateRepresentation

Page 31: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Data

Page 32: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

EvaluatorData

Page 33: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

EvaluatorData

Page 34: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator“get page 2”

Data

Page 35: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator“get page 2”

Data

builds

Page 36: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

builds

Page 37: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

builds

Page 38: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

builds

Page 39: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

builds

drawing cmds

Page 40: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

buildsobj#3?dict.x, .y?

drawing cmds

Page 41: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

buildsobj#3?dict.x, .y?

drawing cmds

Page 42: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

buildsobj#3?dict.x, .y?

obj#3 = ”foo”x = 20y = 30

drawing cmds

Page 43: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

buildsobj#3?dict.x, .y?

obj#3 = ”foo”x = 20y = 30

drawing cmds

Page 44: 2011 11-mozcamp-111115062121-phpapp02

Why IR?Partial

Evaluator

draw(obj#3, dict.x, dict.y

)

“get page 2”Data

Graphics

buildsobj#3?dict.x, .y?

obj#3 = ”foo”x = 20y = 30

draw oncanvas

drawing cmds

Page 45: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

Page 46: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

• Extracting data slow (compressed)

Page 47: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

• Extracting data slow (compressed)

• Transform data (images) slow

Page 48: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

• Extracting data slow (compressed)

• Transform data (images) slow

• Sometimes a lot of objects on page

Page 49: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

• Extracting data slow (compressed)

• Transform data (images) slow

• Sometimes a lot of objects on page

➡ Freezes UI

Page 50: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

• Extracting data slow (compressed)

• Transform data (images) slow

• Sometimes a lot of objects on page

➡ Freezes UI

➡ Use WebWorker

Page 51: 2011 11-mozcamp-111115062121-phpapp02

Problem Processing

• Extracting data slow (compressed)

• Transform data (images) slow

• Sometimes a lot of objects on page

➡ Freezes UI

➡ Use WebWorker

➡ :( no direct memory access, postMessage

Page 52: 2011 11-mozcamp-111115062121-phpapp02

Data

MainThread

Web Worker

Page 53: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluatorData

MainThread

Web Worker

Page 54: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluatorData

“get page 2”

data

MainThread

Web Worker

Page 55: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluatorData Data

“get page 2”

data

MainThread

Web Worker

Page 56: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluatorData

builds

Data“get page 2”

data

MainThread

Web Worker

Page 57: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

builds

Data“get page 2”

data

MainThread

Web Worker

Page 58: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

builds

Data“get page 2”

data

MainThread

Web Worker

Page 59: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

builds

Data“get page 2”

data

draw(“foo”, 20, 30

)

MainThread

Web Worker

Page 60: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

builds

Data“get page 2”

data

draw(“foo”, 20, 30

)

MainThread

Web Worker

IR

Page 61: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

Graphics

builds

Data“get page 2”

data

draw(“foo”, 20, 30

)

MainThread

Web Worker

IR

Page 62: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

Graphics

builds

Data“get page 2”

data

draw(“foo”, 20, 30

)

MainThread

Web Worker

IR

IR cmds

Page 63: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

Graphics

builds

Data“get page 2”

data

draw(“foo”, 20, 30

)

MainThread

Web Worker

IR

IR cmds

Page 64: 2011 11-mozcamp-111115062121-phpapp02

PartialEvaluator

draw(obj#3, dict.x, dict.y

)

Data

Graphics

builds

draw oncanvas

Data“get page 2”

data

draw(“foo”, 20, 30

)

MainThread

Web Worker

IR

IR cmds

Page 65: 2011 11-mozcamp-111115062121-phpapp02
Page 66: 2011 11-mozcamp-111115062121-phpapp02

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj

Page 67: 2011 11-mozcamp-111115062121-phpapp02

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj

PartialEvaluator

Page 68: 2011 11-mozcamp-111115062121-phpapp02

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj

PartialEvaluator xRef, catalog, resources+

Page 69: 2011 11-mozcamp-111115062121-phpapp02

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj Graphics

PartialEvaluator xRef, catalog, resources+

Page 70: 2011 11-mozcamp-111115062121-phpapp02

setGState: [ LW: 10 ]dependency: [ font0 ]setFont: font0, 12beginTextmoveText: 100, 700showText: “Hello World!”endTextmoveTo: 50, 600lineTo: 400, 600stroke

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj Graphics

PartialEvaluator xRef, catalog, resources+

Page 71: 2011 11-mozcamp-111115062121-phpapp02

setGState: [ LW: 10 ]dependency: [ font0 ]setFont: font0, 12beginTextmoveText: 100, 700showText: “Hello World!”endTextmoveTo: 50, 600lineTo: 400, 600stroke

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj Graphics

PartialEvaluator xRef, catalog, resources+

Page 72: 2011 11-mozcamp-111115062121-phpapp02

setGState: [ LW: 10 ]dependency: [ font0 ]setFont: font0, 12beginTextmoveText: 100, 700showText: “Hello World!”endTextmoveTo: 50, 600lineTo: 400, 600stroke

5 0 obj<< /Length 8 0 R>> stream /GS1 gs /F0 12 Tf BT 100 700 Td (Hello World!) Tj ET 50 600 m 400 600 l S endstreamendobj Graphics

PartialEvaluator xRef, catalog, resources+ IR

Page 73: 2011 11-mozcamp-111115062121-phpapp02

Images

Page 74: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

Page 75: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

• DOMImg.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));

Page 76: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

• DOMImg.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));

• If not JPEG stream:

Page 77: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

• DOMImg.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));

• If not JPEG stream:

• read bytes, convert to colorspace

Page 78: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

• DOMImg.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));

• If not JPEG stream:

• read bytes, convert to colorspace

• imgData = canvas.getImageData()

Page 79: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

• DOMImg.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));

• If not JPEG stream:

• read bytes, convert to colorspace

• imgData = canvas.getImageData()

• fillWithPixelData(bytes, imgData)

Page 80: 2011 11-mozcamp-111115062121-phpapp02

Images• JPEG streams:

• DOMImg.src = 'data:image/jpeg;base64,' + window.btoa(bytesToString(bytes));

• If not JPEG stream:

• read bytes, convert to colorspace

• imgData = canvas.getImageData()

• fillWithPixelData(bytes, imgData)

• canvas.putImageData(imgData)

Page 81: 2011 11-mozcamp-111115062121-phpapp02

Jpeg, but...

Page 82: 2011 11-mozcamp-111115062121-phpapp02

Jpeg, but...

• no natives support for CMYK Jpeg

Page 83: 2011 11-mozcamp-111115062121-phpapp02

Jpeg, but...

• no natives support for CMYK Jpeg

➡ use JS implementation

Page 84: 2011 11-mozcamp-111115062121-phpapp02

Jpeg, but...

• no natives support for CMYK Jpeg

➡ use JS implementation

• no native support for Jpeg 2000

Page 85: 2011 11-mozcamp-111115062121-phpapp02

Jpeg, but...

• no natives support for CMYK Jpeg

➡ use JS implementation

• no native support for Jpeg 2000

➡ use EMScripten: C-Lib ➟ JS

Page 86: 2011 11-mozcamp-111115062121-phpapp02

Jpeg, but...

• no natives support for CMYK Jpeg

➡ use JS implementation

• no native support for Jpeg 2000

➡ use EMScripten: C-Lib ➟ JS

‣ works, but not that performant

Page 87: 2011 11-mozcamp-111115062121-phpapp02

Fonts

Page 88: 2011 11-mozcamp-111115062121-phpapp02

Fonts

• There are lots of different font formats!

Page 89: 2011 11-mozcamp-111115062121-phpapp02

Fonts

• There are lots of different font formats!

• fonts are converted to OpenType

Page 90: 2011 11-mozcamp-111115062121-phpapp02

Fonts

• There are lots of different font formats!

• fonts are converted to OpenType

• use CSS: @font-face { font-family:'font0'; src:url(data:font/opentype;base64, ...)

Page 91: 2011 11-mozcamp-111115062121-phpapp02

Fonts

• There are lots of different font formats!

• fonts are converted to OpenType

• use CSS: @font-face { font-family:'font0'; src:url(data:font/opentype;base64, ...)

• some fonts can’t be converted :(

Page 92: 2011 11-mozcamp-111115062121-phpapp02

Fonts

• There are lots of different font formats!

• fonts are converted to OpenType

• use CSS: @font-face { font-family:'font0'; src:url(data:font/opentype;base64, ...)

• some fonts can’t be converted :(

• paint them

Page 93: 2011 11-mozcamp-111115062121-phpapp02

Fonts

Type I convert to Type II

Type II “use directly”

Type III paint ourself

CDI convert to Type II

Page 94: 2011 11-mozcamp-111115062121-phpapp02

Fonts

Type I convert to Type II

Type II “use directly”

Type III paint ourself

CDI convert to Type II

still needto repair

fonts!

Page 95: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

Page 96: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

Page 97: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

Page 98: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

• Pull Requests

Page 99: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

• Pull Requests

• Wiki

Page 100: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

• Pull Requests

• Wiki

• Update gh-pages on every push

Page 101: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

• Pull Requests

• Wiki

• Update gh-pages on every push

• Testing:

Page 102: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

• Pull Requests

• Wiki

• Update gh-pages on every push

• Testing:

• In Pull Request: “@pdfjsbot test”

Page 103: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure• Using GitHub

• Issue Tracker

• Pull Requests

• Wiki

• Update gh-pages on every push

• Testing:

• In Pull Request: “@pdfjsbot test”

• Runs tests on AC2 instance

Page 104: 2011 11-mozcamp-111115062121-phpapp02
Page 105: 2011 11-mozcamp-111115062121-phpapp02
Page 106: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

Page 107: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

• AreWePdfYet?

Page 108: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

• AreWePdfYet?

• Take top100 PDFs from Google

Page 109: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

• AreWePdfYet?

• Take top100 PDFs from Google

• render the first 5 pages each

Page 110: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

• AreWePdfYet?

• Take top100 PDFs from Google

• render the first 5 pages each

• compare to Preview

Page 111: 2011 11-mozcamp-111115062121-phpapp02

Infrastructure

• AreWePdfYet?

• Take top100 PDFs from Google

• render the first 5 pages each

• compare to Preview

• http://people.mozilla.com/~bdahl/corpusreport/test/ref/

Page 112: 2011 11-mozcamp-111115062121-phpapp02

Todo = Help :)

Page 113: 2011 11-mozcamp-111115062121-phpapp02

Worker Canvas

Page 114: 2011 11-mozcamp-111115062121-phpapp02

'Read-Only' Memory Web Worker

Page 115: 2011 11-mozcamp-111115062121-phpapp02

Faster Canvas Rendering

Page 116: 2011 11-mozcamp-111115062121-phpapp02

CMYK JpegJpeg2000

Page 117: 2011 11-mozcamp-111115062121-phpapp02

Font Load Event

Page 118: 2011 11-mozcamp-111115062121-phpapp02

WebPrint API

Page 119: 2011 11-mozcamp-111115062121-phpapp02

XHR Range Support

Page 120: 2011 11-mozcamp-111115062121-phpapp02

Font Support

Page 122: 2011 11-mozcamp-111115062121-phpapp02

SVG Backend

(text selection [Gecko])

Page 123: 2011 11-mozcamp-111115062121-phpapp02

“HTML5” Backend

Page 124: 2011 11-mozcamp-111115062121-phpapp02

Search | Selection | Copy

Page 125: 2011 11-mozcamp-111115062121-phpapp02

Input Forms

Page 126: 2011 11-mozcamp-111115062121-phpapp02

More Parts Of Spec

Page 127: 2011 11-mozcamp-111115062121-phpapp02

Improve Viewer

Page 128: 2011 11-mozcamp-111115062121-phpapp02

Pref & MemoryAnalysis

Page 129: 2011 11-mozcamp-111115062121-phpapp02

Improve Test Infrastructure

Page 130: 2011 11-mozcamp-111115062121-phpapp02

More Testing!

Page 131: 2011 11-mozcamp-111115062121-phpapp02

More Testing

• use PDF.JS extension!

• http://mozilla.github.com/pdf.js/extensions/firefox/pdf.js.xpi

• report broken PDFs!

• help us categorize issues

Page 132: 2011 11-mozcamp-111115062121-phpapp02

Feedback Feature

Page 133: 2011 11-mozcamp-111115062121-phpapp02

Demo

Page 134: 2011 11-mozcamp-111115062121-phpapp02

Github: https://github.com/mozilla/pdf.js

Twitter: @pdfjs

Mailing List: https://groups.google.com/group/mozilla.dev.pdf-js/topics

IRC: irc.mozilla.org #pdfjs

Engineering Weekly Call:

Thursday - 10:00am PDT, 17:00 UTC

ReadmeIssuesWiki

Page 135: 2011 11-mozcamp-111115062121-phpapp02

Q & A