• Stars
    star
    150
  • Rank 247,323 (Top 5 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A message bus that operates across iframes

Framebus Build Status Build Status npm version

Framebus allows you to easily send messages across frames (and iframes) with a simple bus.

In one frame:

var Framebus = require("framebus");
var bus = new Framebus();

bus.emit("message", {
  from: "Ron",
  contents: "they named it...San Diago",
});

In another frame:

var Framebus = require("framebus");
var bus = new Framebus();

bus.on("message", function (data) {
  console.log(data.from + " said: " + data.contents);
});

The Framebus class takes a configuration object, where all the params are optional.

type FramebusOptions = {
  origin?: string, // default: "*"
  channel?: string, // no default
  verifyDomain?: (url: string) => boolean, // no default
  targetFrames?: <HTMLFrameElement | Window>[], // by default, all frames available to broadcast to
};

The origin sets the framebus instance to only operate on the chosen origin.

The channel namespaces the events called with on and emit so you can have multiple bus instances on the page and have them only communicate with busses with the same channel value.

If a verifyDomain function is passed, then the on listener will only fire if the domain of the origin of the post message matches the location.href value of page or the function passed for verifyDomain returns true.

var bus = new Framebus({
  verifyDomain: function (url) {
    // only return true if the domain of the url matches exactly
    url.indexOf("https://my-domain") === 0;
  },
});

If a targetFrames array is passed, then framebus will only send messages to those frames and listen for messages from those frames. You can pass a reference to a Window (the return value of window.open) or an HTMLFrameElement (a DOM node representing an iframe).

var myIframe = document.getElementById("my-iframe");

var bus = new Framebus({
  targetFrames: [myIframe],
});

To add additional frames to the targetFrames array in the future, use the addTargetFrame method. targetFrames must be set, even if it's an empty array, for this method to work.

var myIframe = document.getElementById("my-iframe");

var bus = new Framebus({
  targetFrames: [],
});

bus.addTargetFrame(myIframe);

API

target(options: FramebusOptions): framebus

returns: a chainable instance of framebus that operates on the chosen origin.

This method is used in conjuction with emit, on, and off to restrict their results to the given origin. By default, an origin of '*' is used.

framebus
  .target({
    origin: "https://example.com",
  })
  .on("my cool event", function () {});
// will ignore all incoming 'my cool event' NOT from 'https://example.com'
Argument Type Description
options FramebusOptions See above section for more details

emit('event', data?, callback?): boolean

returns: true if the event was successfully published, false otherwise

Argument Type Description
event String The name of the event
data Object The data to give to subscribers
callback(data) Function Give subscribers a function for easy, direct replies

emitAsPromise('event', data?): Promise

returns: A promise that resolves when the emitted event is responded to the first time. It will reject if the event could not be succesfully published.

Argument Type Description
event String The name of the event
data Object The data to give to subscribers

Using this method assumes the browser context you are using supports Promises. If it does not, set a polyfill for the Framebus class with setPromise

// or however you want to polyfill the promise
const PolyfilledPromise = require("promise-polyfill");

Framebus.setPromise(PolyfilledPromise);

on('event', fn): boolean

returns: true if the subscriber was successfully added, false otherwise

Unless already bound to a scope, the listener will be executed with this set to the MessageEvent received over postMessage.

Argument Type Description
event String The name of the event
fn(data?, callback?) Function Event handler. Arguments are from the emit invocation
↳ this scope The MessageEvent object from the underlying postMessage

off('event', fn): boolean

returns: true if the subscriber was successfully removed, false otherwise

Argument Type Description
event String The name of the event
fn Function The function that was subscribed

include(popup): boolean

returns: true if the popup was successfully included, false otherwise

var popup = window.open("https://example.com");

framebus.include(popup);
framebus.emit("hello popup and friends!");
Argument Type Description
popup Window The popup refrence returned by window.open

addTargetFrame(frame): boolean

Used in conjunction with targetFrames configuration. If a targetFrames array is not passed on instantiation, this method will noop.

var frame = document.getElementById("my-iframe");

framebus.addTargetFrame(frame);
framebus.emit("hello targetted iframe!");
Argument Type Description
frame Window or HTMLIFrameElement The iframe or popup to add to targetFrames

teardown(): void

Calls off on all listeners used for this bus instance and makes subsequent calls to all methods noop.

bus.on("event-name", handler);

// event-name listener is torn down
bus.teardown();

// these now do nothing
bus.on("event-name", handler);
bus.emit("event-name", data);
bus.off("event-name", handler);

Pitfalls

These are some things to keep in mind while using framebus to handle your event delegation

Cross-site scripting (XSS)

framebus allows convenient event delegation across iframe borders. By default it will broadcast events to all iframes on the page, regardless of origin. Use the optional target() method when you know the exact domain of the iframes you are communicating with. This will protect your event data from malicious domains.

Data is serialized as JSON

framebus operates over postMessage using JSON.parse and JSON.stringify to facilitate message data passing. Keep in mind that not all JavaScript objects serialize cleanly into and out of JSON, such as undefined.

Asynchronicity

Even when the subscriber and publisher are within the same frame, events go through postMessage. Keep in mind that postMessage is an asynchronous protocol and that publication and subscription handling occur on separate iterations of the event loop (MDN).

Published callback functions are an abstraction

When you specify a callback while using emit, the function is not actually given to the subscriber. The subscriber receives a one-time-use function that is generated locally by the subscriber's framebus. This one-time-use callback function is pre-configured to publish an event back to the event origin's domain using a UUID as the event name. The events occur as follows:

  1. http://emitter.example.com publishes an event with a function as the event data

    var callback = function (data) {
      console.log("Got back %s as a reply!", data);
    };
    
    framebus.emit("Marco!", callback, "http://listener.example.com");
  2. The framebus on http://emitter.example.com generates a UUID as an event name and adds the callback as a subscriber to this event.

  3. The framebus on http://listener.example.com sees that a special callback event is in the event payload. A one-time-use function is created locally and given to subscribers of 'Marco!' as the event data.

  4. The subscriber on http://listener.example.com uses the local one-time-use callback function to send data back to the emitter's origin

    framebus
      .target("http://emitter.example.com")
      .on("Marco!", function (callback) {
        callback("Polo!");
      });
  5. The one-time-use function on http://listener.example.com publishes an event as the UUID generated in step 2 to the origin that emitted the event.

  6. Back on http://emitter.example.com, the callback is called and unsubscribed from the special UUID event afterward.

Development and contributing

See CONTRIBUTING.md

More Repositories

1

manners

A polite Go HTTP server that shuts down gracefully.
Go
987
star
2

credit-card-type

A library for determining credit card type
TypeScript
916
star
3

card-validator

Validate credit cards as users type.
TypeScript
822
star
4

runbook

A framework for gradual system automation
Ruby
700
star
5

braintree_ios

Braintree SDK for iOS
Swift
542
star
6

braintree_php

Braintree PHP library
PHP
535
star
7

braintree_ruby

Braintree Ruby library
Ruby
430
star
8

braintree_android

Braintree SDK for Android
Kotlin
406
star
9

android-card-form

A ready-made card form layout that can be included in your Android app, making it easy to accept credit and debit cards.
Java
360
star
10

curator

Model and repository framework
Ruby
354
star
11

braintree_node

Braintree Node.js library
JavaScript
325
star
12

sanitize-url

TypeScript
253
star
13

braintree_python

Braintree Python library
Python
235
star
14

pg_ha_migrations

Enforces DDL/migration safety in Ruby on Rails project with an emphasis on explicitly choosing trade-offs and avoiding unnecessary magic.
Ruby
182
star
15

braintree_express_example

An example Braintree integration for Express
CSS
175
star
16

jsdoc-template

A clean, responsive documentation template with search and navigation highlighting for JSDoc 3
CSS
172
star
17

braintree_java

Braintree Java library
Java
147
star
18

braintree_dotnet

Braintree .NET library
C#
132
star
19

braintree_php_example

An example Braintree integration for PHP
CSS
124
star
20

braintree-android-drop-in

Braintree Drop-In SDK for Android
Java
118
star
21

braintree_flask_example

An example Braintree integration for Flask
CSS
103
star
22

braintree-ios-drop-in

Braintree Drop-in for iOS
Objective-C
97
star
23

braintree_rails_example

An example Braintree integration for Ruby on Rails
HTML
85
star
24

braintree_spring_example

An example Braintree integration for Spring (Java)
CSS
80
star
25

braintree-encryption.js

Javascript Library for Client-side Encryption with Braintree
JavaScript
77
star
26

pg_column_byte_packer

Auto-order table columns for optimize disk space usage
Ruby
71
star
27

restricted-input

Restrict <input>s to certain valid characters (e.g. formatting phone or card numbers)
TypeScript
67
star
28

graphql-api

Schemas, changelogs and feature requests for Braintree's GraphQL API
61
star
29

browser-detection

A utility for detecting browsers in Braintree libs.
TypeScript
60
star
30

braintree_aspnet_example

An example Braintree integration in the ASP.NET framework
CSS
59
star
31

mallory

Reverse proxy for HTTPS services, with SSL verification.
Python
57
star
32

us-bank-account-validator

A library for validating US bank account routing and account numbers
TypeScript
51
star
33

popup-bridge-android

PopupBridge allows WebViews to open popup windows in a browser and send data back to the WebView
Java
49
star
34

popup-bridge-ios

Enable your web view to open pages in a Safari View Controller
Swift
32
star
35

litmus_paper

Backend health tester for HA Services
Ruby
32
star
36

open_api_parser

A parser for Open API specifications
Ruby
30
star
37

big_brother

a daemon to monitor and administer servers in a LVS cluster of load balanced virtual servers
Ruby
28
star
38

mysql_to_postgresql

ruby script which migrates data from a MySQL database to PostgreSQL
Ruby
26
star
39

fake-wallet-app-ios

A fake version of the {PayPal,Venmo} Wallet for development
Objective-C
25
star
40

braintree_android_encryption

braintree_android_encryption
Java
24
star
41

browser-switch-android

Open a url in a browser or Chrome Custom Tab and receive a response as the result of user interaction.
Java
23
star
42

braintree_slim_example

An example Braintree integration for Slim (PHP)
CSS
22
star
43

form-napper

Hijack, submit, and inject data into forms.
JavaScript
21
star
44

braintree_perl

Braintree Perl library
Perl
18
star
45

braintree-auth-example

A Ruby/Sinatra application that demonstrates the Braintree Auth API
JavaScript
17
star
46

curator_rails_example

Example Rails application for curator
Ruby
16
star
47

activerecord-postgresql-citext

citext support for rails 4
Ruby
15
star
48

braintreehttp_php

PHP
15
star
49

wrap-promise

Small module to help support APIs that return a promise or use a callback.
TypeScript
15
star
50

iframer

Create consistent iframes
TypeScript
14
star
51

mallorca

Man-in-the-middle proxying for HTTPS.
JavaScript
14
star
52

braintree_graphql_rails_example

An example Braintree integration with the GraphQL API using Ruby on Rails
HTML
14
star
53

inject-stylesheet

Create a <style> element with CSS properties, filtering input using an allowlist or blocklist.
TypeScript
14
star
54

apollo-tracing-uploader-java

Upload Java GraphQL tracing metrics to Apollo Graph Manager
Java
13
star
55

braintree_client_side_encryption

javascript library for client-side encryption with braintree
JavaScript
13
star
56

braintree-ios-visa-checkout

Visa Checkout component for our Braintree iOS SDK
Objective-C
9
star
57

braintree_android_encryption_examples

Java
8
star
58

braintree-web-bower

JavaScript
8
star
59

braintree-android-visa-checkout

Visa Checkout component for our Braintree Android SDK
Java
7
star
60

spidersuite

Configurable crawler and reporting tool for verifying websites
JavaScript
6
star
61

qsagi

A friendly way to talk to RabbitMQ
Ruby
5
star
62

eslint-config

Shared linting configuration for braintree js projects
TypeScript
5
star
63

braintree-types

TypeScript definitions for Braintree Custom Actions
TypeScript
4
star
64

heckler

Heckler's aim is to allow you to correlate code changes with Puppet noop output!
Go
4
star
65

braintree.github.io

Braintree open source website
HTML
3
star
66

braintreehttp_python

Python
3
star
67

braintreehttp_java

Java
3
star
68

event-emitter

A simple JS based event emitter
TypeScript
3
star
69

asset-loader

A module to load frontend assets.
TypeScript
3
star
70

braintree_windows_phone_encryption

.net library for client-side encryption with braintree
C#
2
star
71

braintreehttp_ruby

Ruby
2
star
72

class-list

A helper for applying classes to dom nodes.
TypeScript
2
star
73

fluent-plugin-s3

Ruby
2
star
74

braintree-android-samsung-pay

Samsung Pay component for our Braintree Android SDK
Java
2
star
75

braintreehttp_node

JavaScript
1
star
76

extended-promise

TypeScript
1
star
77

braintree-web-drop-in-bower

Braintree Drop-in for the web
JavaScript
1
star
78

webhint-configuration-braintree-sdk

Beta Webhint configuration for Braintree's sdk-related packages
1
star
79

destructor

TypeScript
1
star
80

braintree_windows_phone_encryption_examples

C#
1
star
81

credit-card-form

Name TBD
1
star
82

popup-bridge-example

Example site for Popup Bridge mobile library
HTML
1
star
83

uuid

A simple node js implementation of uuid v4 for use with Braintree's JS based SDKs.
JavaScript
1
star