Skip to content

Commit

Permalink
1. add BrowserWindow.addExtension, BrowserWindow.removeExtension, and…
Browse files Browse the repository at this point in the history
… BrowserWindow.getExtensions

2. change the way users load extensions
3. store datas into `userData/` when developing the project
  • Loading branch information
qazbnm456 committed Apr 23, 2017
1 parent 1bce422 commit 2005e16
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -12,6 +12,7 @@ app/dist/about.css
extensions/*
builds/*
dist/*
userData/*
coverage
node_modules/
npm-debug.log
Expand Down
2 changes: 1 addition & 1 deletion app/pages/inject-to.js
Expand Up @@ -13,7 +13,7 @@ exports.injectTo = (extensionId, isBackgroundPage, context, LocalStorage) => {

if (LocalStorage) {
storagePath = process.env.NODE_ENV === 'development'
? path.join(remote.app.getPath('temp'), 'lulumi-local-storage')
? path.join(path.resolve('./userData'), 'lulumi-local-storage')
: path.join(remote.app.getPath('userData'), 'lulumi-local-storage');

// eslint-disable-next-line no-undef
Expand Down
88 changes: 34 additions & 54 deletions app/src/api/chrome-extension.js
@@ -1,4 +1,4 @@
import { app, nativeImage, webContents } from 'electron';
import { app, BrowserWindow, nativeImage, webContents } from 'electron';
import { Buffer } from 'buffer';
import fs from 'fs';
import path from 'path';
Expand Down Expand Up @@ -53,15 +53,13 @@ const getManifestFromPath = (srcDirectory) => {
Object.assign(manifest, {
srcDirectory: srcDirectory,
extensionId: extensionId,
// We can not use 'file://' directly because all resources in the extension
// will be treated as relative to the root in Chrome.
startPage: url.format({
protocol: 'chrome-extension',
protocol: 'lulumi-extension',
slashes: true,
hostname: extensionId,
pathname: manifest.devtools_page
})
})
pathname: manifest.devtools_page,
}),
});
return manifest;
} else if (manifest && manifest.name) {
console.warn(`Attempted to load extension "${manifest.name}" that has already been loaded.`);
Expand Down Expand Up @@ -151,6 +149,7 @@ const injectContentScripts = (manifest) => {
contentScripts: manifest.content_scripts.map(contentScriptToEntry),
icons: iconsToEntry(manifest.icons),
srcDirectory: manifest.srcDirectory,
name: manifest.name,
};
global.renderProcessPreferences.push(entry);
contentScripts[manifest.name] = entry;
Expand All @@ -168,8 +167,6 @@ const removeContentScripts = (manifest) => {
delete contentScripts[manifest.name];
}

// Transfer the |manifest| to a format that can be recognized by the
// |DevToolsAPI.addExtensions|.
const manifestToExtensionInfo = (manifest) => {
return {
startPage: manifest.startPage,
Expand All @@ -193,7 +190,6 @@ const loadLulumiExtensions = (win, manifests) => {
manifests.forEach(loadExtension);

const extensionInfoArray = manifests.map(manifestToExtensionInfo);
// win.devToolsWebContents.executeJavaScript(`DevToolsAPI.addExtensions(${JSON.stringify(extensionInfoArray)})`);
};

app.on('web-contents-created', (event, webContents) => {
Expand Down Expand Up @@ -228,7 +224,7 @@ const lulumiExtensionHandler = (request, callback) => {

fs.readFile(path.join(manifest.srcDirectory, parsed.path), (err, content) => {
if (err) {
return callback(-6); // FILE_NOT_FOUND
return callback(-6); // FILE_NOT_FOUND
} else {
return callback(content);
}
Expand All @@ -246,7 +242,6 @@ app.on('session-created', (sess) => {
// the persistent path of "Lulumi Extensions" preference file
let loadedExtensionsPath = null;

/*
app.on('will-quit', () => {
try {
const loadedExtensions = objectValues(manifestMap).map((manifest) => {
Expand All @@ -266,77 +261,62 @@ app.on('will-quit', () => {
// Ignore error
}
});
*/

