/
Core-Gadget - Document Structure
Core-Gadget - Document Structure
This is a DRAFT rewrite of the basic document structure for gadgets... it is ONLY A DRAFT
<section title="Document Structure"> <section title="The <Module> Element" <t>The root of the Gadget Specification Document is the <Module> element. It's children MUST consist of no more than one <ModulePrefs> element, no more than one <UserPref> element, and one or more <Content> elements.</t> <figure><artwork> Module = element Module { attribute specificationVersion { text }, undefinedAttribute*, ModulePrefs?, UserPref*, Content+, extensionElement* } </artwork></figure> <t>The "specificationVersion" attribute identifies the version of the OpenSocial specification the container MUST use to process and render the Gadget Specification. The value is a string conforming to the version identifier described in <xref target="Versioning"/>. If absense, the default value is "1.0".</t> <t>Text nodes included as children of the <Module> element SHOULD be ignored.</t> </section> <section title="The <ModulePrefs> Element"> <t>The <ModulePrefs> element serves as a container for all metadata, features and processing rules dealing with the gadget. The children of the element consist of a variety of optional attributes and elements.</t> <figure><artwork> ModulePrefs = element ModulePrefs { attribute title { text }?, attribute title_url { IRI }?, attribute description { text }?, attribute author { text }?, attribute author_email { text }?, attribute screenshot { IRI }?, attribute thumbnail { IRI }?, attribute height { text }?, attribute width { text }?, attribute doctype { "quirksmode" | text }, undefinedAttribute*, (Require* & Optional* & Preload* & Icon* & Locale* & Link* & OAuth? & OAuth2?, extensionElement*) } </artwork></figure> <t>The <ModulePrefs> element MAY contain zero or more <Require>, <Optional>, <Preload>, <Icon>, <Locale> and <Link> elements and MAY contain no more than one each of the <OAuth> and <OAuth2> elements.</t> <t>The "title" attribute specifies the gadget's title. If provided, A container SHOULD use this value in any situation where a title bar or other identifying name for the gadget is required.</t> <t>If provided, containers SHOULD use the value of the "title_url" attribute to provide a link target whenever the value of the "title" attribute is displayed.</t> <t>The "description" attribute provides an optional description of the gagdget. If provided, Container's SHOULD use this value to provide a description of the gadget wherever appropriate.</t> <t>The "author" attribute optionally provides the name of the author of the gadget. If provided, Container's SHOULD use this value wherever appropriate.</t> <t>The "author_email" attribute optionally provides the an email address to serve as a point of contact for the author of the gadget. Containers MAY display this value wherever appropriate.</t> <t>The "screenshot" attribute provides an optional IRI of a visual representation of the gadget, for instance, a screenshot. The referenced resource MUST be an image on a publicly-accessible web site that is not blocked by robots.txt. PNG is the preferred format, though GIF and JPG are also acceptable. Gadget screenshots should be 280 pixels wide. The height of the screenshot should be the "natural" height of the gadget when it is in use. Containers SHOULD display this image on wherever appropriate to provide a preview of the gadget to Users.</t> <t>The "thumbnail" attribute provides an optional IRI of a gadget thumbnail. The referenced resource MUST be an image on a publicly-accessible web site that is not blocked by robots.txt. PNG is the preferred format, though GIF and JPG are also acceptable. Gadget thumbnails SHOULD be 120x60 pixels and SHOULD be smaller than images referenced using the "screenshot" attribute but larger than any images linked to using <xref target="Icons">/ModulePrefs/Link/@rel="icon"</xref>elements.</t> <t>The optional "height" and "width" attributes respectively define, in pixes, the preferred default display height and width of the gadget. Container's SHOULD use this value to set the appropriate display dimensions for the gadget.</t> <t>The optional "doctype" attribute is a string that identifies the preferred rendering model for the gadget. When set to "quirksmode", the gadget SHOULD be rendered using the so-called "browser quirks mode". Additional values can be used to support other rendering modes but only "quirksmode" is defined by this specification.</t> </section> <section title="The <Require> and <Optional> Elements"> <t>The <Require> and <Optional> elements share a common structure and are each used to declare OpenSocial features that are either required or optional for the gadget to operate. Element element consists of a feature identifier, a version, a list of specific gadget views the feature dependency applies to, and zero or more <Param> elements that provide specific feature-dependent detail.</t> <figure><artwork> dependency = attribute feature { text }, attribute version { text }, attribute views { text }, undefinedAttribute*, Param*, extensionElement, Optional = element Optional { dependency } Require = element Require { dependency } Param = element Param { attribute name { text }, undefinedAttribute*, text } </artwork></figure> <t>Features are collections of processing instructions and JavaScript Library APIs that provide specific functionality to a gadget. A feature might also place various constraints and rules on the container and gadget when in use. Containers MUST honor the constraints and rules of any feature it claims to support.</t> <t>The "feature" attribute on the <Optiona> and <Require> elements specifies the unique identifier of a feature.</t> <t>The "version" attribute specifies the specific version of the identified feature, using the syntax described in <xref target="Versioning"/>.</t> <t>The "views" attribute specifies a comma separated list of views for which the feature is optional or required. Containers SHOULD only load features when an appropriate view is being rendered.</t> <t>For every feature identified using a <Require> element, the container MUST provide an implementation that matches the version specified by the "version" attribute. The container MUST display an error if it is incapable of providing an appropriate implementation for a required feature.</t> <t>For every feature identified using a <Optional> element, the container MAY provide an implementation of the feature. If an implementation is provided, it MUST match the version specified by the "version" attribute.</t> <t>Containers MUST NOT substitute versions of features that do not match that which is requested by the gadget.</t> <t>Containers SHOULD support as many versions of a feature as is practical to facilitate backwards compatibility with existing gadgets.</t> <t>Containers MAY refuse to support features or specific versions of features that are known or assumed to be incompatible with the specification version required by the Gadget, or that are known to be incompatible with other Features or versions of Features required by the Gadget. For example, a Container MAY not support the combination of @specificationVersion="1.0" and <Require feature="opensocial" version="2.0">, or the combination of <Require feature="opensocial" version="1.0"> and <Require feature="opensocial-data" version="1.1">. In cases where such combinations are requested, the Features are said to be conflicting. Conflicting Features SHOULD be treated by Containers as if they were unsupported. Containers SHOULD provide an error message describing conflicts to Developers when a conflict is detected. If one or more of the conflicting Features is specified as Optional by a Gadget, and the set of Required features and specification version do not conflict, Containers SHOULD attempt to render the Gadget by removing the conflicting optional Features, returning false from <xref target="gadgets.util.hasFeature">gadgets.util.hasFeature</xref> for the features that have been removed. Containers SHOULD include the largest set of Optional Features that does not produce conflicts.</t> <t>It is possible for there to be feature version conflicts when two valid feature dependencies exist for the same feature. This situation can occur when the same feature is declared at a global scope (no @views specified) and at a view scope (@views specified) but with differing @version values. For example, if we are rendering a Gadget's "default" view and with <Require feature="myfeature" version="1"> and <Require feature="myfeature" version="2" views="default"> declared. In such cases, Containers SHOULD use the Feature version from the Feature declaration that explicitly matches the current View (See /ModulePrefs/Required/@views and /ModulePrefs/Optional/@views) over other Feature declarations. Developers can easily correct this conflict by always using the @views attribute for Features in Gadgets that use mixed Feature versions. <xref target="Issue-1133">Discussion</xref></t> <section title="The <Param> Element"> <t>The <Param> element provides configuration details for a feature dependency. When specified, these values will be made available by the container to the gadget developer using the <spanx style="verb">gadgets.util.getFeatureParameters</spanx> API, with the value of the "name" attribute serving as the parameter key and the text value of the element serving as the parameter value.</t> <t>When a feature dependency for a specific view has been defined, the container SHOULD make only the parameters from the view-specific dependency available to the gadget using the getFeatureParameters API.</t> </section> </section> <section title="The <Preload> Element"> <t>The <Preload> element is used to identify resources that a container SHOULD load automatically when the gadget is processed and rendered.</t> <figure><artwork> Preload = element Preload { SignedFetch, attribute href { IRI }, attribute views { text }? } </artwork></figure> <t>The processing semantics of the <Preload> are generally identical to those of those defined for the <spanx style="verb">gadgets.io.makeRequest</spanx> API.</t> <t>The "href" attribute specifies the IRI of the resource to fetch. The value of this attribute matches the "url" parameter of the <spanx style="verb">gadgets.io.makeRequest</spanx> API.</t> <t><Preload> elements MAY use the Signed Fetch mechanism defined by <xref target="SignedFetch"/> and MAY contain the same optional attributes used to configure <Content> elements for signed fetch as described in <xref target="signed-fetch"/>.</t> <t>The "views" attribute provides a comma-separated list of views for which this <Preload> element applies. Containers SHOULD NOT preload resources that are not specified for the view being rendered. If no "views" attribute is specified, then the content SHOULD be preloaded for all views.</t> <t>When processing the <Preload> element, the container MUST sends an HTTP request to the IRI specified by the href attribute. The results of that request MUST be converted into a temporary object that is stored and accessed at runtime via the <spanx style="verb">gadgets.io.makeRequest</spanx> API. The container MUST NOT return a preloaded resource in response to a call to <spanx style="verb">gadgets.io.makeRequest</spanx> unless: <list style="symbols"> <t>The "url" parameter of the makeRequest call matches the value of the <Preload> element's href attribute,</t> <t>The <Preload> element's authz attribute value matches one of the acceptable authorization types,</t> <t>The "sign_owner" parameter of the makeRequest call matches the value of the <Preload> element's sign_owner attribute,</t> <t>The "sign_viewer" parameter of the makeRequest call matches the value of the <Preload> element's sign_viewer attribute, and</t> <t>The views attribute on the <Preload> element is either unspecified or contains the name of the current view.</t> </list> </t> </section> <section title="The <Icon> Element (deprecated)"> <t>The <Link> Element is a currently deprecated mechanism that was used in previous versions of this specification for to provide an image to serve as an icon for the gadget. The definition of the <Link> element is included here for backwards compatibility purposes only and will be permanently removed from future versions of this specification.</t> <figure><artwork> Icon = element Icon { attribute mode { "base64" }?, attribute type { mimeType }?, text } </artwork></figure> <t>Historically, <Icon> element was used in one of two ways: (1) to provide a link via a URL to the image resource or (2) to directly embed the image into the gadget specification using a Base64-encoding of the binary data. The "mode" attribute is used to identify which method is being used. When specified, the value of "mode" MUST be "base64", in which case the text content of the <Icon> element MUST be processed as Base64-encoded binary data. If the "mode" attribute is omitted, the text content of the element MUST be processed as a URL referencing an image document. The "type" attribute is used to specified the MIME media type of the image resource in either case.</t> <figure><preamble>For example, to reference an icon by URL, it would be:</preamble> <artwork><![CDATA[ <Icon type="image/png">http://www.example.org/images/icon.png</Icon> ]]></artwork></figure> <figure><preamble>To embed the icon directly, it would be:</preamble> <artwork><![CDATA[ <Icon mode="base64" type="image/png>{base64 data}</Icon> ]]></artwork></figure> <t>Use of the <Icon> element has been deprecated in the current version of this specification. Gadget developers SHOULD use the <Link> element with a "rel" attribute value equal to "icon" in place of the <Icon> element:</t> <figure><artwork><![CDATA[ <Link href="http://www.example.org/images/icon.png" rel="icon" /> ]]></artwork></figure> </section> <section title="The <Link> Element"> <t>The <Link> element is used to associate a variety of additional resources with the gadget specification. At a minimum, the element MUST contain the "rel" and "href" attributes.</t> <figure><artwork> Link = element Link { attribute rel { text }, attribute href { IRI }, attribute method { "GET" | "POST" }?, undefinedAttribute*, text } </artwork></figure> <t>The "href" attribute specifies the IRI of the resource being linked to the gadget specification. The value MUST be usable for dereferencing and therefore MUST be mapped to a URL following the rules specified in [TODO: RFC 3987].</t> <t>The specific relationship between the gadget specification and the referenced resource is specified by the value of the "rel" attribute. The value of the rel attribute can be any string value. This specification defines a number of rel attribute values that are significant. Implementations MUST NOT use any rel attribute value prefixed with the characters "opensocial", "gadgets", or "events" that are not defined by this specification.</t> <t>The optional "match" attribute can be used with certain links to specify the HTTP method that is to be used when dereferencing the Link href. The "match" attribute is primarily used when working with <xref target="gadget-lifecycle-events">Gadget Lifecycle Events</xref>.</t> <t>The "rel" attribute values currently defined by this specification are:</t> <texttable> <ttcol align="left" width="15%">"rel"</ttcol> <ttcol align="left">Description</ttcol> <c><spanx style="verb">icon</spanx></c> <c>Used to link an image resource to the gadget specification that serves as a representative icon for the gadget.</c> <c><spanx style="verb">event</spanx></c> <c>Used to associate a remote endpoint to which <xref target="gadget-lifecycle-events">Gadget Lifecycle Events</xref> are to be delivered.</c> <c><spanx style="verb">event.addapp</spanx></c> <c>Used to associate a remote endpoint to which <xref target="gadget-lifecycle-events">Gadget Lifecycle Events</xref> matching the "event.addapp" event are to be delivered.</c> <c><spanx style="verb">event.removeapp</spanx></c> <c>Used to associate a remote endpoint to which <xref target="gadget-lifecycle-events">Gadget Lifecycle Events</xref> matching the "event.removeapp" event are to be delivered.</c> <c><spanx style="verb">event.app</spanx></c> <c>Used to associate a remote endpoint to which <xref target="gadget-lifecycle-events">Gadget Lifecycle Events</xref> matching the "event.app" event are are to be delivered.</c> </texttable> </section> <section title="The <Locale> Element"> <t>The <Locale> element is used to provide localization information for a gadget. Containers are required to honor localization rules as specified in <xref target="Localization"> Localization</xref>. Each Locale tag represents localization information for a single locale.</t> <figure><artwork> Msg = element msg { attribute name { text }, undefinedAttribute*, text } Locale = element Locale { attribute lang { "all" | text }?, attribute country { "all" | text }?, attribute messages { IRI }?, attribute language_direction { "rtl" | "ltr" }?, attribute views { text }, undefinedAttribute*, Msg* } </artwork></figure> <t>The "lang" attribute specifies the language for the locale specified as an ISO-639-1 Language Code, or the special value "all", which containers MUST interpret as applying to all languages unless a more specific match is found. If the lang attribute is not specified, the default is considered to be "all".</t> <t>The "country" attribute specifies the country code for the locale specified as an ISO-3166-1 Country code, or the special value "all", which containers MUST interpret as applying to all countries unless a more specific match is found. If the country attribute is not specified, the default is considered to be "all".</t> <t>The optional "language_direction" attribute is used to specify the default text rendering direction for the gadget. Valid values are "ltr", to indicate "Left-to-Right" ordering, or "rtl" to indicate "Right-to-Left" ordering. Directional rendering of text is discussed in detail in <xref target="Localization"/>.</t> <t>The optional "views" attribute specifies a comma-separated list of gadget views for which the Locale information applies. Containers SHOULD only use the information provided by the containing <Locale> element when an appropriate view is being rendered.</t> <t>The optional "messages" attribute specifies the IRI of an XML document conforming to the <xref target="message-bundle-document"> Message Bundle Document</xref> format. The IRI specified MUST be suitable for dereferencing. The container processing the gadget specification MUST fetch the referenced resource and treat all child elements of the root XML element in the document as though they are child nodes of the containing <Locale> element.</t> <t>The <Locale> element MAY contain zero or more <msg> elements, each of which provide a singular localized value. The key used to identify the value is specified using the "name" attribute. The text content of the <msg> element provides the localized value.</t> <figure><preamble>An example <Locale> that uses a referenced Message Bundle Document:</preamble><artwork><![CDATA[ <Locale language="en" country="US" messages="http://example.org/i18n/en/messages.xml" /> ]]></artwork></figure> <figure><preamble>An example <Locale> that uses contained <msg> elements:</preamble><artwork><![CDATA[ <Locale language="en" country="US"> <msg name="foo">This is the American English Version</msg> <msg name="bar">Hello From My Gadget</msg> </Locale> ]]></artwork></figure> </section> <section title="The <OAuth> Element"> <t>The <OAuth> element supplies the container with OAuth 1.0 specific configuration details for the gadget. For details see <xref target="OAuth"/>.</t> <figure><artwork> OAuth = element OAuth { undefinedAttribute*, Service*, extensionElement* } </artwork></figure> <t>The <OAuth> element contains zero or more <Service> elements, each of which detail a specific OAuth 1.0 service associated with the gadget.</t> <figure><artwork> Service = element Service { attribute name { text }?, undefinedAttribute*, element Request { OAuthResourceType }?, element Access { OAuthResourceType }?, element Authorization { attribute url { IRI }, undefinedAttribute*, extensionElement* }? } OAuthResourceType = { attribute url { IRI }, attribute method { "GET" | "POST" }?, attribute param_location { "auth-header" | "uri-query" | "post-body" }?, extensionElement* } </artwork></figure> <t>The optional "name" attribute on the <Service> element specifies a name used to reference the service at runtime. If unspecified, the value is assumed to be an empty string. Gadget developers specify which OAuth Service they wish to use by passing the service name as a parameter to the <spanx style="verb">gadgets.io.makeRequest</spanx> API.</t> <t>The child elements of the <Service> element consist of the <Request>, <Access> and <Authorization> elements, each of which are optional but MUST NOT appear more than once within a single <Service> element.</t> <t>The <Request> element identifies the endpoint for acquiring OAuth request tokens. The "url" attribute specifies the IRI of the endpoint. This IRI MUST be suitable for dereferencing. The "method" attribute specifies the HTTP verb to use when sending the request, valid values are either "GET" or "POST". If not specified, the value is assumed to be "POST". The "param_location" attributes specifies how OAuth parameters are to be passed in the request. Valid options are either "uri-query", "auth-header", and "post-body", corresponding to the options described in <xref target="OAuth-Core">Section 5.2 of the OAuth specification</xref>. If not specified, the value is assumed to be "auth-header".</t> <t>The <Access> element identifies the endpoint for acquiring OAuth access tokens. The <Access> element shares the same attribute definitions as the <Request> element.</t> <t>The <Authorization> element is used to acquire authorization. The "url" attribute specifies the IRI of the endpoint. This IRI MUST be suitable for dereferencing. For details, refer to <xref target="OAuth-Core">Section 6.2 of the OAuth specification.</xref></t> </section> <section title="The <OAuth2> Element"> <t>The <OAuth2> element supplies the container with OAuth 2.0 specific configuration details for the gadget. For details see <xref target="OAuth"/>.</t> <figure><artwork> OAuth2 = element OAuth2 { undefinedAttribute*, Service*, extensionElement* } </artwork></figure> <t>The <OAuth2> element contains zero or more <Service> elements, each of which detail a specific OAuth 2.0 service associated with the gadget.</t> <figure><artwork> Service = element Service { attribute name { text }?, attribute scope { text }?, undefinedAttribute*, element Authorization { attribute url { IRI }, attribute method { "GET" | "POST" }?, undefinedAttribute*, extensionElement* }?, element Token { attribute url {IRI}, undefinedAttribute* }? } </artwork></figure> <t>The optional "name" attribute on the <Service> element specifies a name used to reference the service at runtime. If unspecified, the value is assumed to be an empty string. Gadget developers specify which OAuth Service they wish to use by passing the service name as a parameter to the <spanx style="verb">gadgets.io.makeRequest</spanx> API.</t> <t>OAuth2 Service elements MAY also specify an optional "scope" attribute providing the scope used by default in all requests. Access Token Scope is defined in Section 3.3 of the <xref target="OAuth2-Core">OAuth 2.0 specification.</xref></t> <t>The child elements of the <Service> element consist of the <Authorization>, <Token> elements, each of which are optional but MUST NOT appear more than once within a single <Service> element.</t> <t>The <Authorization> element identifies the endpoint for acquiring OAuth authorization tokens. The "url" attribute specifies the IRI of the endpoint. This IRI MUST be suitable for dereferencing. The "method" attribute specifies the HTTP verb to use when sending the request, valid values are either "GET" or "POST". If not specified, the value is assumed to be "GET".</t> <t>The <Token> element is used to acquire OAuth 2.0 access tokens. The "url" attribute specifies the IRI of the endpoint. This IRI MUST be suitable for dereferencing. For details, refer to <xref target="OAuth2-Core">Section 3.2 of the OAuth 2.0 specification.</xref></t> </section> <section title="The <UserPref> Element"> <t>The <UserPref> element is used within a gadget specification to define a "user preference" for use within instances of the gadget. Each instance of the <UserPref> element defines exactly one preference value. Multiple <UserPref> elements MAY be used within a gadget specification.</t> <t>Containers MUST process each <UserPref> by making each available to the gadget via the <spanx style="verb">gadgets.Prefs</spanx> API, using the value of <UserPref> element's required "name" attribute as the index key for storing and retrieving preferences using the API.</t> <figure><artwork> BaseUserPref = { attribute name { text }, attribute display_name { text }?, attribute default_value { text }?, attribute required { "true" | "false" }?, undefinedAttribute*, extensionElement* } SimpleUserPref = element UserPref { BaseUserPref, attribute datatype { "string" | "hidden" | "bool" | "list" | "number" }? } EnumUserPref = element UserPref { BaseUserPref, attribute datatype { "enum" }, element EnumValue { attribute value { text }, attribute display_value { text }?, undefinedAttribute*, extensionElement* }*, extensionElement* } EnumPref = element SimpleUserPref | EnumUserPref </artwork></figure> <t>The "datatype" attribute specifies the data type for the instances of the preference value at runtime. Valid values are "string", "hidden", "bool", "list" and "number". If not specified, the value is assumed to be "string". For more information on "datatype", refer to <xref target="datatypes-values"/> below.</t> <t>The "display_name" attribute specifies a preferred display name for the preference. The value SHOULD be localized as described in <xref target="Localization" />.</t> <t>The "default_value" attribute specifies the default value for instances of the preference. The value of the attribute depends on the value of the "datatype" attribute. Container's MUST provide the value of the "default_value" attribute as the value of the preference when using the <spanx style="verb">gadgets.Prefs</spanx> API and a stored value for the preference does not yet exist.</t> <t>The "required" attribute specifies whether instances of the preference require a valid value in order for the gadget to function correctly. Valid values are "true" and "false". If not specified, the value is assumed to be "false". If the value is "true", Containers SHOULD display an error message or a prompt if there is no value stored.</t> <section title="User Preference Data Types"> <t>The default data type for all user preference values is "string", represented either by omitting the "datatype" attribute on the <UserPref> element or by explicitly specifying <spanx style="verb">datatype="string"</spanx>. When datatype is "string", The value of the "default_value" attribute and the stored value of the user preference at runtime MUST be a string.</t> <figure><preamble>An example "string" preference:</preamble> <artwork><![CDATA[ <UserPref name="foo" datatype="string" default_value="foo" display_name="Foo" required="true" /> ]]></artwork></figure> <t>When datatype equals "number", the value of the "default_value" attribute and the stored value of the user preference at runtime MUST be a numeric value.</t> <figure><preamble>An example "number" preference:</preamble> <artwork><![CDATA[ <UserPref name="foo" datatype="number" default_value="123" display_name="Foo" required="true" /> ]]></artwork></figure> <t>When datatype equals "bool", the value of the "default_value" attribute and the stored value of the user preference MUST evaluate to "true" or "false" when accessed via the <spanx style="verb">gadgets.Prefs.getBool</spanx> API.</t> <figure><preamble>An example "bool" preference:</preamble> <artwork><![CDATA[ <UserPref name="foo" datatype="bool" default_value="true" display_name="Foo" required="true" /> ]]></artwork></figure> <t>When datatype equals "list", the value of the "default_value" attribute and the stored value of the user preference MUST be a pipe-delimited (|) string of values, returned as a JavaScript array when accessed via the <spanx style="verb">gadgets.Prefs.getArray</spanx> API.</t> <figure><preamble>An example "list" preference:</preamble> <artwork><![CDATA[ <UserPref name="foo" datatype="list" default_value="foo|bar|baz" display_name="Foo" required="true" /> ]]></artwork></figure> <t>When datatype equals "hidden", the value of the "default_value" attribute and the stored value of the user preference MUST be a string. The difference between "hidden" and "string" is that "hidden" user preferences are not visible and are not editable by users by can be accessible via the <spanx style="verb">gadgets.Prefs.getString</spanx> API.</t> <figure><preamble>An example "hidden" preference:</preamble> <artwork><![CDATA[ <UserPref name="foo" datatype="hidden" default_value="foo" display_name="Foo" required="true" /> ]]></artwork></figure> <t>When datatype equals "enum", the <UserPref> element SHOULD contain one or more <EnumValue> elements, each of which define a single possible value for the preference. Each <EnumValue> element contains a required "value" attribute that specifies a string value, and an optional "display_value" attribute that specifies a textual representation of the "value". If unspecified, the "display_value" defaults to the "value". Containers SHOULD display the "display_value" in place of "value" when rendering a user interface for editing purposes. The value of the "default_value" attribute and the stored value of the user preference MUST equal one of the supplied <EnumValue> "value" attributes.</t> <figure><preamble>An example "enum" preference:</preamble> <artwork><![CDATA[ <UserPref name="foo" datatype="string" default_value="foo" display_name="Foo" required="true"> <EnumValue value="foo" display_value="Foo" /> <EnumValue value="bar" display_value="Bar" /> <EnumValue value="baz" display_value="Baz" /> </UserPref> ]]></artwork></figure> </section> </section> <section title="The <Data> Element"> <t>The <Data> element contains data pineline elements as defined by <xref target="DataPipelining"/>. All data pipeline elements defined in this block are registered globlly for all views by default. Individual data pipeline elements MAY be specified for particular views by adding the "view" attribute to the tag.</t> <t>See <xref target="DataPipelining"/> for complete information on the data pipelining mechanism and element definitions.</t> </section> <section title="The <ExternalServices> Element"> <t>The <ExternalServices> element contains zero or more <ServiceTag> elements used to establish an "alias" for container-managed external services utilized by the gadget.</t> <figure><artwork> ExternalServices = element ExternalServices { undefinedAttribute*, element ServiceTag { attribute alias { text }, text }* } </artwork></figure> <t>The <ServiceTag> element has a single "alias" attribute whose value is a string and textual content that provides a gadget-specific plain-text label for the alias. Additional markup within the <ServiceTag> is not allowed.</t> <t>Currently, when making a remote request from within a gadget using either the <spanx style="verb">OSAPI</spanx> or <spanx style="verb">gadgets.io.makeRequest</spanx> APIs, the full URL of the remote service that is being invoked must be known to the gadget and specified within the request, along with all other details of the request. Often, however, it is desirable to offload the responsibility of managing access to external services to the container, for instance, when multiple services are available that implement the same protocol and it would be difficult for a single gadget to keep track of all instances; or when a potentially untrusted gadget needs to be given access to secure backend systems. In such cases, a container can choose to manage all of the details involved with connecting to and communicating with the service and expose that service to the gadget via an "alias".</t> <t>Once an alias for a service is established, a gadget specification can use the <ServiceTag> element within <ExternalServices> to declare a gadget-specific reference label for the alias that can be used when invoking the <spanx style="verb">OSAPI</spanx> or <spanx style="verb">gadgets.io.makeRequest</spanx> APIs in place of the URL.</t> <t>For example, suppose that a gadget requires access to a backend enterprise application that implements a proprietary communications protocol. Software is added to the container that allows it to communicate with the backend system. All of the details including the URL, authentication details, authorization, and so forth are configured within the container by an administrator and an alias is assigned to the service: "opensocial:service://example.com/api?version=1".</t> <t>The gadget developer then creates the gadget specification and adds a <ServiceTag> element referencing the alias and created a lobel for the alias that can be used within the gadget's Javascript:</t> <figure><artwork><![CDATA[ <Module> ... <ExternalServices> <ServiceTag alias="opensocial:service://example.com/api?version=1"> EnterpriseService </ServiceTag> </ExternalServices> <Content> ... <script> ... var params = { 'alias' : 'EnterpriseService', 'href' : '/files', 'format': 'json', }; osapi.http.get(params).execute( function(result) { ... } ); ... </script> ... </Content> </Module> ]]></artwork></figure> <t>When the gadget is installed, the container will attempt to match the alias specified in the <ServiceTag> to any known configured services -- in this case, our backend enterprise service -- and will automatically proxy all gadget requests to the "EnterpriseService" label to the backend service.</t> <t>It is possible for multiple service instances managed by a single container to share the same alias; for instance, when there are multiple servers available that implement the same communication protocols. In such cases, when the gadget is installed, the container can either automatically select an appropriate service instance to map the <ServiceTag> to or provide a choice to the user installing the gadget to select which service instance to use.</t> <t>If a <ServiceTag> specifies an alias that is not currently known to the container, installation of the gadget SHOULD fail and an error reported.</t> </section> <section title="The <Content> Element"> <t>The <Content> element provides the user interface and runtime code for the gadget. A gadget specification MUST have at least one <Content> element.</t> <figure><artwork> CommonContent = { attribute preferred_height { text }?, attribute preferred_width { text }?, attribute view { text }?, undefinedAttribute* } UrlContent = element Content { CommonContent, SignedFetch, attribute type { "url" }, attribute href ( IRI ), extensionElement* } ProxiedContent = element Content { CommonContent, SignedFetch, attribute type { "html" }?, attribute href { IRI }, extensionElement* } HtmlContent = element Content { CommonContent, attribute type { "html" }?, text } Content = UrlContent | HtmlContent | ProxiedContent </artwork></figure> <t>The required "type" attribute specifies the type of content provided by the <Content> element. Valid values are either "html" or "url". Containers MUST process the <Content> element according to the specific rules for each type.</t> <t>The <Content> element MUST conform to the following rules:</t> <list style="numbers"> <t>If the value of "type" is "html" and the "href" attribute is specified, the content of <Content> MAY contain one or more Data Pipeline elements as defined in <xref target="DataPipelining"/>. The <Content> element MAY also contain any combination of the "Signed Fetch" attributes defined by <xref target="signed-fetch" />.</t> <t>If the value of "type" is "html", and the "href" attribute is not specified, the content of <Content> MUST NOT contain child elements and SHOULD be suitable for handling as HTML [TODO: HTML]. The HTML markup SHOULD be wrapped within a CDATA tag otherwise it MUST be escaped in order to prevent the HTML from being interpreted by the XML parser; for example, "<br>" as "&lt;br>".</t> <t>If the value of "type" is "url", the <Content> element MUST contain the "href" attribute and MUST NOT contain child elements or text. Containers SHOULD ignore any elements or text contained within the <Content>. The element MAY contain any combination of the "Signed Fetch" attributes defined by <xref taret="signed-fetch"/>.</t> <t>Any <Content> element MAY contain "preferred_height" and " preferred_width" attributes that specify the preferred dimensions, in pixels, the container SHOULD use when rendering the content.</t> <t>Any <Content< element MAY contain a "views" attribute that specifies a comma-separated list of views. A single gadget can support multiple views. Each view is associated with at least one <Content> element. When the container renders a gadget with multiple <Content> elements, it will use the view name to select the appropriate content.</t> </list> <t>When a <Content> element uses the "href" attribute, the view names listed in it's views attribute MUST NOT be used in any other <Content> element. A single view name MAY appear within multiple <Content> elements that specify a "type" attribute value of "html" and do not include an "href" attribute. How multiple <Content> elements sharing the same view name are processed to provide the rendered content for a view is defined in <xref target="content-processing-model"/>.</t> <t><Content> elements that do not specify a "views" attribute are considered, by default, to be associated with the "default" view.</t> <section title="Processing Model" anchor="content-processing-model"> <t>Containers MUST conform to the following rules when rendering a gadget view.</t> <section title="HTML Content"> <figure><preamble>The simplest form of content provided by a gadget is HTML associated with the "default" view:</preamble><artwork> <Content type="html"><![CDATA[ <div>Hello World!</div> ]]></Content> </artwork></figure> <figure><preamble>The same example can be provided by explicitly naming the default view in the element's views attribute:</preamble><artwork> <Content type="html" views="default"><![CDATA[ <div>Hello World!</div> ]]></Content> </artwork></figure> <t>When the container renders the "default" view for the gadget, it will select this <Content> element and display the HTML "<div>Hello World!</div>" to the user.</t> <t>If a gadget provides multiple "html" <Content> elements that specify the same view, the content is concatenated together when rendered in the order those <Content> elements appear within the gadget specification:</t> <figure><preamble>For instance, given two "html" Content elements for the "default" view:</preamble><artwork> <Content type="html"><![CDATA[ <div>Hello World!</div> ]]></Content> <Content type="html" views="default,greeting"><![CDATA[ <div>How are you?</div> ]]></Content> </artwork></figure> <figure><preamble>When rendering the default view, the container would generate the following:</preamble><artwork> <div>Hello World!</div> <div>How are you?</div> </artwork></figure> <figure><preamble>However, when rendering the "greeting" view, the container would only select the <Content> element that lists the "greeting" view:</preamble><artwork> <div>How are you?</div> </artwork></figure> <t>Once the HTML content for a view has been assembled from the appropriate <Content> elements, the container MUST perform Variable Substitution on the resulting content as defined by <xref target="variable-substitution"/>.</t> </section> <section title="Proxied Content"> <t>As an alternative to including HTML markup directly within the gadget specification, a <Content> element that uses type="html" MAY reference an external resource containing HTML markup using the "href" attribute. When the gadget is rendered, the container will fetch the external resource and process it's HTML content as if it were included directly within the <Content> element. This is commonly referred to as "Proxied Content".</t> <figure><preamble>An example of proxied content associated with the "default" view:</preamble><artwork> <Content type="html" href="http://example.org/hello.html"/> </artwork></figure> <t>When rendering the "default" view for a gadget containing the above <Content> element, the container will issue an HTTP request to the address provided by the "href" attribute to retrieve the content.</t> <t>The container MUST add the following additional query string parameters to the address provided by the "href" attribute: <list style="hanging"> <t hangText="lang">The preferred language of the user for which the content is being rendered, specified as an ISO-639-1 language code.</t> <t hangText="country">The country of the user for which the content is being rendered, specified as an ISO-3166-1 country code.</t> <t hangText="opensocial_proxied_content">MUST be specified using the value "1". Servers can use this to identify proxied content renders from other types of requests.</t> </list> </t> <t>When the remote service returns the HTML content back to the container, the container will continue to process it as if the HTML had been directly included within the gadget specification.</t> <t>Note that, whereas multiple HTML Content elements MAY share a common view name, the view names associated with Proxied Content MUST be unique to that <Content> element, therefore making concatentation unnecessary. The container MUST, however, still perform Variable Substitution on the returned HTML content.</t> <t>If the response to the proxied request returns a successful HTTP status code, the container MUST interpret the resulting response body according to the rules for content declared inline.</t> <t>If the response to the proxied request returns an unsuccessful HTTP status code, the container SHOULD present a meaningful error message to the end user. Containers SHOULD obtain a suitable error message for display by displaying the content specified for a view named as "{view-name}.error", where {view-name} matches the name of the view that the proxied request was being processed for. If an exact match can not be found, the special view name "default.error" should be used. If content for the "default.error" is not present, the container SHOULD display a generic message indicating that a problem occurred.</t> <figure><preamble>For instance, A Proxied Content for the "greeting" view with a specific "greeting.error" view to display error responses:</preamble><artwork> <Content type="html" href="http://example.org/hello.html" views="greeting"/> <Content type="html" views="greeting.error"> There was an error retrieving the greeting content. </Content> </artwork></figure> <figure><preamble>An alternative Proxied Content for the "greeting" view that uses the "default.error" view to display error responses:</preamble><artwork> <Content type="html" href="http://example.org/hello.html" views="greeting"/> <Content type="html" views="default.error"> There was an error retrieving the content. </Content> </artwork></figure> <t>Containers SHOULD cache the results of the HTTP request following the recommendations of Section 13 of <xref target="RFC2616"/>. If a container does support caching of data, it MUST also support using the "refresh_interval" parameter to override the default caching directives. TODO: How does that work?</t> <t>TODO: Discuss the cache key requirements... the ones that are in the spec currently need to be clarified.</t> <t>TODO: Discuss Pipelined content</t> </section> <section title="Redirected Content"> <t>When using Proxied Content, the container is responsible for sending the HTTP request to the remote server and processing the content while the gadget is being rendered. Alternatively, by using type="url" within the <Content> element, the container can be instructed to provide a "direct view" of the content retrieved from the remote source without additional processing. When the gadget is being rendered for display within a Web Browser, this can be achieved by using an HTML IFrame whose src attribute is set to the value of the <Content> element's href attribute. This is commonly referred to as "Redirected Content".</t> <figure><preamble>An example of redirected content associated with the "default" view:</preamble><artwork> <Content type="type" href="http://example.org/hello.html"/> </artwork></figure> <t>When rendering the "default" view for a gadget containing the above <Content> element, the container will issue an HTTP request to the address provided by the "href" attribute to retrieve the content and will display that to the user exactly as it is returned from the server without any further processing.</t> <t>The container MUST add the following additional query string parameters to the address provided by the "href" attribute: <list style="hanging"> <t hangText="lang">The preferred language of the user for which the content is being rendered, specified as an ISO-639-1 language code.</t> <t hangText="country">The country of the user for which the content is being rendered, specified as an ISO-3166-1 country code.</t> <t hangText="libs">A relative URL reference that points to any JavaScript resources necessary to satisfy the optional or required features listed within the gadget specifications <ModulePrefs>. TODO: this needs more explanation</t> </list> </t> <figure><preamble>When rendering the default view for a gadget containing the above Redirected Content element, the container would generate the following:</preamble><artwork> ... >iframe src="http://example.org/hello.html?language=en&country=US&libs=????" ... </artwork></figure> <t>Like Proxied Content, view names associated with Redirected Content MUST not be shared with any other <Content> elements making concatenation unnecessary. Additionally, because Redirected Content is rendered exactly as it is provided by the remote service, Variable Substitution is not required. </t> </section> <section title="Authentication for Proxied and Redirected Content" anchor="signed-fetch"> <t>For Proxied and Redirected Content (as well as the <Preload> element) the Signed Fetch mechanism described in <xref target="SignedFetch"/> MAY be used to specify the type of authentication used in the request sent to the remote service.</t> <figure><preamble>The Signed Fetch attributes defined below MAY be used on any Proxied and Redirected Content elements:</preamble><artwork> NoAuth = { attribute authz { "none" }? } AuthCommon = { attribute refresh_interval { text }?, attribute sign_owner { "true" | "false" }?, attribute sign_viewer { "true" | "false" }? } OAuth1 = { AuthCommon, attribute authz { "oauth" }, attribute oauth_received_callback { text }?, attribute oauth_request_token { text }?, attribute oauth_request_token_secret { text }?, attribute oauth_service_name { text }?, attribute oauth_token_name { text }?, } OAuth2 = { AuthCommon, attribute authz { "oauth2" }, attribute oauth_received_callback { text }?, attribute oauth_request_token { text }?, attribute oauth_request_token_secret { text }?, attribute oauth_service_name { text }?, attribute oauth2_scope { text }?, attribute oauth_token_name { text }?, } SignedAuth = { AuthCommon, attribute authz { "signed" }, } SignedFetch = NoAuth | OAuth1 | OAuth 2 | SignedAuth </artwork></figure> <t>The "authz" attribute identifies the authentication type used when submitting the request to fetch the resource. The valid values are "none", "oauth", "oauth2" or "signed" and each correspond to the values and meanings defined for the <spanx style="verb">gadgets.io.AuthorizationType</spanx> API. When not specified, the default is assumed to be "none" indicating that authentication is to be used.</t> <t>When "authz" is equal to "oauth", requests sent to the remote service MUST be authenticated using the OAuth 1.0 protocol.</t> <t>When "authz" is equal to "oauth2", requests sent to the remote service MUST be authenticated using the OAuth 2.0 protocol.</t> <t>When "authz" is either "oauth" or "oauth2", the following additional optional attributes MAY be included as defined by <xref target="OAuth"/>: <list style="symbols"> <t>oauth_received_callback</t> <t>oauth_received_callback</t> <t>oauth_request_token</t> <t>oauth_request_token_secret</t> <t>oauth_service_name</t> <t>oauth2_scope</t> <t>oauth_token_name</t> </list> </t> <t>When "authz" is equal to "signed", the "Signed Fetch" mechanism described by <xref target="SignedFetch"/> is to be used.</t> <t>The "sign_owner" attribute indicates whether the identity of the gadget "OWNER" needs be included in the request sent to fetch the resource. If the value of this attribute is "true", the container MUST include the identity of the gadget "OWNER".</t> <t>The "sign_viewer" attribute indicates whether the identity of the current gadget "VIEWER" needs to be included in the request sent to fetch the resource. If the value of this attribute is "true", the container MUST include the identity of the gadget "VIEWER".</t> <t>TODO: Define refresh_interval.. currently it's role in signed fetch is undefined</t> </section> </section> </section> </section> <!-- END DOCUMENT STRUCTURE -->
, multiple selections available,