Skip to content
Permalink
Browse files

Speed up extension messaging. Migrate -wavebox extensions into main. …

…Update background page http handlers
  • Loading branch information...
Thomas101 committed Mar 15, 2019
1 parent 1b2f35d commit 8162dc5cd260afc2b0fe11e92e3114da47e25d44
@@ -1,3 +1,4 @@
import { app } from 'electron'
import fs from 'fs-extra'
import path from 'path'
import RuntimePaths from 'Runtime/RuntimePaths'
@@ -6,6 +7,7 @@ import {
CRExtensionI18n,
CRExtensionVersionParser
} from 'shared/Models/CRExtension'
import { CRExtensionWebPreferences } from 'WebContentsManager'

const UNINSTALL_FLAG = '__uninstall__'
const PURGE_FLAG = '__purge__'
@@ -211,6 +213,53 @@ class CRExtensionFS {
}
}

/**
* Previously we namespaced some extensions with extensionid-wavebox we no longer
* want to do this, so migrate them and their partition data before launch
* Introduced in Wavebox 4.8.3 - 4.8.4
* This function will throw on errors
* @param info: the loaded extension info
* @return the updated info or the original info
*/
static migrateWaveboxNamespacedExtension (info) {
const shouldMigrate = [
'dheionainndbbpoacpnopgmnihkcmnkl-wavebox',
'mdanidgdpmkimeiiojknlnekblgmpdll-wavebox',
'elifhakcjgalahccnjkneoccemfahfoa-wavebox'
].includes(info.extensionId)
if (!shouldMigrate) { return info }

const nextExtensionId = info.extensionId.substr(0, info.extensionId.length - 8)
const nextPath = path.join(RuntimePaths.CHROME_EXTENSION_INSTALL_PATH, nextExtensionId, info.versionString)
const nextManifestPath = path.join(nextPath, 'manifest.json')

// Move the extension
fs.moveSync(info.path, nextPath)
fs.removeSync(path.dirname(info.path))
fs.writeJSONSync(nextManifestPath, {
...fs.readJSONSync(nextManifestPath),
wavebox_extension_id: nextExtensionId
})

// Move the extension data
const prevPartitionSeg = CRExtensionWebPreferences.partitionIdForExtension(info.extensionId).replace('persist:', '')
const nextPartitionSeg = CRExtensionWebPreferences.partitionIdForExtension(nextExtensionId).replace('persist:', '')
try {
fs.moveSync(
path.join(app.getPath('userData'), 'Partitions', encodeURIComponent(prevPartitionSeg)),
path.join(app.getPath('userData'), 'Partitions', encodeURIComponent(nextPartitionSeg))
)
} catch (ex) {
// Don't fall over if the partition data isn't available
}

return {
...info,
extensionId: nextExtensionId,
path: nextPath
}
}

