New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 665045 link

Starred by 9 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: iOS
Pri: 2
Type: Compat


Participants' hotlists:
iOS-Web-Platform-Backlog


Sign in to add a comment

Should __gCrWeb be exposed to applications?

Project Member Reported by rbyers@chromium.org, Nov 14 2016

Issue description

Chrome for iOS has an internal global object __gCrWeb which I believe is exposed to web applications.  This has interoperability implications just like webkit* prefixed APIs.

Eg. what if sites come to depend on the APIs there to deliver some sort of user experience? Is it OK if Firefox for iOS decided the wanted to copy some aspect of that API to improve behavior on some sites, and then how would we feel about such APIs eventually making it into the compat spec https://compat.spec.whatwg.org/)?  What if sites could be broken by changes in the surface area exposed via __gCrWeb, do we need to be careful about removing anything?

Or can we avoid all this complexity by hiding __gCrWeb from the application somehow?
 

Comment 1 by rbyers@chromium.org, Nov 14 2016

Cc: pinkerton@chromium.org esprehn@chromium.org zkoch@chromium.org

Comment 2 by rbyers@chromium.org, Nov 14 2016

BTW, I did an HTTPArchive search and found 10,000 pages that refer to "__gCrWeb" today.  Eg. on http://www.0-1.ru/ there is this code:

        if (0 <= window.navigator.userAgent.indexOf("CriOS")) {
            var a = window.__gCrWeb && window.__gCrWeb.message && window.__gCrWeb.message.invokeOnHost;
            if (a) {
                z_();
                a({
                    command: "cast.sender.init"
                });
                return
            }
        }


Comment 3 by rbyers@chromium.org, Nov 14 2016

It looks like most of the hits above are from YouTube embeds.  But I do see a few hits from URLs not served by Google.  See https://docs.google.com/spreadsheets/d/1Dhn_7hadWi6JGvfHhKrz1bNzeY1yPmpbUsLQByOWtzs/edit#gid=2017732530

Eg. the hit on https://www.plastc.com/wallet seems to be due to issue 665044 - trying to ignore errors raised by internal bling code.
Cc: eugene...@chromium.org stuartmorgan@chromium.org mard...@chromium.org
+mardini, eugenebut
+stuartmorgan as FYI since he was around for much of the early development related to our JS injection. 
We can not hide __gCrWeb. Chrome for iOS is not allowed to use Blink and has to rely on JavaScript execution for most of the features.

Comment 6 by pkl@chromium.org, Nov 14 2016

Owner: eugene...@chromium.org
Status: Assigned (was: Untriaged)

Comment 7 by rbyers@chromium.org, Nov 14 2016

I know we can't use blink.  But we can control what JS runs first, right?  Why can't we inject a single bundle of all our script at the beginning that looks like this:

(function() {
  var gCrWeb=__gCrWeb;
  delete window.__gCrWeb;
  ...<all-js-resource-script contents>
})();

Then all later scripts that run will not see any __gCrWeb property on window, but all your own internal scrips will still have access to it.
Status: WontFix (was: Assigned)
We can control all injected JS, but we also call those injected functions from the native code. Hiding __gCrWeb will make Native->JS communication impossible and will break multiple features.

Comment 9 by rbyers@chromium.org, Nov 15 2016

Couldn't you do Native->JS communication by having the JS side pass callback functions back to the native side?

If there's really no way to fix this, then do you have any other ideas for mitigating the web platform risks I outlined at the top of the bug?  You're effectively shipping a proprietary API to the web platform, and history has shown that most proprietary browser APIs end up getting cloned by other browsers and as a result end up being standardized retroactively.  We should assume this case won't be any different.
Status: Assigned (was: WontFix)
>> Couldn't you do Native->JS communication by having the JS side pass callback functions back to the native side?
Unfortunately, no. The only way to talk from native code to JS is JS execution on the main frame.

We could move __gCrWeb to window.chrome, but I don't think it will make things better. Chrome for iOS has to expose certain APIs to the native code and that API will always be visible to web pages.

