Delegated Resource Selection
1.0 SPECIFICATION
Introduction
Within Collaborative ALM scenarios, separate servers across various domains will need to exchange information securely and reliably. An approach to accomplish this is to delegate some of the core integration sequences: resource selection and creation. By delegating these tasks to the owning applications services, it is possible to independenlty upgrade their capabilities without impacting the integration by only adhering to the cross webpage communication protocol and formats.
This specification defines communication between an embedded page (webpage of HTML content) and some outside observer, where the goal is to communicate some response to the observer. The response is a well-defined JSON object with defined semantics. A common scenario is a page from one origin which needs to embed (using an HTML iframe) a webpage from another origin. Another scenario is displaying that same webpage, but this time in a native application which has a web browser embedded in its user interface.
This specification satisfies these scenarios for commonly used web browsers without imposing relaxed browser security (e.g. enabling cross-site scripting). This is done by employing two different communication protocols: 'Post Message' and 'Window Name' which are detailed in the following sections.
Notation and Conventions
The key words “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. Domain name examples use
RFC2606.
Terminology
Observer - a client web application that is
JavaScript? enabled which registers event handlers to content elements
Embedded page - a URL-referencable HTML resource that provides client capabilities and dispatches events
iframe - an
element defined in HTML used for embedding browsable content
Protocol Selection
The observer selects which protocol the use and communicates it to the embedding page. The observer MUST supply the as part of the embedded page's URL a fragment identifier and the embedded page MUST use the designated protocol. Embedded pages MUST support both these protocols:
Example for testing for protocol selection
function respond(message){
var protocol = window.location.hash;
if (protocol == '#oslc-windowName-1.0'){
respondWithWindowName(message);
} else if(protocol == '#oslc-postMessage-1.0'){
respondWithPostMessage(message);
}
}
Protocol Definitions
'Post Message'
See
W3C HTML5 postMessage
Input |
protocol - passed in URL's fragment ( oslc-postMessage-1.0 ) |
Notification |
Observer listens for window 'message' events, ignoring events from other sources or not prefixed with "oslc-response:" |
Output |
response - passed in event.data string, must be prefixed with "oslc-response:" |
The 'Post Message' protocol relies on the function
window.postMessage()
, available in the latest or pending releases of most browsers (Firefox 3, Safari 4, IE 8). Observers must anticipate other, unrelated uses of postMessage(), and should ignore messages not conforming to this protocol.
Typically, the embedded page will be loaded in a window inside another window, such as a iframe inside some surrounding webpage. In such cases,
postMessage()
must be called on that parent window. But in a native application, an outer page is not needed and the embedded page may be shown directly in the browser's "root" window. When the embedded page has no parent window, it must call
postMessage()
on its own window.
Observer Responsibilities for 'Post Message'
Given: the observer has been given a URL to the webpage (and that URL must not specify any fragment identifier), perform the following:
- Append the fragment identifier
oslc-postMessage-1.0
to the URL
- Add a
'message'
listener to the outer window to receive messages from the chooser page
- Display the modified URL for the chooser in a frame and show the frame
- When a properly-formed message from that frame is received, destroy the chooser frame and handle the message
function postMessageProtocol(/*string*/ url) {
// Step 1
url += '#oslc-postMessage-1.0';
// Step 2
var frame;
var listener = function(e) {
var HEADER = "oslc-response:";
if (e.source == frame.contentWindow && e.data.indexOf(HEADER) == 0) {
// Step 4
window.removeEventListener('message', listener, false);
destroyFrame(frame);
// remove spaces from "s u b s t r"
handleMessage(e.data.s u b s t r(HEADER.length));
}
};
window.addEventListener('message', listener, false);
// Step 3
frame = doc.createElement('iframe');
frame.src = url;
displayFrame(frame);
}
Embedded Page Responsibilities for 'Post Message'
As soon as the embedded page has loaded, perform the following:
- (User makes a selection somehow)
- Communicate the User's choice (or lack of one if selection was cancelled)
- Send response using
postMessage()
to the page's parent window
- If the page is not parented, then the message is posted to the page's own window. The page must ignore this message to itself.
function respondWithPostMessage(/*string*/ response) {
// Step 2
(window.parent | window).postMessage("oslc-response:" + response, "*");
}
'Window Name'
See
Window Object 1.0 Window.name
Input |
protocol - passed in URL's fragment ( oslc-windowName-1.0 ) returnURL - passed in window.name |
Notification |
Observer listens for window 'onload' event, ignoring all loads except returnURL |
Output |
response - passed in window.name |
The 'window name' protocol uses the (
window.name
) property to communicate the response. This special property of window maintains its value even as the window navigates to a different origin. But the IFrame's
window.name
can only be read when the accessing window shares the same origin. For this to happen, when the embedded page is finished it must set the
window.name
and also change the
window.location
to a page with the same origin as the outer frame. This not only allows the observer to access the result, but also fires an event telling the observer when to do so. This return location is passed to the embedded page using the
window.name
property.
Observer Responsibilities for 'Window Name'
Given: the observer has been given a URL to the webpage (and that URL must not specify any fragment identifier), perform the following:
- Append the fragment identifier
oslc-windowName-1.0
to the URL
- Construct a frame, hooking a listener for 'onload' events from that frame
- Provide the returnURL to the picker by setting the frame's
window.name
to the URL string
- Display frame and wait
- For each 'onload' event: if the frame's location becomes returnURL, read from
window.name
and finish
The following Javascript code illustrates the protocol. Note: We provide helper classes that contain that code.
bug 76689
function windowNameProtocol(/*string*/ url, onDataReceived) {
// Step 1
url += '#oslc-postMessage-1.0';
// Step 2
// NOTE: In Internet Explorer, the following code will not function.
// (Browser-specific workarounds are not essential to this illustration.)
var frame = doc.createElement('iframe');
frame.onload = function() {
// Step 5
try { // May throw an exception if the frame's location is still a different origin
if (frame.contentWindow.location == returnLocation) {
var message = frame.contentWindow.name;
destroyFrame(frame);
handleMessage(message);
}
} catch(e) {
// ignore: access exception when trying to access window name
};
};
// Step 3
// Set frame.name to a URL of a blank page on the observer's domain.
frame.name = "http://localhost/blank.html";
// Step 4
frame.src= url;
displayFrame(frame);
}
Embedded Page Responsibilities for 'Window Name'
As soon as the embedded page has loaded, perform the following:
- (User makes a selection somehow)
- Read returnLocation from
window.name
- Communicate the User's choice (or lack of one if selection was cancelled)
function respondWithWindowName(/*string*/ response) {
// Step 2
var returnURL = window.name;
// Step 3
window.name = response;
window.location = returnURL;
}
Resource Selection
The resource selector is used by observer applications to perform service provider specific search and query to locate resources, then the result is communicated from the selector embedded page to the observer of the selections made. Resource selectors defined in the
RM Service Discovery Document's oslc_rm:requirementSelectionDialog
element MUST support both the
Protocol Selection and format of message as indicated here:
Format of Message
The items selection MUST be returned as a JSON string. The JSON string MUST contain:
- Attribute of name "http://open-services.net/xmlns/rm/1.0/web/message" and value of "http://open-services.net/xmlns/rm/1.0/web/create"
- JSON object named "http://open-services.net/xmlns/rm/1.0/web/results" whose value is either:
- an array of JSON objects that MUST contain the attributes:
-
http://www.w3.org/1999/02/22-rdf-syntax-ns#resource
- the URI of the selected resource.
-
http://www.w3.org/2000/01/rdf-schema#label
- a label intended for user interface displays.
- an empty string MUST indicate that the resource selector has been cancelled
Example:
{
"http://open-services.net/xmlns/rm/1.0/web/message": "http://open-services.net/xmlns/rm/1.0/web/select",
"http://open-services.net/xmlns/rm/1.0/web/results" : [
{
"http://www.w3.org/2000/01/rdf-schema#label": "Signal diffuser shall be ISO compliant.",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#resource": "http://example.com/requirements/23"
},
{
"http://www.w3.org/2000/01/rdf-schema#label": "System performance shall degrade gracefully under load.",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#resource": "http://example.com/requirement/44"
}
]
}
Resource Creation
The resource creation is used by observer applications to perform service provider specific resource creation, then the result is communicated from the creation embedded page to the observer of the resource creations that occurred. Resource creation dialogs are defined in the service discovery document's oslc_rm:requirementCreationDialog property {Creation Dialog URL}. Consumers and providers of creation dialog URLs MUST support both the
Protocol Selection and format of message as indicated in this specification.
Prefilling Creation Dialogs
Service providers MUST support receiving a POST request whose content body is a requirement resource definition (content body of application/x-oslc-rm-requirement-1.0+xml) to the {Creation Dialog URL} to retrieve a URL that represents the embedded page to be used. Service providers MUST respond with a response status of 201 (Created) with the response header Location whose value is the URL to request the newly created form. This freshly created form is intended to be used at most once - Providers SHOULD respond with 410 (Gone) or 404 (Not found) if an attempt is made to POST to the form more than once. Consumers are expected to POST to the form within a short amount of time of it being created - providers are not required to keep the form indefinitely, and may periodically cleanup these resources.
Format of Message
The corresponding URIs of the resources created MUST be returned as a JSON string. The JSON string MUST contain:
- Attribute of name "
http://open-services.net/xmlns/rm/1.0/web/message
" and value of " http://open-services.net/xmlns/rm/1.0/web/create
"
- JSON object named "
http://open-services.net/xmlns/rm/1.0/web/results
" whose value is either:
- an array of JSON objects that MUST contain the attributes:
- an empty string MUST indicate that the resource creation has been cancelled
Example:
{ "http://open-services.net/xmlns/rm/1.0/web/message": "http://open-services.net/xmlns/rm/1.0/web/create", "http://open-services.net/xmlns/rm/1.0/web/results" : [ { "http://www.w3.org/2000/01/rdf-schema#label": "SRD272: Signal coherence shall be verified", "http://www.w3.org/1999/02/22-rdf-syntax-ns#resource": "http://example.com/requirement55" }, { "http://www.w3.org/2000/01/rdf-schema#label": "URD38: The system shall support ISO 7373 on signal coherence", "http://www.w3.org/1999/02/22-rdf-syntax-ns#resource": "http://example.com/requirement54" } ] }
Observer iframe Considerations
It is recommended that the observer's iframe make the following adjustments to provide a more seemless user experience with the embedded page:
- embed the
iframe
within a div
element, setting div's height and width per service description hints and iframe's height/width to 100%
- set the
iframe
border size to '0'
- set scrolling to auto
References