/* ****************************************************************************/
// Removing
/* ****************************************************************************/
@@ -169,6 +169,15 @@ class CRExtensionManager {
.filter((info) => !disabledIds.has(info.extensionId))

extensions.forEach((info) => {
// Migrate first
try {
info = CRExtensionFS.migrateWaveboxNamespacedExtension(info)
} catch (ex) {
console.error('Failed to migrate extension. Refusing to load', ex)
return
}

// Load into app
try {
this.loadExtensionVersion(info.extensionId, info.versionString)
} catch (ex) {
@@ -11,7 +11,6 @@ import {
} from 'shared/crExtensionIpcEvents'
import Resolver from 'Runtime/Resolver'
import { SessionManager } from 'SessionManager'
import CRExtensionMatchPatterns from 'shared/Models/CRExtension/CRExtensionMatchPatterns'
import ContentPopupWindow from 'Windows/ContentPopupWindow'
import CRExtensionPopupWindow from './CRExtensionPopupWindow'
import CRExtensionTab from './CRExtensionTab'
@@ -150,12 +149,6 @@ class CRExtensionBackgroundPage {
(evt) => evt.preventDefault()
)

// Update cors via the extension config
SessionManager
.webRequestEmitterFromPartitionId(this.partitionId)
.beforeSendHeaders
.onBlocking(undefined, this._handleBeforeSendHeaders)

// Relax cors for extensions that request it
SessionManager
.webRequestEmitterFromPartitionId(this.partitionId)
@@ -201,26 +194,6 @@ class CRExtensionBackgroundPage {
// Web Request
/* ****************************************************************************/

/**
* Handles the before send headers event
* @param details: the details of the request
* @param responder: function to call with updated headers
*/
_handleBeforeSendHeaders = (details, responder) => {
if (this.isRunning && this.webContentsId === details.webContentsId) {
if (details.resourceType === 'xhr') {
return responder({
requestHeaders: {
...details.requestHeaders,
'Origin': ['null']
}
})
}
}

responder({})
}

/**
* Handles the headers being received and updates them if required
* @param details: the details of the request
@@ -229,24 +202,21 @@ class CRExtensionBackgroundPage {
_handleAllUrlHeadersReceived = (details, responder) => {
if (this.isRunning && this.webContentsId === details.webContentsId) {
if (details.resourceType === 'xhr') {
const { protocol, hostname, pathname } = new URL(details.url)
if (CRExtensionMatchPatterns.matchUrls(protocol, hostname, pathname, Array.from(this.extension.manifest.permissions))) {
const responseHeaders = details.responseHeaders
const requestHeaders = details.headers
const updatedHeaders = {
...responseHeaders,
'access-control-allow-credentials': responseHeaders['access-control-allow-credentials'] || ['true'],
'access-control-allow-headers': [].concat(
responseHeaders['access-control-allow-headers'],
requestHeaders['Access-Control-Request-Headers'],
Object.keys(requestHeaders).filter((k) => k.startsWith('X-'))
),
'access-control-allow-origin': [
`${CR_EXTENSION_PROTOCOL}://${this.extension.id}`
]
}
return responder({ responseHeaders: updatedHeaders })
const responseHeaders = details.responseHeaders
const requestHeaders = details.headers
const updatedHeaders = {
...responseHeaders,
'access-control-allow-credentials': responseHeaders['access-control-allow-credentials'] || ['true'],
'access-control-allow-headers': [].concat(
responseHeaders['access-control-allow-headers'],
requestHeaders['Access-Control-Request-Headers'],
Object.keys(requestHeaders).filter((k) => k.toLowerCase().startsWith('x-'))
),
'access-control-allow-origin': [
`${CR_EXTENSION_PROTOCOL}://${this.extension.id}`
]
}
return responder({ responseHeaders: updatedHeaders })
}
}
return responder({})
@@ -322,12 +322,12 @@ class CRExtensionRuntimeHandler extends EventEmitter {
// Prepare for teardown
evt.sender.once('render-view-deleted', () => {
if (runtime && runtime.backgroundPage && runtime.backgroundPage.isRunning) {
runtime.backgroundPage.webContents.sendToAll(`${CRX_PORT_DISCONNECTED_}${portId}`)
runtime.backgroundPage.webContents.send(`${CRX_PORT_DISCONNECTED_}${portId}`)
}
})

// Emit the connect event
runtime.backgroundPage.webContents.sendToAll(
runtime.backgroundPage.webContents.send(
`${CRX_PORT_CONNECTED_}${extensionId}`,
portId,
{
@@ -4,7 +4,6 @@ import CoreUserStore from 'shared/AltStores/User/CoreUserStore'
import { STORE_NAME } from 'shared/AltStores/User/AltUserIdentifiers'
import PersistenceBootstrapper from './PersistenceBootstrapper'
import actions from './userActions' // eslint-disable-line
import pkg from 'package.json'
import semver from 'semver'
import userPersistence from 'Storage/userStorage'
import wirePersistence from 'Storage/wireStorage'
@@ -37,19 +36,6 @@ class UserStore extends CoreUserStore {
// Extensions
/* ****************************************/

/**
* @return all the extensions supported in this version
*/
this.supportedExtensionList = () => {
return this.extensionList().filter((ext) => {
try {
return semver.gte(pkg.version, ext.minVersion)
} catch (ex) {
return false
}
})
}

/**
* @return the launch settings
*/
@@ -48,7 +48,7 @@ class Port {
// Re-queuing this seems to mimic the behaviour of chrome more closely.
// It can prevent ipc-loops. LP has this problem
setTimeout(() => {
this.onMessage.emit(message, this.sender)
this.onMessage.emit(JSON.parse(message), this.sender)
})
})
}
@@ -80,7 +80,7 @@ class Port {
// Re-queuing this seems to mimic the behaviour of chrome more closely.
// It can prevent ipc-loops. LP has this problem
setTimeout(() => {
ipcRenderer.sendToAll(this[privTabId], `${CRX_PORT_POSTMESSAGE_}${this[privPortId]}`, message)
ipcRenderer.sendToAll(this[privTabId], `${CRX_PORT_POSTMESSAGE_}${this[privPortId]}`, JSON.stringify(message))
})
}
}
@@ -204,6 +204,7 @@ class Runtime {
!targetExtensionId ? this[privExtensionId] : targetExtensionId, // Some extensions like to send falsy values
connectInfo
)

return new Port(this[privExtensionId], portId, connectedParty, connectInfo.name)
}

@@ -4,8 +4,6 @@ import alt from '../alt'
import actions from './userActions'
import { WaveboxHTTP } from 'Server'
import { ipcRenderer } from 'electron'
import semver from 'semver'
import pkg from 'package.json'
import ParallelHttpTracker from 'shared/AltStores/ParallelHttpTracker'
import TakeoutService from './TakeoutService'
import WaveboxAuthProviders from 'shared/Models/WaveboxAuthProviders'
@@ -42,23 +40,6 @@ class UserStore extends RendererUserStore {
this.userProfileUploadAfter = null
this.userProfileRetryUpload = null

/* ****************************************/
// Extensions
/* ****************************************/

/**
* @return all the extensions supported in this version
*/
this.supportedExtensionList = () => {
return this.extensionList().filter((ext) => {
try {
return semver.gte(pkg.version, ext.minVersion)
} catch (ex) {
return false
}
})
}

/* ****************************************/
// Listeners
/* ****************************************/
@@ -1,6 +1,9 @@
import RemoteStore from '../RemoteStore'
import User from '../../Models/User/User'
import { ACContainer, ACContainerSAPI } from '../../Models/ACContainer'
import pkg from 'package.json'
import semver from 'semver'

import {
ACTIONS_NAME,
DISPATCH_NAME,
@@ -75,6 +78,21 @@ class CoreUserStore extends RemoteStore {
return new Set(ids)
}

/**
* @return all the extensions supported in this version
*/
this.supportedExtensionList = () => {
return this.extensionList().filter((ext) => {
try {
const satisfyMinVersion = ext.minVersion ? semver.gte(pkg.version, ext.minVersion) : true
const satisfyMaxVersion = ext.maxVersion ? semver.lte(pkg.version, ext.maxVersion) : true
return satisfyMinVersion && satisfyMaxVersion
} catch (ex) {
return false
}
})
}

/* ****************************************/
// Wire config
/* ****************************************/

0 comments on commit 8162dc5

Please sign in to comment.
You can’t perform that action at this time.