Are we concerned that Chrome has window.chrome global object?
> Unfortunately, no. The only way to talk from native code to JS is JS execution on the main frame.

Ah, I see - that is a shame.  Ok, another idea: rather than hard-code __gCrWeb could we generate a random string every time we launch so that applications couldn't predict what it would be?  That would be nearly as good as being hidden IMHO. Although I guess a really motivated application could search all objects looking for one with the desired properties.  To mitigate that we could perhaps use Symbol.for() given the random key to get the object from the global symbol registry instead of adding a property to window.

> Are we concerned that Chrome has window.chrome global object?

Yes.  These are all legacy back from WebKit days before we had the blink launch process and in various degrees of being removed.  Eg. on Android we have only chrome.loadTimes and chrome.csi which are being removed in issue 621512.  We definitely shouldn't be adding any new APIs here (though I suppose we don't have the tooling necessary to enforce that - filed issue 665273).

> ... get the object from the global symbol registry instead of adding a property to window.

Correction: we'd still have to stick it on an object like 'window' and it would still be findable with Object.getOwnPropertySymbols, but at least we could keep it from showing up in Object.getOwnPropertyNames.  Using Symbol probably isn't worth the effort.  A non-enumerable property on window with a random name is probably about as hidden as we can make it while still being able to get at it via a JavaScript string.

Another difference to note with window.chrome is that those were APIs that we were intentionally exposing and comitting to supporting as a stable contract with web pages.  In this bug we're talking just about accidental exposure of internal implementation details, right?  Or is the API surface area of __gCrWeb considered to be a stable contract?
Components: Mobile>WebView>Glue
I'm not sure if a bug is the best place for this brainstorming. 

@rbyers: can you start a doc to collect some of this discussion and enumerate the problems to solve, and we can iterate there? A brainstorming GVC might be higher bandwidth, and thus more useful as well. 
>>  Ok, another idea: rather than hard-code __gCrWeb could we generate a random string every time we launch so that applications couldn't predict what it would be?
Unfortunately that won't work with current architecture. Often our scripts directly call __gCrWeb functions and not all our scripts are injected together. However this is something that could actually be feasible if we refactor our scripts injections system. 

>> Or is the API surface area of __gCrWeb considered to be a stable contract?
In practice we don't change it often, but I was never meant to be stable.

Yeah we should start a design doc. Before we embark on adding web platform features by way of JS shims to bling I think we need to redesign the bindings system to actually isolate the features (ex. saving intrinsic methods like Array.prototype.slice, avoiding calling author code randomly), and also use generated random callback names like JSONP.
FWIW, a couple of responses based on the historical thinking here (not it any way intended to discourage brainstorming of better approaches):

> You're effectively shipping a proprietary API to the web platform, and history has shown that most proprietary browser APIs end up getting cloned by other browsers and as a result end up being standardized retroactively.

Most of what is exposed is to work around the fundamental limitations of building a browser on iOS for anyone but Apple. It would be nonsensical for Apple to clone workarounds that they don't need by virtue of being able to call private methods and do things much more cleanly and efficiently.

> We should assume this case won't be any different.

While this is certainly a conversation we've had in the past and something we've tried to be sensitive to in implementation, I very strongly disagree that we should assume that this case--which has wildly different context and purpose in several key ways--will end the same way. The realities here do not have any precedent I'm aware of. I'm happy to discuss more about the history of these discussions in person in the new year.
Cc: danyao@chromium.org rbyers@chromium.org
Doc with some proposed solutions:
https://docs.google.com/document/d/1K6wbb-pEqSNl2L3VvatlNVuvJPo7ta-J2g9KsdIsgvo/edit#heading=h.9nwcxunbqs8

Owner: ----
Status: Available (was: Assigned)
Labels: -Type-Bug Type-Compat
Owner: danyao@chromium.org
Status: Assigned (was: Available)
Components: Mobile>iOSWeb
Components: -Mobile>WebView>Glue
Components: -Mobile>iOSWeb Mobile>iOSWeb>ScriptInjections

Sign in to add a comment