From e33e394d16b0f49ec3d17bb75f39d401bb659a8d Mon Sep 17 00:00:00 2001 From: Michael Henretty Date: Mon, 27 Jan 2014 15:19:42 -0800 Subject: [PATCH] Bug 959800 - [Offline] mozbrowser iframes don't display correct offline content --- apps/system/js/net_error.js | 79 ++++++++++++++++++++++++++++++------- build/jshint/xfail.list | 1 - build/webapp-optimize.js | 23 +++++++++++ 3 files changed, 87 insertions(+), 16 deletions(-) diff --git a/apps/system/js/net_error.js b/apps/system/js/net_error.js index 45a07d0affe9..3d41081290f7 100644 --- a/apps/system/js/net_error.js +++ b/apps/system/js/net_error.js @@ -1,7 +1,55 @@ -'use strict'; (function(window) { + 'use strict'; + + /** + * Return the current application object + */ + var _app; + function getAppObject(cb) { + if (_app) { + cb(_app); + return; + } + + var request = navigator.mozApps.getSelf(); + request.onsuccess = function() { + cb(request.result); + }; + request.onerror = function() { + console.warn('about:netError error fetching app: ' + request.error.name); + cb(); + }; + } + + /** + * Check if net_error is coming from within an iframe + */ function isFramed() { - return window !== window.parent; + var error = getErrorFromURI(); + var manifestURL = error.m; + + // frame type values (regular, browser, app) + var frameType = error.f; + switch (frameType) { + + // if we are in a "regular" frame, we are indeed framed + case 'regular': + return true; + + // if we are an "app" frame, we are not framed + case 'app': + return false; + + // If we are in a "browser" frame, we are either in a browser tab + // or a mozbrowser iframe within in app. Since browser tabs are + // considered unframed, we must perform a check here to distinguish + // between the two cases. + case 'browser': + return manifestURL !== window.BROWSER_MANIFEST; + + default: + throw new Error('about:netError: invalid frame type - ' + frameType); + } } /** @@ -39,17 +87,13 @@ * of an app simply return the URI */ function getAppName(cb) { - var request = navigator.mozApps.getSelf(); - request.onsuccess = function() { - if (request.result && request.result.manifest.name) { - cb(request.result.manifest.name); + getAppObject(function(app) { + if (app && app.manifest.name) { + cb(app.manifest.name); } else { cb(location.protocol + '//' + location.host); } - }; - request.onerror = function() { - cb(location.protocol + '//' + location.host); - }; + }); } /** @@ -155,28 +199,33 @@ * m - Manifest URI of the application that generated the error. * c - Character set for default gecko error message (eg. 'UTF-8'). * d - Default gecko error message. + * f - The frame type ("regular", "browser", "app") */ + var _error; function getErrorFromURI() { - var error = {}; + if (_error) { + return _error; + } + _error = {}; var uri = document.documentURI; // Quick check to ensure it's the URI format we're expecting. if (!uri.startsWith('about:neterror?')) { // A blank error will generate the default error message (no network). - return error; + return _error; } // Small hack to get the URL object to parse the URI correctly. var url = new URL(uri.replace('about:', 'http://')); // Set the error attributes. - ['e', 'u', 'm', 'c', 'd'].forEach( + ['e', 'u', 'm', 'c', 'd', 'f'].forEach( function(v) { - error[v] = url.searchParams.get(v); + _error[v] = url.searchParams.get(v); } ); - return error; + return _error; } /** diff --git a/build/jshint/xfail.list b/build/jshint/xfail.list index 4bccfa3a446e..c6541bd11a39 100644 --- a/build/jshint/xfail.list +++ b/build/jshint/xfail.list @@ -1041,7 +1041,6 @@ apps/system/js/logo_loader.js apps/system/js/media_playback.js apps/system/js/media_recording.js apps/system/js/modal_dialog.js -apps/system/js/net_error.js apps/system/js/nfc_handover.js apps/system/js/nfc_handover_manager.js apps/system/js/nfc_manager.js diff --git a/build/webapp-optimize.js b/build/webapp-optimize.js index ef54b848c77a..3df2913d74d5 100644 --- a/build/webapp-optimize.js +++ b/build/webapp-optimize.js @@ -277,6 +277,22 @@ function optimize_aggregateJsResources(doc, webapp, htmlFile) { scripts.forEach(commentScript); } +/** + * Append values to the global object on the page + * + * @param {HTMLDocument} doc DOM document of the file. + * @param {Object} globals dictionary containing the appended globals. + */ +function optimize_embedGlobals(doc, globals) { + var script = doc.createElement('script'); + var content = ''; + for (var key in globals) { + content += 'window.' + key + '="' + globals[key] + '";'; + } + script.innerHTML = content; + doc.documentElement.appendChild(script); +} + /** * Inline and minify all css/script resources on the page * @@ -317,6 +333,13 @@ function optimize_inlineResources(doc, webapp, filePath, htmlFile) { oldScript.parentNode.removeChild(oldScript); }); + // add the browser manifest url to our global object for net_error + // see: https://bugzilla.mozilla.org/show_bug.cgi?id=959800#c8 + optimize_embedGlobals(doc, { + BROWSER_MANIFEST: + 'app://browser.' + config.GAIA_DOMAIN + '/manifest.webapp' + }); + // inline stylesheets let styles = Array.slice(doc.querySelectorAll('link[rel="stylesheet"]')); styles.forEach(function(oldStyle) {