Skip to content

Latest commit

 

History

History
233 lines (181 loc) · 10.6 KB

development.md

File metadata and controls

233 lines (181 loc) · 10.6 KB

This guide is intended to teach you the basics of developing a Privly injectable application.

Quick Start

If you are developing these applications, the easiest way to begin is to clone the Google Chrome Extension or Mozilla Firefox Extension and hack on the privly-applications directory. That directory has the privly-applications repository included as a git module. You can also setup a development environment for the Rails-based content server if you like, but it would be faster if you asked for a development account on dev.privly.org.

For experimentation, we recommend changing the code found in the PlainPost directory. Please note that PlainPost is intentionally left simple to make hacking easier.

For more information on how injectable apps are structured, please read below.

Templating

When developing Privly applications, you can either edit one of the existing applications directly, or modify their .subtemplate files. If you use the templating system, you should look at the build.py script for details.

Directory Structure

The applications are all in their own directory. The directory is determined by the name of the application, for instance, the PlainPost app is in the PlainPost directory. The required directory structure is:

ApplicationName/
                show.html
                new.html
shared/
       css/
           common.css
           tooltip.css
           injected/injected.css
           top/top.css
       images/ajax-loader.gif
       javascripts/
                   parameters.js
                   host_page_integration.js
                   extension_integration.js
                   network_service.js
                   tooltip.js
                   meta_loader.js
vendor/
       jquery.min.js
       markdown.js
       jasmine/
       jquery.dataTables.min.js
       bootstrap/

The pages may reference any contentApps must expose at least the following two pages within their application's directory:

  • show: The application expects to be associated with pre-existing data found in the URL referencing it.
  • new: The application is being used to generate a new URL that will likely be shared across the web.

Several JavaScripts are required to ease integration issues and are guaranteed to be present in the shared directory. Other scripts are optional and are provided to make certain tasks easier.

  • parameters.js: Grabs the parameters found on both the query string and the anchor of the link.
  • host_page_integration.js: (required) Interfaces the application with the host page. This is primarily used to resize the height of the application when it is viewed in the context of other web applications.
  • network_service.js: Facilitates same-origin requests when served from an extension or application that permits it. This is generally not used when the application is hosted by the user's content server.
  • tooltip.js: (required) Defines a tooltip that gives application metadata when it is injected into a host page. For the tooltip JavaScript to work, you must also include the tooltip.css in every injectable page.
  • extension_integration.js: (required) Defines functions for integrating with extension platforms. This is primarily used for sending hyperlinks to extensions for their posting to host pages.
  • meta_loader.js: "show.html" may be shown injected into a page, or as a normal top level web page. The meta loader checks for special meta tags defining CSS for specific contexts, which will be loaded dynamically. For more information, see the JavaScript file's source.
  • jquery.min.js: Jquery gives better cross-browser support for a number of operations. Try to live without it if you can, since it can create more overhead for your application than is necessary. If you don't know what jquery is, then you probably are going to have difficulty developing an application.
  • markdown.js: Converts markdown text to HTML. This is primarily used for previewing content typed in markdown.
  • jasmine/: Jasmine is a JavaScript testing library. See testing.
  • jquery.dataTables.min.js: Datatables provides a table view rendered in JavaScript that is searchable.
  • bootstrap/: Bootstrap provides mobile-responsive layout.

The shared CSS folder also has some recommended CSS for apps. The top and injected folders contain stylesheets which should only be applied when the page is viewed as the top application or an injected application, respectably.

Connecting to Data Storage

While the application can have a URL that points to a particular server, the application might not be served from the domain in the URL. Platforms serving the applications must allow the application to make appropriate same-origin requests. You can assume same-origin access for all "get" requests when creating a new link, but the way requests are handled when reading existing content is a bit more complicated.

  • "Get" requests are universally permitted
  • All other request types should make an effort to verify that the content server's data will not be mangled by interacting with your application. This can be most easily accomplished by storing a string in JSON data that specifies the list of supported applications.

You should use the network_service.js JavaScript library to make all requests to the remote server since it simplifies requests on several architectures.

Several of the cases are discussed below:

"Hosted" Apps

If a user does not have a local version of the application in a browser extension or on a mobile app, then they will click on the link and be taken to the content's storage provider. If the application does not support hosted operation (maybe it doesn't trust the server), then it should display an error message. Otherwise, the hosted content server should provide fallback operation, which is possible with clever use of cross-domain requests.

Extension Apps

Many platforms allow the developer to make same-origin requests to a content server. Your application should put in place proper precautions to prevent a URL attack. For instance, when an extension injects an application into the context of a social network, the URL may be tied to a server which does not expect your application's requests. This is a potentially potent attack similar to cross site scripting. You can mitigate it by requiring the content server to affirm its support for your injectable application in the initial get request. The best way to do this is to have data in the get request's response that affirms app support.

Mobile Apps

Mobile applications use an authentication token (essentially an API secret token) to gain access to the user's account. This is all handled by the network_service.js file without you needing to worry about it. Keep in mind that if you need an authentication scheme, you will need to support the auth_token or implement the auth scheme inside the injectable application.

Integration

The applications must communicate with a variety of platforms and must support both posting new content (link creation) and reading existing content (injected into a host page and served from a content server).

Posting a New Link

An application that is creating a new link should display the link in the UI when the posting process is complete, as well as fire the event found in this specification. Firing the event will cause browser extensions to close the application and automatically paste the link into a host page.

Since the application may be served from a location other than the server hosting its data, extensions and mobile apps give the application a parameter specifying the target domain. This is all handled by network_service.js for you.

Make sure the html file is named "new.html." All other functionality for this posting application is up to the developer.

Reading a Link Discovered on the Web

When viewing an existing application (ie after it has been posted to a host page like a webmail provider) then it could be viewed in several different contexts. We are making efforts to abstract away the differences in platforms using the shared JavaScript files, but you should take note of a few unique aspects of the different platforms.

Make sure the html file is named "show.html." All other functionality for this posting application is up to the developer.

Injected Viewing

Determining whether the App was Injected

The injected view is triggered whenever the application sees that it is not the top window. This can be evaluated with this statement:

window.self === window.top

When this statement evaluates to true, then the current window (self) is the top window and it is not in an iframe. Conversely, if it evaluates to false, the application is being displayed in an iframe. There is a helper in host_page_integration.js that makes this easier.

Setting the Height of the iframe

The iframe is protected by what is known as the same origin policy. This means the host page only knows what your application tells it. Since the host page controls the height of your application, you must message it the height of the app. There are helpers for doing this in host_page_integration.js. Call either:

privlyHostPage.dispatchResize(height) to resize to a specified height, or

privlyHostPage.resizeToWrapper() to resize to the current height of the application. (note: for this function to work, you must have a div surrounding the content with the id privlyHeightWrapper, this allows JavaScript to get an accurate representation of the height of the content)

Layout

Now that you know your app is injected, you should take steps to ensure that the layout is non-intrusive to the host page in which it is contained. This currently means that you should not display much formatting, because there is no way to know what your surrounding context looks like.

Top View

Either an extension or a hosted server could serve the application as the top window when reading the content. This is where you have full control of the application's environment, and need not worry about the strange integration cases outlined above.

Platform Specific README

Several platforms have their own readme with platform specific details. Make sure you check those out if you are developing on the corresponding platform.