Pass loadURIOptions dictionary for docshell loads
Categories
(Core :: DOM: Security, enhancement, P2)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox66 | --- | fixed |
People
(Reporter: ckerschb, Assigned: ckerschb)
References
(Blocks 1 open bug)
Details
(Whiteboard: [domsecurity-active])
Attachments
(2 files, 4 obsolete files)
|
32.20 KB,
patch
|
ckerschb
:
review+
|
Details | Diff | Splinter Review |
|
50.80 KB,
patch
|
Gijs
:
review+
|
Details | Diff | Splinter Review |
| Assignee | ||
Updated•7 years ago
|
| Assignee | ||
Comment 1•7 years ago
|
||
| Assignee | ||
Comment 2•7 years ago
|
||
Comment 3•7 years ago
|
||
| Assignee | ||
Comment 4•7 years ago
|
||
Comment 5•7 years ago
|
||
Comment 6•7 years ago
|
||
| Assignee | ||
Comment 7•7 years ago
|
||
| Assignee | ||
Comment 8•7 years ago
|
||
| Assignee | ||
Updated•7 years ago
|
Comment 9•7 years ago
|
||
Comment 10•7 years ago
|
||
| Assignee | ||
Comment 11•7 years ago
|
||
Comment 12•7 years ago
|
||
| Assignee | ||
Comment 13•7 years ago
|
||
| Assignee | ||
Comment 14•7 years ago
|
||
After some intensive hacking I realized that CSP requires more changes. I am suggesting we provide the fundamental architecture for loadArgs within this Bug and do the CSP stuff within Bug 1518454.
| Assignee | ||
Comment 15•7 years ago
|
||
Boris,
let me summarize the changes within this patch:
- We create a LoadArgs.webidl which contains a dictionary for arguments we want to pass to LoadURI().
- We update nsIWebNavigation.idl and pass that new loadArgs object to LoadURIWithOptions and since LoadURI() was just forwarding calls to LoadURIWithOptions() I removed LoadURI completely.
- Probably we can be a little smarter within the WebIDL regarding default values. For now, I only require a triggeringPrincipal and default the loadFlags to 0.
- As mentioned, the CSP bits are getting pretty big sizewise, so let's do all the CSP related changes to the loadArgs dict within Bug 1518454.
- Gijs offered his help to review the frontend bits if you are fine with those backend changes.
Thanks!
| Assignee | ||
Comment 16•7 years ago
|
||
Gijs,
please see the previous comment for some background. Additionally, I don't like the additional
-
if (postData) { -
loadArgs.postStream = postData; -
}
instead of just adding let loadArgs = { ..., postStream: postData }, but if postData is null then I get the following error:
Console message: [JavaScript Error: "'postStream' member of LoadArgs is not an object."
Maybe it has to do with the defaults in the LoadArgs.webidl but I am not sure - would be really happy if we can clean that up.
Thanks!
Comment 17•7 years ago
|
||
You should be able to use the ? suffix for properties on the dictionary that can be null, I think?
In fact, this means I'm a bit confused about the triggering principal:
required Principal? triggeringPrincipal;
Comment 18•7 years ago
|
||
Yeah, passing an explicitly null postStream seems fine so we should allow that.
In fact, this means I'm a bit confused about the triggering principal:
We currently have a mode where we allow null to be passed (when the "security.strict_security_checks.enabled" pref is false. That's the default on release, beta, and Android...
Comment 19•7 years ago
•
|
||
Comment on attachment 9035079 [details] [diff] [review]
bug_1513241_part_1_update_loadURI_interface.patch
>+++ b/docshell/base/nsDocShell.cpp
>+nsDocShell::LoadURIWithOptions(const nsAString& aURI,
Why not just call this loadURI? There is no more "non-options" version, and the fact that it has options is obvious from the options member...
>+ const mozilla::dom::LoadArgs& aLoadArgs) {
This file has "using namespace mozilla::dom", so I don't think we need the full namespacing here.
>+ nsCOMPtr<nsIInputStream> postStream;
>+ if (aLoadArgs.mPostStream.WasPassed()) {
>+ postStream = aLoadArgs.mPostStream.Value();
>+ }
Since we should allow null for the postStream anyway, with null representing "no post data", the IDL should probably just have:
InputStream? postStream = null;
and then this code can be:
nsCOMPtr<nsIInputStream> postStream = aLoadArgs.mPostStream;
>+ if (aLoadArgs.mHeaders.WasPassed()) {
Same thing here; I think we should just allow passing null to represent "no header stream" and set that up as the default value.
>+ if (aLoadArgs.mBaseURI.WasPassed()) {
And probably same here; might as well allow passing null explicitly for the base URI.
I don't know whether we'd still want the headerStream and baseURI locals if we do that.
>+ if (aLoadArgs.mReferrerURI.WasPassed()) {
We probably want to allow passing null here too, actually. Especially since the IDL comments claim something about what happens if it's null. ;)
>+nsDocShell::LoadURIWithOptionsFromScript(const nsAString& aURI,
>+ dom::LoadArgs loadArgs;
Is the namespace prefixing needed?
>@@ -6905,22 +6917,22 @@ nsresult nsDocShell::EndPageLoad(nsIWebP
>+ dom::LoadArgs loadArgs;
Is the prefixing needed?
>+++ b/docshell/base/nsIDocShell.idl
>+interface nsIContentSecurityPolicy;
Hmm. Why is this needed?
>+++ b/docshell/base/nsIWebNavigation.idl
>+#include "mozilla/dom/LoadArgsBinding.h"
Why is this needed? The "native" decl should forward-declare the type, and I doubt the header needs to see the actual declaration...
>+ * @param aLoadArgs
>+ * A JSObject of the form LoadArgs.webidl holding info like e.g. the
"defined in LoadArgs.webidl", right?
>+++ b/dom/ipc/TabChild.cpp
> + dom::LoadArgs loadArgs;
Do we need the prefixing?
>+ NS_ConvertUTF8toUTF16(aURI),loadArgs);
Missing space. Did you clang-format this? If not, please do.
>+++ b/dom/security/FramingChecker.cpp
>@@ -252,18 +253,21 @@ static bool ShouldIgnoreFrameOptions(nsI
>+ dom::LoadArgs loadArgs;
Do we need the prefixing?
>+++ b/dom/webidl/LoadArgs.webidl
>+dictionary LoadArgs {
This name seems very generic... How about LoadURIOptions (and rename the .webidl too).
>+ * The principal that initiated the load.
>+ */
>+ required Principal? triggeringPrincipal;
There was more documentation in the .idl. Is leaving it out purposeful?
I'm a bit torn on whether this should be in the dictionary or just an argument, given the "required" status. Especially given the C++ callers, who can easily forget to set the member...
That said, if we're planning to just pass around the entire LoadURIOptions struct as a whole, it makes sense to have this in the dictionary.
Maybe we should add a constructor to dictionaries with required args that takes those args... Maybe file a followup on that and reference this dictionary?
>+ * One of the REFERRER_POLICY_* constants from nsIHttpChannel.
>+ * Normal case is REFERRER_POLICY_NO_REFERRER_WHEN_DOWNGRADE.
I know you just copied this comment, but seems to be the "normal case" is UNSET and then the internals will do something with that, right?
>+++ b/editor/composer/nsEditingSession.cpp
>+ dom::LoadArgs loadArgs;
Do we need the prefixing?
>+++ b/xpfe/appshell/nsWebShellWindow.cpp
>+ dom::LoadArgs loadArgs;
Do we need the prefixing?
r=me with those bits fixed. Thank you for doing this!
| Assignee | ||
Comment 20•7 years ago
|
||
Thanks Boris, I incorporated all of your suggestions, in particular:
- Renamed the dictionary as well as the file to LoadURIOptions.webidl
- Kept LoadURI() and ditched LoadURIWithOptions()
- Removed namespace prefixing where possible
Regarding the triggeringPrincipal as part of the dictionary or having it as a separate argument
- I prefer having it within the dictionary because as you have pointed out we can pass around the loadURIOptions struct as a whole. Additionally we have strong assertions within LoadURI() which enforce we have a triggeringPrincipal set. Please note that even if the pref security.strict_security_checks.enable is set to false we still assert that LoadURI gets a valid triggeringPrincipal.
Copying over r+ from bz!
| Assignee | ||
Comment 21•7 years ago
|
||
Gijs, this is way cleaner now having the webidl updated with the default values. What do you think?
Comment 22•7 years ago
|
||
Why is this needed? The "native" decl should forward-declare the type, and I doubt the header needs to see the actual declaration...
What happened to that review comment?
| Assignee | ||
Comment 23•7 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #22)
Why is this needed? The "native" decl should forward-declare the type, and I doubt the header needs to see the actual declaration...
What happened to that review comment?
Sorry for not pointing that out explicitly, but I didn't ignore your comment. If I remove |#include "mozilla/dom/LoadURIOptionsBinding.h"| from nsIWebNavigation.idl I get the following compile error:
0:31.02 /home/ckerschb/source/mc-dbg/dist/include/nsIWebNavigation.h:95:93: error: no type named 'LoadURIOptions' in namespace 'mozilla::dom'
0:31.02 JS_HAZ_CAN_RUN_SCRIPT virtual nsresult LoadURI(const nsAString& aURI, const mozilla::dom::LoadURIOptions & aLoadURIOptions) = 0;
| Assignee | ||
Updated•7 years ago
|
Comment 24•7 years ago
|
||
Ah, I see. We don't automatically generate forward-decls for "native" bits.
Still, all we should need here is a forward-decl (inside the "%{C++" section), not an include, right?
| Assignee | ||
Comment 25•7 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #24)
Ah, I see. We don't automatically generate forward-decls for "native" bits.
Still, all we should need here is a forward-decl (inside the "%{C++" section), not an include, right?
Unfortunately not - I tried several things.
First approach: Simply doing:
%{ C++
class mozilla::dom::LoadURIOptions;
%}
causes this compile error:
In file included from /home/ckerschb/source/mc/uriloader/base/nsDocLoader.cpp:14:
0:04.64 /home/ckerschb/source/mc-dbg/dist/include/nsIWebNavigation.h:38:21: error: no class named 'LoadURIOptions' in namespace 'mozilla::dom'
0:04.64 class mozilla::dom::LoadURIOptions;
Second Approach:
If in nsIWebNavigation.idl I do:
webidl LoadURIOptions;
it produces the following code within dist/include/nsIWebNavigation.h:
namespace mozilla {
namespace dom {
class LoadURIOptions; /* webidl LoadURIOptions */
} // namespace dom
} // namespace mozilla
which then causes this warning.
1:42.28 struct LoadURIOptions : public DictionaryBase
1:42.28 ^
1:42.28 /home/ckerschb/source/mc-dbg/dist/include/nsIWebNavigation.h:39:1: note: did you mean struct here?
1:42.28 class LoadURIOptions; /* webidl LoadURIOptions */
1:42.28 ^~~~~
1:42.28 struct
1:47.07 1 warning generated.
TDIL because I was not aware that we can use forward declarations within *.idl. Do you want me to file a bug to generate forward declarations for native bits? Or how should we proceed?
Comment 26•7 years ago
|
||
First approach: Simply doing:
You want:
%{C++
namespace mozilla {
namespace dom {
struct LoadURIOptions;
} // namespace dom
} // namespace mozilla
%}
Comment 27•7 years ago
|
||
Comment 28•7 years ago
|
||
I would be fine with calling it postData on the C++ side, fwiw.
| Assignee | ||
Comment 29•7 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #26)
First approach: Simply doing:
You want:
%{C++ namespace mozilla { namespace dom { struct LoadURIOptions; } // namespace dom } // namespace mozilla %}
Thanks - that works!
| Assignee | ||
Comment 30•7 years ago
|
||
The code we are having at the moment causes some problems on Android [1], which is also why we only assert that we pass the right triggeringPrincipal for top-level loads if it's not an Android build. To accomodate, I changed the LoadURIOptions.webidl to
Principal? triggeringPrincipal = null;
so the principal is not required. Jonathan will fix that problem within Bug 1504968. I'll leave a comment within Bug 1504968 as well.
[1] https://treeherder.mozilla.org/#/jobs?repo=try&revision=61ab3e53d35dba0a5db9c20394a7000cd301bef7
| Assignee | ||
Comment 31•7 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #28)
I would be fine with calling it postData on the C++ side, fwiw.
I updated that part and also called it postData in the webidl.
| Assignee | ||
Comment 32•7 years ago
|
||
(In reply to :Gijs (he/him) from comment #27)
this._sendMessage("WebNavigation:LoadURI", { uri: aURI,
flags: aLoadURIOptions.loadFlags,Can you file a follow-up issue to make these object prop names match to make
this slightly more ergonomic?
Thanks Gijs, I incorporated your suggestions and filed Bug 1519365 to get those property names updated.
Comment 33•7 years ago
|
||
Comment 34•7 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/6ae543902cda
https://hg.mozilla.org/mozilla-central/rev/71cb45922e34
Comment 35•6 years ago
|
||
Any chance you could update the docs on MDN to explain what arguments loadURI() now expects?
I'm trying to fix a regression from this in qbrt which calls loadURI() on startup.
I can see that loadURI() expects an object as the second argument and it seems to require that triggeringPrincipal is set in that object, but I'm not sure what to set it to? If I set it to the system principal using Services.scriptSecurityManager.getSystemPrincipal() then it silently fails.
browser.loadURI(url, {
'triggeringPrincipal': Services.scriptSecurityManager.getSystemPrincipal()
});
I don't suppose you could point me in the right direction?
Updated•6 years ago
|
Comment 36•6 years ago
|
||
(In reply to Ben Francis [:benfrancis] from comment #35)
Any chance you could update the docs on MDN to explain what arguments
loadURI()now expects?
Which docs are these? The slug and page itself doesn't make it clear. Is this the one on docshell/webnavigation? <browser> ? Or the global function that we (used to?) have in browser windows? Or something else? They're all different...
Either way, it looks like it wasn't updated for a very very long time... AFAIK no versions of loadURI have taken that set of args for a while now. I'm not convinced we need to fix it now - it'd be better to just mark these bits of XUL documentation as deprecated as I expect other parts of it are similarly outdated/wrong/broken.
I can see that
loadURI()expects an object as the second argument and it seems to require thattriggeringPrincipalis set in that object, but I'm not sure what to set it to? If I set it to the system principal usingServices.scriptSecurityManager.getSystemPrincipal()then it silently fails.
It looks like you're using non-e10s. Is that intentional? I might have broken you in bug 1560178, but in that case the loadURI call should throw NS_ERROR_FAILURE .
Comment 37•6 years ago
|
||
Looking at the qbrt source code, you're calling browser.loadURI, where the params default to an empty object ( https://searchfox.org/mozilla-central/rev/b9041f813de0a05bf6de95a145d4e25004499517/toolkit/content/widgets/browser-custom-element.js#965,989 ), and which then calls the webnav/docshell's loadURI, so AFAICT you end up at https://searchfox.org/mozilla-central/rev/b9041f813de0a05bf6de95a145d4e25004499517/docshell/base/nsDocShell.cpp#3940-3942 (only if the security.strict_security_checks.enabled pref is set to true in your setup), so I don't think these patches should be breaking anything "silently". Ping me on IRC or slack if these comments aren't sufficient to unblock you, but I very much doubt these patches are to blame for any breakage. They also didn't change the arguments to the XUL browser's loadURI, so I'm clearing the devdoc keyword.
Comment 38•6 years ago
|
||
Which docs are these? The slug and page itself doesn't make it clear. Is this the one on docshell/webnavigation? <browser> ? Or the global function that we (used to?) have in browser windows? Or something else? They're all different...
I got there from the <browser> docs.
Either way, it looks like it wasn't updated for a very very long time... AFAIK no versions of loadURI have taken that set of args for a while now. I'm not convinced we need to fix it now - it'd be better to just mark these bits of XUL documentation as deprecated as I expect other parts of it are similarly outdated/wrong/broken.
If it's deprecated, where is the current documentation for the <browser> element?
It looks like you're using non-e10s. Is that intentional? I might have broken you in bug 1560178, but in that case the loadURI call should throw NS_ERROR_FAILURE .
To be clear, I didn't write any of this code, I'm just trying to get it working again. I don't know whether e10s is enabled or not, but my understanding is that qbrt just downloads a Nightly build of Firefox to use as a runtime so I'd expect it to do what ever Nightly does.
The error with the current set of arguments is:
JavaScript error: chrome://global/content/elements/browser-custom-element.js, line 874: TypeError: aParams is null
If I just pass the URL and an empty object for aParams then I get:
JavaScript error: chrome://global/content/elements/browser-custom-element.js, line 886: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIWebNavigation.loadURI]
If I set triggeringPrincipal to the system principal in the aParams object, qbrt fails to start but without any errors.
I can't access bug 1560178 so I don't know whether that's relevant.
They also didn't change the arguments to the XUL browser's loadURI, so I'm clearing the devdoc keyword.
Ah sorry, I must have misunderstood what was changed in this patch (I was pointed here as a possible source of the change). The description seemed to match the change in interface on the browser element, but if this is unrelated I'll try to find you in IRC/Slack rather than continue the conversation here.
Description
•