The fantastic but confusing idea of Resource Hints: (a)synchronous? - html

I've been reading through Google's slides for the so-called pre-optimisation. (For the ones interested or for those who do not know what I'm talking about, this slide kinda summarises it.)
In HTML5 we can prefetch and prerender pages in the link element. Here's an overview. We can use the rel values dns-prefetch, subresource, prefetch and prerender.
The first confusing thing is that apparently only prefetch is in the spec for HTML5 (and 5.1) but none of the others are. (Yet!) The second, that browser support is OK for (dns-)prefetch but quite bad for the others. Especially Firefox's lack of support for prerender is annoying.
Thirdly, the question that I ask myself is this: does the prefetching (or any other method) happen as soon as the browser reads the line (and does it, then, block the current page load), or does it wait with loading the resources in the background until the current page is loaded completely?
If it's loaded synchronously in a blocking manner, is there a way to do this asynchronously or after page load? I suppose with a JS solution like this, but I'm not sure it will run asynchronously then.
var pre = document.createElement("link");
pre.setAttribute("rel", "prerender prefetch");
pre.setAttribute("href", "next-page.php");
document.head.appendChild(pre);
Please answer both questions if applicable!
EDIT 17 September
After reading through the Editor's draft of Resource Hints I found the following (emphasis mine):
Resource fetches that may be required for the next navigation can
negatively impact the performance of the current navigation context
due to additional contention for the CPU, GPU, memory, and network
resources. To address this, the user agent should implement logic to
reduce and eliminate such contention:
Resource fetches required for the next navigation should have lower
relative priority and should not block or interfere with resource
fetches required by the current navigation context.
The optimal time to initiate a resource fetch required for the next navigation is
dependent on the negotiated transport protocol, users current
connectivity profile, available device resources, and other context
specific variables. The user agent is left to determine the optimal
time at which to initiate the fetch - e.g. the user agent may decide
to wait until all other downloads are finished, or may choose to
pipeline requests with low priority if the negotiated protocol
supports the necessary primitives. Alternatively, the user agent may
opt-out from initiating the fetch due to resource constraints, user
preferences, or other factors.
Notice how much the user agent may do this or that. I really fear that this will lead to different implementations by different browsers which will lead to a divergence again.
The question remains though. It isn't clear to me whether loading an external resource by using prefetch or other happens synchronously (and thus, when placed in the head, before the content is loaded), or asynchronously (with a lower priority). I am guessing the latter, though I don't understand how that is possible because there's nothing in the link spec that would allow asynchronous loading of link elements' content.

Disclaimer: I haven't spent a lot of dedicated time with these specs, so it's quite likely I've missed some important point.
That said, my read agrees with yours: if a resource is fetched as a result of a pre optimization, it's likely to be fetched asynchronously, and there's little guarantee about where in the pipeline you should expect it to be fetched.
The intent seems advisory rather than prescriptive, in the same way as the CSS will-change attribute advises rendering engines that an element should receive special consideration, but doesn't prescribe the behavior, or indeed that there should be any particular behavior.
there's nothing in the link spec that would allow asynchronous loading of link elements' content
Not all links would load content in any case (an author type wouldn't cause the UA to download the contents of a mailto: URL), and I can't find any mention of fetching resources in the spec apart from that in the discussion around crossorigin:
The exact behavior for links to external resources depends on the exact relationship, as defined for the relevant link type. Some of the attributes control whether or not the external resource is to be applied (as defined below)... User agents may opt to only try to obtain such resources when they are needed, instead of pro-actively fetching all the external resources that are not applied.
(emphasis mine)
That seems to open the door for resources specified by a link to be fetched asynchronously (or not at all).

Related

When to perform certain actions in a Google Extension: onStartup, onInstalled, or just in the JS

Not usually a fan of asking these kind of open ended questions but I cant find any reliable documentation (either independent or from google) that is very clear and tutorials and examples all conflict with each other.
Currently I'm working with chrome.commands.onCommand as well as chrome.tabs.onCreated and chrome.tabs.onActivated but I'm interested in general guidelines as well (which it seems to me may be impossible). I've found a few resources such as this one and the samples but the samples are mostly one liners (WHY) and the only useful SO link I found specifically states that the post is specific to that API.
I'm using a persistent background page (since the SO answer says that matters) and really like the quote included from the documentation:
If you need to do some initialization when your extension is installed or upgraded, listen to the runtime.onInstalled event. This is a good place to register for declarativeWebRequest rules, contextMenu entries, and other such one-time initialization
But I'm currently doing all my registration in runtime.onInstalled and lose keybinds (tab stuff still seems to work but relies on the keybinds so I can't tell for sure) when the browser crashes and restarts. I'd think keybinds are a one-time initialization thing but clearly not. I could just move the keybinds to onStartup as I know it doesn't work in onInstalled but I'd prefer to know best practices for extensions (who cares if I don't use the best practice for some random library, but extensions are all about the best code imo).
Any help would be appreciated, and if any other info is needed feel free to leave a comment and let me know. I'd prefer to not have to come up with a minimum example though if possible though and keep this to guidelines for chrome.commands, chrome.tabs, as well as general guidelines for persistent pages (although event pages would be appreciated since there seem to be no good resources and others may find this question in the future).
Given the useful info by #wOxxOm and #err1100 I've decided to self answer this question. I like using comments in the question for clarification, however I often see SO users answering the question in the comments instead of posting an answer (maybe because the answers in the comments are usually more conversational than stating an answer) but either way I think questions deserve answers. If either of them posts an answer I'll accept the first to post or if someone other than them posts a significantly better answer (don't go stealing their credit).
Persistent Pages:
Persistent pages apparently have better support across different browsers and so should be preferred in that case (at least as of 11/24/2018). Otherwise consider using an event page if the extension is just for Chrome as persistence is rarely needed.
onInstalled:
Context menus and anything with the declarativeXXXX naming scheme should be initialized once in the onInstalled event but there aren't many other things requiring one time initialization.
onStartup:
With persistent pages the script is loaded once and never unloaded unless the browser is closed and so onStartup doesn't have much of a use.
In the Script:
As said above, since the script is loaded only once per browser restart (and also ran once if installed on an already running browser) all per browsing session initalization can be done here.
Event Pages:
I didn't have a clear idea of exactly what the use of non persistent pages were (I believe this is what wOxxOm is referring to as an event page as googling it takes me to defunct documentation and redirects to documentation without the term) prior to this question so I'll clear that up for those who may be in the same boat. A non persistent script is ran (at some point, IDK and won't be testing this) and registers it's event listeners. After that the script dies but the listeners remain meaning that initialization can be done with onInstalled and onStartup (since I know for sure when these are run and not when the non persistent page script is ran) and all the events you registered to listen for will reactivate that part of your script (really just runs the callback provided but whatever).
onInstalled:
Just like with Persistent pages use this for the same things that require one time initialization.
onStartup:
I'd leave no code in the script and everything in a listener if creating an event page but I'm not well versed in event pages so I'll update this if someone comments on it being wrong. Stuff requiring initialization each browser restart would be in this listener.
In the Script:
As said above, I don't have a great understanding of event scripts but it seems like the only code in your script should be for setting up listeners and whatever variables those listeners need. No significant scripting should occur in the script however do as you must to make your extension of course (or just use a persistent page).

Best practice for email links that will set a DB flag?

Our business wants to email our customers a survey after they work with support. For internal reasons, we want to ask them the first question in the body of the email. We'd like to have a link for each answer. The link will go to a web service, which will store the answer, then present the rest of the survey.
So far so good.
The challenge I'm running into: making a server-side changed based on an HTTP GET is bad practice, but you can't do a POST from a link. Options seem to be:
Use an HTTP GET instead, even though that's not correct and could cause problems (https://twitter.com/rombulow/status/990684453734203392)
Embed an HTML form in the email and style some buttons to look like links (likely not compatible with a number of email platforms)
Don't include the first question in the email (not possible for business reasons)
Use HTTP GET, but have some sort of mechanism which prevents a link from altering the server state more than once
Does anybody have any better recommendations? Googling hasn't turned up much about this specific situation.
One thing to keep in mind is that HTTP is specifying semantics, not implementation. If you want to change the state of your server on receipt of a GET request, you can. See RFC 7231
This definition of safe methods does not prevent an implementation from including behavior that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method. What is important, however, is that the client did not request that additional behavior and cannot be held accountable for it. For example, most servers append request information to access log files at the completion of every response, regardless of the method, and that is considered safe even though the log storage might become full and crash the server. Likewise, a safe request initiated by selecting an advertisement on the Web will often have the side effect of charging an advertising account.
Domain agnostic clients are going to assume that GET is safe, which means your survey results could get distorted by web spiders crawling the links, browsers pre-loading resource to reduce the perceived latency, and so on.
Another possibility that works in some cases is to treat the path through the graph as the resource. Each answer link acts like a breadcrumb trail, encoding into itself the history of the clients answers. So a client that answered A and B to the first two questions is looking at /survey/questions/questionThree?AB where the user that answered C to both is looking at /survey/questions/questionThree?CC. In other words, you aren't changing the state of the server, you are just guiding the client through a pre-generated survey graph.

What is the benefit of blocking cookie for clicked link? (SameSite=strict)

So for Google Chrome and Opera, cookies have SameSite attribute, which can have one of two values: strict or lax.
One of a few differences between those is that SameSite=strict will prevent a cookie from being sent when we click a link to another domain.
I know that SameSite is not W3C recommendation yet, but what is potential benefit of this behavior? I find it rather annoying, because the cookie is sent anyway when we refresh or click another link on the current domain. That leads to rather weird user experience - for example: we are logged out, then we click some domestic link or refresh and we are suddenly authenticated.
I'm aware that it's not designed for the greatest user experience, but rather for security. But what are we actually winning here in terms of security?
The benefits of using strict instead of lax are limited. I can see two:
Protection against CSRF attacks via GET requests. Such attacks are not normally possible since they rely on the server implementing GET endpoints with side effects (incorrectly and in violation of the semantics specified by RFC 7231). An example was given by you in the comments:
Imagine we have a very bad design and all our actions are performed on GET method. The attacker placed link saying "Save puppies" which links to http://oursite.com/users/2981/delete. That's the only use-case I can think of - when we have some action done via GET method, while it shouldn't.
Protection against timing attacks. There's a class of attacks - which were already discovered back in 2000, but which Mathias Bynens has recently explored and popularised - that involve a malicious webpage using JavaScript to initiate a request to a page on another domain and then measuring how long it takes, and inferring things about the user from the time taken. An example that Mathias invented is to initiate a request to a Facebook page with a restricted audience, such that it is only accessible by, say, people in Examplestan. Then the evil webpage times how long it takes for the response to come back. Facebook serves the error page when you try to access an inaccessible post faster than it serves the actual post, so if the evil webpage gets a quick response, it can infer that the user is not in Examplestan; if it gets a slow response, then the user is probably an Examplestani.
Since browsers don't stop executing JavaScript on a page when you do top-level navigation until they've received a response from the URL being navigated to, these timing attacks are unfortunately perfectly possible with top-level navigation; your evil page can just navigate the user away via location=whatever, then time how long it takes for the other page to load by repeatedly recording the current timestamp to localStorage in a loop. Then on a subsequent visit the evil page can check how long the page took to start unloading, and infer the response time of the page being timed.
The domain hosting the target page - like facebook.com, in the case of Mathias's example - could protect its users from this kind of attack by using samesite=strict cookies.
Obviously, these limited benefits come at a serious UX tradeoff, and so are typically not worth it compared to the already-pretty-good protections offered by samesite=lax!
There should be an answer here so I'm just going to repeat what's already been said in the comments.
You should always use samesite=lax, unless you're OK with giving your users a terrible user experience. lax is secure enough, as cookies will only be sent for Safe Methods (i.e. GET) when referred from a different domain. If you do dangerous things with GET requests, well, you have bigger problems.

Load page / Cache analysis

Hello all please help with the analysis of my page.
Question 1
Why since everything is load from cache. Load time is 690ms?
question 2
what will be the reason to use --> private, max-age=60000
(public), max-age=60000 VS. private, max-age=60000
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en
First, load time isn't just defined by the time it takes to get assets from the network. Painting and parsing can take a lot of time, as can the parsing of Javascript. In your case, DOMContentLoaded is only fired after 491 milliseconds, so that's already part of the answer.
As to your second question, the answer really is in the link you provided:
If the response is marked as “public” then it can be cached, even if it has HTTP authentication associated with it, and even when the response status code isn’t normally cacheable. Most of the time, “public” isn’t necessary, because explicit caching information (like “max-age”) indicates that the response is cacheable anyway.
By contrast, “private” responses can be cached by the browser but are typically intended for a single user and hence are not allowed to be cached by any intermediate cache - e.g. an HTML page with private user information can be cached by that user’s browser, but not by a CDN.

Implementation of synchronization primitives over HTML5 local storage

Consider a scenario where a browser has two or more tabs pointing to the same origin. Different event loops of the different tabs can lead to race conditions while accessing local storage and the different tabs can potentially overwrite each other's changes in local storage.
I'm writing a web application that would face such race conditions, and so I wanted to know about the different synchronization primitives that could be employed in such a scenario.
My reading of the relevant W3C spec, and the comment from Ian Hickson at the end of this blog post on the topic, suggests that what's supposed to happen is that a browser-global mutex controls access to each domain's localStorage. Each separate "thread" (see below for what I'm fairly confident that means) of JavaScript execution must attempt to acquire the storage mutex (if it doesn't have it already) whenever it examines local storage. Once it gets the mutex, it doesn't give it up until it's completely done.
Now, what's a thread, and what does it mean for a thread to be done? The only thing that makes sense (and the only thing that's really consistent with Hixie's claim that the mutex makes things "completely safe") is that a thread is JavaScript code in some browser context that's been initiated by some event. (Note that one possible event is that a <script> block has just been loaded.) The nature of JavaScript in the browser in general is that code in a <script> block, or code in a handler for any sort of event, runs until it stops; that is, runs to the end of the <script> body, or else runs until the event handler returns.
So, given that, what the storage mutex is supposed to do is to force all shared-domain scripts to block upon attempting to claim the mutex when one of their number already has it. They'll block until the owning thread is done — until the <script> tag code is exhausted, or until the event handler returns. That behavior would achieve this guarantee from the spec:
Thus, the length attribute of a Storage object, and the value of the various properties of that object, cannot change while a script is executing, other than in a way that is predictable by the script itself.
However, it appears that WebKit-based browsers (Chrome and Safari, and probably the Android browser too, and now maybe Opera?) don't bother with the mutex implementation, which leaves you in the situation that drove you to ask the question. If you're concerned with such race conditions (a perfectly reasonable attitude), then you can use either the locking mechanism suggested in the blog post (by someone who does, or did, work for Stackoverflow :) or else implement a version counting system to detect dirty writes. (edit — now that I think about it, an RDBMS-style version mechanism would be problematic, because there'd still be a race condition checking the version!)