EPUB Scriptable Components 1.0
Editor's Draft 15 January 2015
This version:
http://www.idpf.org/epub/sc/api/sc-api-20150115.html
Latest version:
http://www.idpf.org/epub/sc/api
Previous version:
N/A
Copyright © 2014-2015 International Digital Publishing Forum™
All rights reserved. This work is protected under Title 17 of the United States Code. Reproduction and dissemination of this work with changes is prohibited except with the written permission of the International Digital Publishing Forum (IDPF).
EPUB is a registered trademark of the International Digital Publishing Forum.
Editors
Will Manis, Invited Expert
Brady Duga, Google
Darryl Lehmann, Imagineeringart.com Inc.
Mike Chen, Inkling
Status of this Document
This specification is a work in progress and subject to change.
All comments on this specification should be submitted via the EPUB 3 Working Group Issue Tracker, hosted on Google Code. NOTE: you must login via a Google Account in order to submit an issue. Please submit spec comments with the labels "Type-ReviewComment" and "Spec-EPUBSC". Members of the EPUB Working Group may submit questions via the mailing list.
Table of Contents
2.2 Reading System Conformance
4. Inter-Component Communication
4.2.3.1 Component ID ("componentId")
4.2.3.2 Message ID ("messageId")
4.2.3.3 Timestamp ("timestamp")
4.2.3.7 TopicData ("topicData")
4.3.1 Subscribe ("epubsc_subscribe")
4.3.2 Unsubscribe ("epubsc_unsubscribe")
4.3.3 Publish ("epubsc_publish")
4.4.2.1 Ready ("epubsc_ready")
4.4.2.2 Pause ("epubsc_pause")
4.4.2.3 Resume ("epubsc_resume")
4.4.2.5 Unload ("epubsc_unload")
4.4.2.6 Event ("epubsc_event")
5.Component-Parent Event Communication
5.2.1 The Publish ("epubsc_publish") Method
5.2.3.2 TopicData ("topicData")
Appendix B. ComponentID sample code
Appendix D. Acknowledgements and Contributors
This section is informative
This specification, EPUB Scriptable Components, provides an interoperable publish and subscribe (pubsub) pattern by which interactive content can be created and incorporated into EPUB Publications. This interactive content can be rendered in any Reading System that conforms to the requirements in this specification.
This specification is not a replacement for the scripting architecture defined in [ContentDocs301], and implementing or using the APIs and processes does not replace the requirements, restrictions and best practices defined in that specification.
Scriptable Components can be used in Reading Systems that support only container-constrained scripts or that support full spine-level scripting.
The goal of this specification and [SCPackage] is to allow third-party Scriptable Components (widgets) to be securely integrated into XHTML Content Documents. As such, this specification requires that Scriptable Components be embedded using the [HTML5] iframe element ‒ whether they are embedded into an XHTML Content Document in an EPUB Publication or into another Scriptable Component.
This specification assumes that domain isolation exists between the Scriptable Components, but the Reading System might or might not enforce domain isolation on the document referenced by the iframe element. If domain isolation is enforced a relatively high degree of isolation and security is achieved. If domain isolation is not enforced security could be an issue (e.g., the Scriptable Component might compromise the EPUB Publication and/or the Reading System).
Compliance with this specification does not guarantee any particular level of security, it is intended to provide a framework in which Reading System implementors can achieve security with third-party scripting.
User Agent to Reading System Communication
Some Reading Systems on mobile devices are implemented using a system-provided web component (often referred to as a WebView) for the rendering of content. It is common for these components to provide some level of communication with the rest of the Reading System, for instance to report on progress and load content. Such calls can have both security and privacy implications. For example, it might be possible to determine the name of the user and the list of books in the users library. Such communications can also be used to exploit vulnerabilities, like buffer overflows, in the Reading System.
This specification does not directly resolve these issues. It is the responsibility of the Reading System implementor to account for the security and privacy implication of WebView-to-application communication.
Privacy
As Scriptable Components evolve, they will invariably make use of communication resources to retrieve and store remote (cloud) data ‒ data that might contain sensitive personal information.
It is beyond the scope of this specification to ensure or enforce the privacy of this information. Reading Systems might employ measures to restrict or eliminate communication across a network, or limit or disallow cookies and local storage.
Refer to the EPUB Specifications for definitions of EPUB-specific terminology used in this document.
Component Parent
Scriptable Component (also Component)
The keywords must, must not, required, shall, shall not, should, should not, recommended, may, and optional in this document are to be interpreted as described in [RFC2119].
All sections of this specification are normative except where identified by the informative status label "This section is informative". The application of informative status to sections and appendices applies to all child content and subsections they may contain.
All examples in this specification are informative.
The following typographic conventions are used in this specification:
markup
All markup (elements, attributes, properties), code (JavaScript, pseudo-code), machine processable values (string, characters, media types) and file names are in red-orange monospace font.
markup
Links to markup and code definitions are underlined and in red-orange monospace font. Only the first instance in each section is linked.
http://www.idpf.org/
URIs are in navy blue monospace font.
hyperlink
Hyperlinks are underlined and in blue.
[reference]
Normative and informative references are enclosed in square brackets.
Term
Terms defined in the Terminology are in capital case.
Informative markup examples are in monospace font.
NOTE
Informative notes are preceded by a "Note" header.
An EPUB Content Document that supports Scriptable Components must meet the following criteria:
› It must conform to all content and security requirements in 3. Scriptable Components.
› It must contain EPUB Scriptable Component code that supports the pub/sub protocol, as defined in this specification [link] 4. Inter-Component Communication.
An EPUB Publication that contains EPUB Scriptable Components must be packaged in conformance with EPUB Widget Packaging and Integration [SCPackage].
EPUB Reading Systems that support Scriptable Components must meet the following criteria:
› Container-constrained scripting [ContentDocs301] must be supported.
› All conformance requirements placed on Reading Systems by the EPUB specification, particularly the requirements for scripting [ContentDocs301], must be met.
› If spine-level scripting [ContentDocs301] is not supported, the Reading System must support the postMessage protocol defined 4.2.2 The postMessage Method for all Scriptable Components that are direct children of the spine. Otherwise, it must not provide the postMessage protocol, as the spine-level Components will already implement it.
All Scriptable Components must be hosted in an [HTML5] iframe element.
All resources used by a Component must be included in the EPUB Container, unless allowed to be remotely hosted (e.g., audio/video).
Scriptable Components must assume that they exist in a separate domain from the EPUB Content Document that hosts them. Reading Systems may enforce domain isolation of Scriptable Components.
The only means of communication between an EPUB Content Document and the contained Scriptable Components must occur using the EPUB Scriptable Components protocol. No direct access across Scriptable Component boundaries is allowed; properties contained on window.parent must not be accessed.
This section is informative
A Scriptable Component communicates via a protocol layer driven internally by an implementation of the HTML5 postMessage API [HTML5WebMsg].
A Scriptable Component functions ubiquitously by being both subscriber and subscribed in this model. This distributed model means that each Scriptable Component is responsible for relaying the messaging protocol to its direct dependent children and its parent in turn.
This protocol defines the methods by which Scriptable Components communicate, and predefines a set of message topics for communication.
To prepare to send and receive messages through the pubsub protocol defined in this specification, a Scriptable Component must initiate the following steps during its load process:
This pubsub communication bridge is used to pass a message of a specific method type, as defined in 4.2.3 Message Structure.
The methods used to communicate are described in 4.3 Methods. These methods define a communication channel for specific handling.
At this stage, the Component can subscribe, unsubscribe, publish, and send topics through the pubsub communication bridge.
The window.postMessage() API [HTML5WebMsg] provides a safe communication bridge between two Scriptable Components in different domains, and is used by Components to publish messages to target windows – their subscribers.
Scriptable Components must use the window.postMessage() method [HTML5WebMsg] to publish messages to, and through, target windows.
Subscribers, in turn, must register event listeners on the event handler event type "message" [HTML5WebMsg] to subscribe to messages.
For security reasons, it is recommended to validate the event source and origin values of all messages received, as described in the authoring security section of [HTML5WebMsg].
Each message published by a Scriptable Component must be serialized as a JSON object [RFC4627] that must be valid to the schema in Appendix A.
Messages are composed of the following properties:
Refer to each properties definition for more information.
Example of a message.
var epubsc_message =
{
"componentId":
"b33ef720-556a-11e4-8ed6-0800200c9a66",
"messageId":
"b33ef720-556a-11e4-8ed6-0800200c9a66+1",
"timestamp":
1413488477617,
"type":
"epubsc_message",
"method":
"epubsc_publish",
"topic":
"current_temperature",
"topicData":
{
"location":
"Toronto,
Ontario",
"currentTemp":
21,
"tempFormat":
"Celcius"
}
};
The required componentId property contains a string identifier that uniquely identifies a Scriptable Component for the lifetime of the session (e.g., a GUID [RFC4122]).
See Appendix B for sample code.
The required messageId property contains a string identifier that uniquely identifies a message.
This specification does not require a format for the identifier. The identifier can be a combination of a unique value with the Scriptable Component identifier, a simple monotonic counter value or any other value guaranteed to be unique.
The required timestamp property is the value returned from the JavaScript Date.now() function.
The required type property identifies the nature of the message object.
For all messages, the value must be the string "epubsc_message".
The required method property contains a string identifier that declares the event method being invoked.
The value must be one of the following: "epubsc_subscribe", "epubsc_unsubscribe" or "epubsc_publish".
The required topic property contains either a reserved or component-defined topic name.
For more information, refer to 4.4.2 Reserved Topics and 4.4.3 Component Topics.
The topicData property is required when the topic requires additional data.
Due to the distributed nature of the pubsub protocol, the order in which messages are received by a subscriber cannot be guaranteed. Components consequently should not be designed to be dependent on an orderly arrival of messages from separate components. Components should rely on the ordering of message from a unique instance of a component. Message timing information should be extracted from the timestamp property.
The epubsc_subscribe method provides the mechanism for a Scriptable Component to subscribe to a topic.
This method must be aware of the topic to begin listening.
The epubsc_unsubscribe method provides the mechanism for a Scriptable Component to terminate listening to a particular topic.
This method must be aware of the topic string value to facilitate this lookup and removal.
The epubsc_publish method allows a ready Scriptable Component to publish a message on a previously subscribed topic.
This method must be aware of the topic name, and the message object to be passed.
All topic subscriptions and publications must be propagated up to the Component Parent, regardless of subscription
The component must send published topics to all subscribed children. If the sender is also subscribed, it must also receive the topic.
A component may subscribe to a topic multiple times.
A component may unsubscribe from a topic by removing a specific handler.
The topic "epubsc_ready" is reserved to indicate that a component has entered its ready state and is able to receive messages.
At startup, a Component must announce that it is ready to handle messages (topic subscriptions and publications) by publishing a message with the epubsc_ready topic.
In this message, it must pass its own componentId to its Component Parent. The Component also has to be able to store and maintain a list of participating windows using each window's componentId.
The topic "epubsc_pause" is reserved to indicate that a component has entered its paused state.
The topic "epubsc_resume" is reserved to indicate that a component has resumed its ready state again.
The topic "epubsc_load" is reserved to indicate that a component has begun loading.
The topic "epubsc_unload" is reserved to indicate that a component has begun unloading.
The topic "epubsc_event" is reserved for Javascript event communication.
This section is informative
A Scriptable Component might receive Javascript events that has no meaning to it. For example, a right arrow key press might not be handled by the component. In this case, the Scriptable Component typically transmits information about this event to its parent, giving the parent an opportunity to respond to it.
A Scriptable Component might also receive Javascript events that has meaning to it. For example, a key press in an input field has an effect within the Scriptable Component. In this case, the Scriptable Component typically informs its parent of its receipt of this event, so that the Reading System does not also react to it.
Scriptable Components have to publish to their parents how the required Javascript events (see section on required events) were or were not handled.
Scriptable Components must use the epubsc_publish method to communicate JavaScript events to the Component Parent.
All event messages must be propagated up to the Component Parent.
The component must not send event messages to any of its children.
Scriptable Components must use the reserved topic “epubsc_event” when publishing JavaScript events.
Scriptable Components must populate the topicData property when publishing JavaScript events.
The property must include the following properties, copied from the original event:
The topicData also must include a boolean property, handled, indicating whether or not the Component handled the event. The Component Parent should not respond to the event if this property is true.
Event transmission is required for mouse (including wheel), keyboard, touch events and pointer events.
Mouse events
Wheel events
Keyboard events
Touch events
Pointer events
The JSON representation schema for messages:
{
"id": "http://www.idpf.org/epub/sc/1.0/schema.json",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "EPUB Scriptable Components Message Schema",
"description": "Schema validation for the message body",
"properties": {
"componentId": { "type": "string" },
"messageId": { "type": "string" },
"timestamp": { "type": "number" },
"type": {
"type": "string",
"enum": ["epubsc_message"]
},
"method": {
"type": "string",
"enum": ["epubsc_subscribe", "epubsc_unsubscribe", "epubsc_publish"]
},
"topic": { "type": "string" },
"topicData": { "type": "object" }
},
"required": ["componentId", "messageId", "timestamp", "method", "topic"],
"additionalProperties": false
}
Validation using this schema requires a processor that supports [JSONSchema].
This appendix is informative
The uniqueness of a component ID over a session is critically important to correct behavior of widgets. An implementation of [RFC4122] will provide sufficient uniqueness.
Examples include:
function generateComponentID_() {
var d = new Date().getTime();
var template = "xxxxxxxx-xxxx-Zxxx-yxxx-xxxxxxxxxxxx";
return template.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d/16);
return (c == "x" ? r : (r & 0x7 | 0x8)).toString(16);
});
}
This appendix is informative
Allow two Scriptable Components to communicate. A UI control in one component may direct a visualization change in a second component.
An embedded Scriptable Component may contain a running video. When the EPUB document is paged or scrolled the Reading System will instruct the Scriptable Component to pause the video.
UI events occurring in IFrames are not bubbled to parent windows. Scriptable Components will enable event propagation and handling by parent windows and Reading Systems.
This appendix is informative
Active members of the working group included:
IDPF Members
Invited Experts/Observers
[ContentDocs301] EPUB Content Documents 3.0.1.
[HTML5] HTML5: A vocabulary and associated APIs for HTML and XHTML.
[HTML5WebMsg] HTML5 Web Messaging.
[JSONSchema] JSON Schema: core definitions and terminology.
[Publications301] EPUB Publications 3.0.1.
[RFC2119] Key words for use in RFCs to Indicate Requirement Levels (RFC 2119). March 1997.
[RFC4627] The application/json Media Type for JavaScript Object Notation (JSON) (RFC 4627). D. Crockford. July 2006.
[SCPackage] EPUB Scriptable Components Packaging and Integration.
[RFC4122] A Universally Unique IDentifier (UUID) URN Namespace (RFC 4122). P. Leach, et al. July 2005.