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

feat: preloads and nodeIntegration in iframes #16425

Merged
merged 11 commits into from Jan 22, 2019

Conversation

MarshallOfSound
Copy link
Member

Description of Change

This adds support for running preload scripts and nodeIntegration in sub-frames (iframes)

Checklist

Release Notes

Notes: Added support for running preload scripts and nodeIntegration in iframes

@MarshallOfSound MarshallOfSound requested review from a team January 17, 2019 05:46
atom/renderer/atom_renderer_client.cc Outdated Show resolved Hide resolved
atom/renderer/atom_sandboxed_renderer_client.cc Outdated Show resolved Hide resolved
docs/api/browser-window.md Outdated Show resolved Hide resolved
docs/api/browser-window.md Outdated Show resolved Hide resolved
docs/api/browser-window.md Outdated Show resolved Hide resolved
lib/browser/guest-window-manager.js Outdated Show resolved Hide resolved
lib/renderer/init.js Outdated Show resolved Hide resolved
@@ -26,7 +26,7 @@
const { defineProperty, defineProperties } = Object

// Helper function to resolve relative url.
const a = window.top.document.createElement('a')
const a = window.document.createElement('a')
const resolveURL = function (url) {
a.href = url
return a.href
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function can be replaced with the URL API

const resolveURL = function(url) {
  return new URL(url, location.href).href
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll follow up with this and other clean up referenced above. I want to keep this down to just the new code

describe('renderer nodeSupportInSubFrames', () => {
const generateTests = (sandboxEnabled) => {
describe(`with sandbox ${sandboxEnabled ? 'enabled' : 'disabled'}`, () => {
let w
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of this shared global, perhaps we could do something like

const withWindow = async (f) => {
  const w = new BrowserWindow(...)
  await f(w)
  await closeWindow(w)
}

// later

it('something', async () => {
  await withWindow(async (w) => {
    // ...
  })
})

Or perhaps there's a nice way to do something like

it('something', withWindow(async () => {
  // ...
}))

mainly I don't like that the window is closed in the test after. That could result in test failures relating to teardown being misattributed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is our current pattern, I like the idea of withWindow but I'd rather do that as a sweeping change rather than file-by-file for consitency 👍

it('should load preload scripts in nested iframes', async () => {
const detailsPromise = emittedNTimes(remote.ipcMain, 'preload-ran', 3)
w.loadFile(path.resolve(__dirname, 'fixtures/sub-frames/frame-with-frame-container.html'))
const [event1, event2, event3] = await detailsPromise
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to refactor these tests to fail rather than timeout if the preload doesn't get loaded?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that's hard to do without complicated IPC. A timeout in this case seemed the simplest (unfortunately) unless you have a good idea here

Copy link
Member

@zcbenz zcbenz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

MarshallOfSound and others added 10 commits January 22, 2019 09:04
This feature has delibrately been built / implemented in such a way
that it has minimum impact on existing apps / code-paths.
Without enabling the new "nodeSupportInSubFrames" option basically none of this
new code will be hit.

The things that I believe need extra scrutiny are:

* Introduction of `event.reply` for IPC events and usage of `event.reply` instead of `event.sender.send()`
* Usage of `node::FreeEnvironment(env)` when the new option is enabled in order to avoid memory leaks.  I have tested this quite a bit and haven't managed to cause a crash but it is still feature flagged behind the "nodeSupportInSubFrames" flag to avoid potential impact.

Closes #10569
Closes #10401
Closes #11868
Closes #12505
Closes #14035
Co-Authored-By: MarshallOfSound <samuel.r.attard@gmail.com>
@@ -330,6 +342,22 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
}))
}

const wrapEventWithReply = (event) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these still don't "wrap" a thing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, will rename

@MarshallOfSound MarshallOfSound merged commit 58a6fe1 into master Jan 22, 2019
@release-clerk
Copy link

release-clerk bot commented Jan 22, 2019

Release Notes Persisted

Added support for running preload scripts and nodeIntegration in iframes

@MarshallOfSound MarshallOfSound deleted the sub-frame-node-rebased branch January 22, 2019 19:24
MarshallOfSound added a commit that referenced this pull request Jan 27, 2019
* feat: add support for node / preloads in subframes

This feature has delibrately been built / implemented in such a way
that it has minimum impact on existing apps / code-paths.
Without enabling the new "nodeSupportInSubFrames" option basically none of this
new code will be hit.

The things that I believe need extra scrutiny are:

* Introduction of `event.reply` for IPC events and usage of `event.reply` instead of `event.sender.send()`
* Usage of `node::FreeEnvironment(env)` when the new option is enabled in order to avoid memory leaks.  I have tested this quite a bit and haven't managed to cause a crash but it is still feature flagged behind the "nodeSupportInSubFrames" flag to avoid potential impact.

Closes #10569
Closes #10401
Closes #11868
Closes #12505
Closes #14035

* feat: add support preloads in subframes for sandboxed renderers

* spec: add tests for new nodeSupportInSubFrames option

* spec: fix specs for .reply and ._replyInternal for internal messages

* chore: revert change to use flag instead of environment set size

* chore: clean up subframe impl

* chore: apply suggestions from code review

Co-Authored-By: MarshallOfSound <samuel.r.attard@gmail.com>

* chore: clean up reply usage

* chore: fix TS docs generation

* chore: cleanup after rebase

* chore: rename wrap to add in event fns
MarshallOfSound added a commit that referenced this pull request Jan 27, 2019
* feat: add support for node / preloads in subframes

This feature has delibrately been built / implemented in such a way
that it has minimum impact on existing apps / code-paths.
Without enabling the new "nodeSupportInSubFrames" option basically none of this
new code will be hit.

The things that I believe need extra scrutiny are:

* Introduction of `event.reply` for IPC events and usage of `event.reply` instead of `event.sender.send()`
* Usage of `node::FreeEnvironment(env)` when the new option is enabled in order to avoid memory leaks.  I have tested this quite a bit and haven't managed to cause a crash but it is still feature flagged behind the "nodeSupportInSubFrames" flag to avoid potential impact.

Closes #10569
Closes #10401
Closes #11868
Closes #12505
Closes #14035

* feat: add support preloads in subframes for sandboxed renderers

* spec: add tests for new nodeSupportInSubFrames option

* spec: fix specs for .reply and ._replyInternal for internal messages

* chore: revert change to use flag instead of environment set size

* chore: clean up subframe impl

* chore: apply suggestions from code review

Co-Authored-By: MarshallOfSound <samuel.r.attard@gmail.com>

* chore: clean up reply usage

* chore: fix TS docs generation

* chore: cleanup after rebase

* chore: rename wrap to add in event fns
@miniak
Copy link
Contributor

miniak commented Jun 15, 2019

Is there a chance this will make it into v4.1.x?
@CVertex highly unlikely

@vladimiry
Copy link

vladimiry commented Jul 31, 2019

Could the event.reply call potentially end up with Object has been destroyed: sender-like error? If so will the event.sender.isDestroyed() be a proper check?

@vladimiry
Copy link

vladimiry commented Aug 2, 2019

I answer the question myself.

Here is the reply code:

event.reply = (...args) => {
event.sender.sendToFrame(event.frameId, ...args)
}

So yes event.sender.isDestroyed() check is needed since reply internally accesses the event.sender.

Here is how the error looks if there is no event.sender.isDestroyed() check:

Error: Object has been destroyed
    at WebContents.sendToFrame (/opt/ElectronMail/resources/electron.asar/browser/api/web-contents.js:138:17)
    at Object.event.reply (/opt/ElectronMail/resources/electron.asar/browser/api/web-contents.js:301:22)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants