Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-browser extension interface #21

Merged
merged 4 commits into from
May 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
},
"devDependencies": {
"@types/chrome": "^0.0.86",
"@types/firefox-webext-browser": "^67.0.1",
"extensionizer": "^1.0.1",
"extract-loader": "^3.1.0",
"file-loader": "^3.0.1",
"html-loader": "^0.5.5"
Expand Down
16 changes: 9 additions & 7 deletions packages/extension/src/background/ChromeStore.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { KeyringStore } from '@polkadot/ui-keyring/types';

import extension from 'extensionizer';

const lastError = (type: string): void => {
const error = chrome.runtime.lastError;
const error = extension.runtime.lastError;

if (error) {
console.error(`ChromeStore.${type}:: chrome.runtime.lastError:`, error);
console.error(`ChromeStore.${type}:: runtime.lastError:`, error);
}
};

export default class ChromeStore implements KeyringStore {
all (cb: (key: string, value: any) => void): void {
chrome.storage.local.get(null, (result: { [index: string]: any }) => {
extension.storage.local.get(null, (result: { [index: string]: any }) => {
lastError('all');

Object.entries(result).forEach(([key, value]) =>
Expand All @@ -24,15 +26,15 @@ export default class ChromeStore implements KeyringStore {
}

get (key: string, cb: (value: any) => void): void {
chrome.storage.local.get([key], (result: { [index: string]: any }) => {
extension.storage.local.get([key], (result: { [index: string]: any }) => {
lastError('get');

cb(result[key]);
});
}

remove (key: string, cb?: () => void): void {
chrome.storage.local.remove(key, () => {
extension.storage.local.remove(key, () => {
lastError('remove');

cb && cb();
Expand All @@ -47,7 +49,7 @@ export default class ChromeStore implements KeyringStore {
return;
}

chrome.storage.local.set({ [key]: value }, () => {
extension.storage.local.set({ [key]: value }, () => {
lastError('set');

cb && cb();
Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/background/handlers/Extension.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
3 changes: 2 additions & 1 deletion packages/extension/src/background/handlers/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { AuthorizeRequest, MessageAuthorize, MessageExtrinsicSign, MessageExtrinsicSign$Response, SigningRequest } from '../types';

import extension from 'extensionizer';
import { assert } from '@polkadot/util';

type AuthRequest = {
Expand Down Expand Up @@ -115,7 +116,7 @@ export default class State {
: (signCount ? `${signCount}` : '')
);

chrome.browserAction.setBadgeText({ text });
extension.browserAction.setBadgeText({ text });
}

async authorizeUrl (url: string, request: MessageAuthorize): Promise<boolean> {
Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/background/handlers/Tabs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/background/handlers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
8 changes: 5 additions & 3 deletions packages/extension/src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import extension from 'extensionizer';

// Runs in the extension background, handling all keyring access

import keyring from '@polkadot/ui-keyring';
Expand All @@ -10,8 +12,8 @@ import { cryptoWaitReady } from '@polkadot/util-crypto';
import ChromeStore from './ChromeStore';
import handlers from './handlers';

chrome.browserAction.setBadgeBackgroundColor({ color: '#ff0000' });
chrome.runtime.onMessage.addListener(handlers);
extension.browserAction.setBadgeBackgroundColor({ color: '#ff0000' });
extension.runtime.onMessage.addListener(handlers);

cryptoWaitReady()
.then(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/background/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
11 changes: 10 additions & 1 deletion packages/extension/src/events.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
// Copyright 2019 @polkadot/extension-bg authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

// for FireFox, we need to listent here to allow origin restrictions to not
// be an issue (otherwise we cannot read the properties on the created events)
// const contentDocument = typeof gBrowser !== 'undefined'
// ? gBrowser.selectedBrowser.contentDocument
// : document;
const eventTarget = document;

const events = {
request: 'PolkadotJsWebRequest',
response: 'PolkadotJsWebResponse'
};

export { eventTarget };

export default events;
15 changes: 15 additions & 0 deletions packages/extension/src/extensionizer.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

declare var gBrowser: undefined | {
selectedBrowser: {
contentDocument: Document
}
};

declare module 'extensionizer' {
const extensionizer: typeof chrome;

export default extensionizer;
}
2 changes: 1 addition & 1 deletion packages/extension/src/inject/Accounts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/inject/Injected.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/inject/Signer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
11 changes: 7 additions & 4 deletions packages/extension/src/inject/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { MessageTypes } from '../background/types';
import { WindowInjected } from './types';

import events from '../events';
import events, { eventTarget } from '../events';
import Injected from './Injected';

// when sending a message from the injector to the expension, we
Expand Down Expand Up @@ -40,7 +40,7 @@ function sendMessage (message: MessageTypes, request: any = null): Promise<any>
}

// setup a response listener (events created by the loader for extension responses)
document.addEventListener(events.response, (event) => {
eventTarget.addEventListener(events.response, (event) => {
const response = (event as CustomEvent).detail;
const promise = callbacks[response.id];

Expand All @@ -58,11 +58,14 @@ document.addEventListener(events.response, (event) => {
}
});

// small helper with the typescript types, just cast window
const windowInject = window as WindowInjected;

// don't clobber the existing object, we will add it it (or create as needed)
(window as WindowInjected).injectedWeb3 = (window as WindowInjected).injectedWeb3 || {};
windowInject.injectedWeb3 = windowInject.injectedWeb3 || {};

// add our enable function
(window as WindowInjected).injectedWeb3['polkadot-js'] = {
windowInject.injectedWeb3['polkadot-js'] = {
name: 'polkadot-js', // process.env.PKG_NAME as string,
version: process.env.PKG_VERSION as string,
enable: (origin: string): Promise<Injected> =>
Expand Down
2 changes: 1 addition & 1 deletion packages/extension/src/inject/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 @polkadot/extension-inject authors & contributors
// Copyright 2019 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

Expand Down
13 changes: 8 additions & 5 deletions packages/extension/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import events from './events';
import extension from 'extensionizer';

import events, { eventTarget } from './events';

function sendResponse (detail: any): void {
document.dispatchEvent(new CustomEvent(events.response, { detail }));
// create the custom event, this will be handled on the injection script
eventTarget.dispatchEvent(new CustomEvent(events.response, { detail }));
}

// Handle all custom events, passing messages to the extension
document.addEventListener(events.request, (event) => {
eventTarget.addEventListener(events.request, (event) => {
// get the request as part of the the event detailt
const request = (event as CustomEvent).detail;

// pass the detail as-is as a message to the extension
chrome.runtime.sendMessage(request, (response) => {
extension.runtime.sendMessage(request, (response) => {
if (!response) {
// no data, send diconnected/unknown error
sendResponse({ id: request.id, error: 'Unknown response' });
Expand All @@ -28,7 +31,7 @@ document.addEventListener(events.request, (event) => {
// inject our data injector
const script = document.createElement('script');

script.src = chrome.extension.getURL('inject.js');
script.src = extension.extension.getURL('inject.js');
script.onload = (): void => {
// remove the injecting tag when loaded
if (script.parentNode) {
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2121,6 +2121,11 @@
resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3"
integrity sha1-wFTor02d11205jq8dviFFocU1LM=

"@types/firefox-webext-browser@^67.0.1":
version "67.0.1"
resolved "https://registry.yarnpkg.com/@types/firefox-webext-browser/-/firefox-webext-browser-67.0.1.tgz#92e3eb4440b56ab43eb93891ea4a3f33516fa7d7"
integrity sha512-+RE7MDu8EQ5EcQe7i0378oCvu1Sf9fEtRdPakYfdcEr79v7wTpO/meQXv9JLqvy7FwM2/9D8cwV7GyclXgRtxA==

"@types/fs-extra@^5.0.3":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1"
Expand Down Expand Up @@ -5666,6 +5671,11 @@ extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==

extensionizer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.1.tgz#504544239a7610ba8404b15c1832091a37768d09"
integrity sha512-UES5CSOYqshNsWFrpORcQR47+ph6UvQK25mguD44IyeMemt40CG+LTZrH1PgpGUHX3w7ACtNQnmM0J+qEe8G0Q==

external-editor@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27"
Expand Down