Parser 2011/Hackpad/Spec

From MediaWiki.org
Jump to navigation Jump to search

Future/Hackpad/Spec Future/Hackpad/Spec

Rough plan for getting HackPad to work as an editor within MediaWiki[edit]

It is assumed that at least for the initial stages of this hack, HackPad will host the editing session. Wikimedia recently pushed some crossdomain functionality but we may also want to try this on local or other non-Wikimedia wikis. So we'll do the iframe-in-iframe hack.

Window[edit]

A gadget will be created, with JS loaded from either Hackpad or Wikimedia, which will do this:

  • Add a button to the interface to edit with HackPad (similar to WYSIFTW).
    • This button will: create Iframe 1, passing the following parameters:
      • username
      • URL of iframe 2
      • article title
      • article text
  • Talk to HackPad, see if any session exists for this article
    • join a session on HackPad if it already exists.

Iframe 1 (Hackpad) -- Editor to edit article[edit]

  • Receives article text, article title, username, URL of iframe 2
  • creates sessionid (MD5 of article title + username + URL of iframe 2) ?
  • Checks if session exists
  • If exists, and user is logged in from elsewhere, kick them out or otherwise resolve problem
  • If does not exist, create session
  • join session, with this user as username
    • N.b. Session cannot just have the public URL with the Wikimedia title in case there are collisions. Use title + user, like "NeilK's editing session for "
  • Send editing interface to browser, also including Iframe 2


Iframe 2 (Wikimedia) -- API to submit article[edit]

A JS object must be made available which can:

  • Post the article text to Wikipedia
    • Fetch edit token
    • Post article (using a normal form-style POST, replacing entire page) to Wikipedia
    • Any conflicts, etc, handled in the usual way.

postMessage API[edit]

Rather than a second iframe, I'd recommend simply sending a message back to the parent window from the first iframe. I've used this technique in Extension:SVGEdit which embeds an svg-edit iframe from an (optionally) separate domain and uses an embedding API wrapped around postMessage. The parent window and the iframe can send strings (and thus JSON-serializable data structures) back and forth to each other, allowing the parent frame to inject initial data, request modified data at save time, etc. svg-edit turned out to have wrapper functions for the postMessage-based API that I could use, but I also tried it manually and it's not super hard. --brion 18:33, 5 May 2011 (UTC)

The host window and the embedded iframe can send string-based messages to each other through the postMessage interface, supported by all current major browsers (in some cases with slight variations).

This is an asynchronous interface, but is entirely client-side: no new server-side APIs need to be created or used, as long as the JavaScript on each end can communicate with its own APIs.

Messages should always be validated:

  • confirm that the sender is from the expected party (either window.parent if you're the iframe or the iframe or iframe.innerDocument if you're the window)
  • confirm that the string can be safely parsed as JSON (DO NOT use eval(), especially before validating the sender!)
  • confirm that the JSON structure format is as expected
  • don't forget that other legitimate code could be added in future piggybacking on the same channel, so ignore messages you don't understand without canceling the event

A common way to format messages is to prefix a JSON structure with a key string to disambiguate protocols:

 "HackpadEmbed|{action:'ping'}"

Iframe sends a 'ready' ping to host window telling that it's ready to work (is this needed?):

 {
   "action": "ready"
 }

Window sends the iframe initial data, setting up the session and seeding the current text:

 {
   "action": "init",
   "id": "87126387687423",
   "session": {
     "title": "Brion's editing session",
     "user": "Brion VIBBER",
   },
   "wiki": {
     "title": "Future/Hackpad/Spec",
     "revid": 12345678,
     "content": "Bla bla bla bla"
   }

The iframe can respond with a confirmation when it's ready, using the message id to associate the response.

...later, window decides it's time to save the session, and requests the current text:

 {
   "action": "getText",
   "id": "7643876284736"
 }

Iframe sends back the current text, using the message id to let it associate the response:

 {
   "response": "7643876284736",
   "content": "Bla bla bla bla 2"
 }

Parent window is now free to save the content and close everything out.

Might need/want a way to close out / garbage collect a session that's no longer in use.