// we can not use protocol or BrowserWindow until app is ready
app.once('ready', () => {
// load persisted extensions
loadedExtensionsPath = process.env.NODE_ENV === 'development'
? path.resolve('./extensions')
: path.join(config.lulumiAppPath, 'extensions');
? path.join(config.devUserData, 'lulumi-extensions')
: path.join(app.getPath('userData'), 'lulumi-extensions');
try {
const loadedExtensions
= fs.readdirSync(loadedExtensionsPath).filter((file) => file.startsWith('.') === false).filter((file) => fs.lstatSync(path.join(loadedExtensionsPath, file)).isDirectory());
const loadedExtensions = JSON.parse(fs.readFileSync(loadedExtensionsPath));
if (Array.isArray(loadedExtensions)) {
for (const extension of loadedExtensions) {
// Start background pages and set content scripts.
const manifest = getManifestFromPath(path.join(loadedExtensionsPath, extension));
for (const srcDirectory of loadedExtensions) {
// start background pages and set content scripts
const manifest = getManifestFromPath(srcDirectory);
loadExtension(manifest);
}
}
} catch (error) {
// Ignore error
// ignore error
}

// the public API to add/remove extensions
/*
BrowserWindow.addDevToolsExtension = function (srcDirectory) {
const manifest = getManifestFromPath(srcDirectory)
BrowserWindow.addExtension = (srcDirectory) => {
const manifest = getManifestFromPath(srcDirectory);
if (manifest) {
loadExtension(manifest)
for (const webContents of getAllWebContents()) {
loadExtension(manifest);
for (const webContents of webContents.getAllWebContents()) {
if (isWindowOrWebView(webContents)) {
loadDevToolsExtensions(webContents, [manifest])
loadLulumiExtensions(webContents, [manifest]);
}
}
return manifest.name
return manifest.name;
}
}

BrowserWindow.removeDevToolsExtension = function (name) {
const manifest = manifestNameMap[name]
if (!manifest) return
BrowserWindow.removeExtension = (name) => {
const manifest = manifestNameMap[name];
if (!manifest) {
return;
}

removeBackgroundPages(manifest)
removeContentScripts(manifest)
delete manifestMap[manifest.extensionId]
delete manifestNameMap[name]
removeBackgroundPages(manifest);
removeContentScripts(manifest);
delete manifestMap[manifest.extensionId];
delete manifestNameMap[name];
}

BrowserWindow.getDevToolsExtensions = function () {
const extensions = {}
BrowserWindow.getExtensions = () => {
const extensions = {};
Object.keys(manifestNameMap).forEach(function (name) {
const manifest = manifestNameMap[name]
extensions[name] = {name: manifest.name, version: manifest.version}
const manifest = manifestNameMap[name];
extensions[name] = {name: manifest.name, version: manifest.version};
})
return extensions
return extensions;
}
*/
});

export function addExtension (srcDirectory) {
const manifest = getManifestFromPath(srcDirectory);
if (manifest) {
loadExtension(manifest);
for (const webContents of webContents.getAllWebContents()) {
if (isWindowOrWebView(webContents)) {
loadLulumiExtensions(webContents, [manifest]);
}
}
return manifest.name;
}
};

export {
manifestMap,
manifestNameMap,
Expand Down
36 changes: 35 additions & 1 deletion app/src/api/extensions/listeners.js
@@ -1,10 +1,44 @@
import { BrowserWindow, ipcMain, webContents } from 'electron';
import { BrowserWindow, dialog, ipcMain, webContents } from 'electron';

const isDarwin = process.platform === 'darwin';

ipcMain.on('open-dev-tools', (event, webContentsId) => {
if (webContentsId) {
webContents.fromId(webContentsId).openDevTools();
}
});
ipcMain.on('add-extension', (event) => {
if (isDarwin) { // use "sheet" dialog when we are on macOS
const window = BrowserWindow.fromWebContents(event.sender)
dialog.showOpenDialog(window, {
properties: ['openDirectory'],
}, (dirs) => {
if (dirs) {
// an array of diretory paths chosen by the user will be returned, but we only want one path
BrowserWindow.addExtension(dirs[0]);
event.sender.send('add-extension-result', dirs[0]);
}
});
} else {
dialog.showOpenDialog({
properties: ['openDirectory'],
}, (dirs) => {
if (dirs) {
// an array of diretory paths chosen by the user will be returned, but we only want one path
BrowserWindow.addExtension(dirs[0]);
event.sender.send('add-extension-result', dirs[0]);
}
});
}
});
ipcMain.on('remove-extension', (event, name) => {
try {
BrowserWindow.removeExtension(name);
event.sender.send('remove-extension-result', 'OK');
} catch (removeError) {
event.sender.send('remove-extension-result', removeError);
}
});

ipcMain.on('lulumi-env-app-name', (event) => {
BrowserWindow.getAllWindows()[0]
Expand Down
35 changes: 34 additions & 1 deletion app/src/guest/renderer/components/AboutMainView/Extensions.vue
Expand Up @@ -3,13 +3,16 @@
el-row(type="flex", align="middle")
el-col(:span="12")
h1 Extensions
el-col(:span="6", :offset="3")
el-button(type="info", @click="addExtension") Add
el-row
el-col(:span="24")
ul(class="extensions-list")
li(v-for="extension in Object.keys(extensions)", :key="extension", class="extensions-list__item")
el-button(:plain="true", type="danger", size="small", icon="circle-cross", @click="removeExtension(extension)")
a(class="extensions-list__item-name extensions-list__item-link", @click.prevent="openDevTools(extensions[extension].webContentsId)")
img(:src="loadIcon(extension)", style="width: 32px; margin-left: -30px; padding-right: 15px;")
| {{ extension }}
| {{ loadName(extension) }}
div
| {{ "Path: " }}
span(class="extensions-list__item-path") {{ loadPath(extension) }}
Expand All @@ -23,6 +26,12 @@
},
},
methods: {
loadName(extensionId) {
// eslint-disable-next-line no-undef
const id = window.renderProcessPreferences
.findIndex(element => element.extensionId === extensionId);
return window.renderProcessPreferences[id].name;
},
loadIcon(extensionId) {
// eslint-disable-next-line no-undef
const id = window.renderProcessPreferences
Expand All @@ -39,6 +48,30 @@
// eslint-disable-next-line no-undef
ipcRenderer.send('open-dev-tools', webContentsId);
},
addExtension() {
// eslint-disable-next-line no-undef
ipcRenderer.once('add-extension-result', () => {
window.location.reload();
});
// eslint-disable-next-line no-undef
ipcRenderer.send('add-extension');
},
removeExtension(extensionId) {
// eslint-disable-next-line no-undef
const id = window.renderProcessPreferences
.findIndex(element => element.extensionId === extensionId);
// eslint-disable-next-line no-undef
ipcRenderer.once('remove-extension-result', (event, result) => {
if (result === 'OK') {
window.location.reload();
} else {
// eslint-disable-next-line no-alert
alert(result);
}
});
// eslint-disable-next-line no-undef
ipcRenderer.send('remove-extension', window.renderProcessPreferences[id].name);
},
},
};
</script>
Expand Down
6 changes: 1 addition & 5 deletions app/src/main/index.js
Expand Up @@ -13,12 +13,8 @@ let mainWindow;

let shuttingDown = false;
const storagePath = process.env.NODE_ENV === 'development'
? path.join(app.getPath('temp'), '.lulumi-test-app-state')
? path.join(config.devUserData, 'lulumi-app-state')
: path.join(app.getPath('userData'), 'app-state');
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line no-console
console.log(storagePath);
}
let appStateSaveHandler = null;

const isDarwin = process.platform === 'darwin';
Expand Down
5 changes: 4 additions & 1 deletion app/src/renderer/js/constants/config.js
Expand Up @@ -4,6 +4,7 @@ let lulumiAppPath = process.env.NODE_ENV === 'development'
? `${__dirname}/../../../../`
: `${__dirname}/../`;
lulumiAppPath = path.resolve(lulumiAppPath);
const lulumiRootPath = path.resolve(`${lulumiAppPath}/../`);

const searchEngine = [
{
Expand Down Expand Up @@ -39,5 +40,7 @@ export default {
lulumiPagesPath: `${lulumiAppPath}/pages/`,
lulumiPDFJSPath: `${lulumiAppPath}/pdfjs/`,
lulumiAppPath,
lulumiRev: '8b59339691b7fc405890ffb514f3c1e357b4c478',
lulumiRootPath,
devUserData: `${lulumiRootPath}/userData/`,
lulumiRev: '9862b77491f241ef4e31152893a882b6eb262dd0',
};
Empty file added userData/.gitkeep
Empty file.

0 comments on commit 2005e16

Please sign in to comment.