Bug 1409191 - Prefetch manifest before install. r=snorp

This is a "hacked" fix. The key idea is to specify the value in manifest on "add to home screen confirm prompt."
We need to reuse prefetch result for  manifest.install().

The plan is to land this patch before Chrome Dev Summit(10/30) for demostration and fix the rest of the issue in a follow up bug.

MozReview-Commit-ID: A4B0ZK7UjyK

--HG--
extra : rebase_source : a91a490a08cb4ec18e5ff9f2e78f11efa6fdd98b
This commit is contained in:
Nevin Chen 2017-10-19 00:59:58 +08:00
parent f0a43c284e
commit 07f054650f
6 changed files with 65 additions and 12 deletions

View File

@ -79,6 +79,17 @@ class Manifest {
await this._store.load();
}
async prefetch(browser) {
const manifestData = await ManifestObtainer.browserObtainManifest(browser);
const icon = await ManifestIcons.browserFetchIcon(browser, manifestData, 192);
const data = {
installed: false,
manifest: manifestData,
cached_icon: icon
};
return data;
}
async install() {
const manifestData = await ManifestObtainer.browserObtainManifest(this._browser);
this._store.data = {

View File

@ -26,6 +26,7 @@ import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
import org.mozilla.gecko.toolbar.PageActionLayout;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.webapps.WebAppManifest;
import org.mozilla.gecko.widget.SiteLogins;
import android.content.ContentResolver;
@ -60,6 +61,7 @@ public class Tab {
private boolean mHasFeeds;
private String mManifestUrl;
private WebAppManifest mWebAppManifest;
private boolean mHasOpenSearch;
private final SiteIdentity mSiteIdentity;
private SiteLogins mSiteLogins;
@ -112,6 +114,14 @@ public class Tab {
public static final int LOAD_PROGRESS_LOADED = 80;
public static final int LOAD_PROGRESS_STOP = 100;
public WebAppManifest getWebAppManifest() {
return mWebAppManifest;
}
public void setWebAppManifest(WebAppManifest mWebAppManifest) {
this.mWebAppManifest = mWebAppManifest;
}
public enum ErrorType {
CERT_ERROR, // Pages with certificate problems
BLOCKED, // Pages blocked for phishing or malware warnings

View File

@ -30,6 +30,7 @@ import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.JavaUtil;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.webapps.WebAppManifest;
import android.accounts.Account;
import android.accounts.AccountManager;
@ -650,7 +651,11 @@ public class Tabs implements BundleEventListener {
tab.setHasOpenSearch(message.getBoolean("visible"));
} else if ("Link:Manifest".equals(event)) {
tab.setManifestUrl(message.getString("href"));
final String url = message.getString("href");
final String manifest = message.getString("manifest");
tab.setManifestUrl(url);
tab.setWebAppManifest(WebAppManifest.fromString(url, manifest));
} else if ("DesktopMode:Changed".equals(event)) {
tab.setDesktopMode(message.getBoolean("desktopMode"));

View File

@ -22,6 +22,7 @@ import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.webapps.WebAppManifest;
public class PwaConfirm extends RelativeLayout {
@ -115,11 +116,15 @@ public class PwaConfirm extends RelativeLayout {
final Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab == null) {
return;
}
final WebAppManifest webAppManifest = selectedTab.getWebAppManifest();
if (selectedTab != null) {
((TextView) findViewById(R.id.pwa_confirm_title)).setText(selectedTab.getTitle());
((TextView) findViewById(R.id.pwa_confirm_url)).setText(selectedTab.getURL());
((ImageView) findViewById(R.id.pwa_confirm_icon)).setImageBitmap(selectedTab.getFavicon());
if (webAppManifest != null) {
((TextView) findViewById(R.id.pwa_confirm_title)).setText(webAppManifest.getName());
((TextView) findViewById(R.id.pwa_confirm_url)).setText(webAppManifest.getStartUri().toString());
((ImageView) findViewById(R.id.pwa_confirm_icon)).setImageBitmap(webAppManifest.getIcon());
}
}

View File

@ -68,6 +68,19 @@ public class WebAppManifest {
}
}
public static WebAppManifest fromString(final String url, final String input) {
try {
final Uri manifestUri = Uri.parse(url);
final JSONObject manifest = new JSONObject(input);
final JSONObject manifestField = manifest.getJSONObject("manifest");
return new WebAppManifest(manifestUri, manifest, manifestField);
} catch (Exception e) {
Log.e(LOGTAG, "Failed to read webapp manifest", e);
return null;
}
}
private WebAppManifest(final Uri uri, final JSONObject manifest, final JSONObject manifestField) {
mManifestUri = uri;
readManifest(manifest, manifestField);

View File

@ -3959,12 +3959,20 @@ Tab.prototype = {
}
},
makeManifestMessage: function(target) {
return {
type: "Link:Manifest",
href: target.href,
tabID: this.id
};
makeManifestMessage: async function(target) {
try {
const manifest = await Manifests.getManifest(this.browser, target.href);
const data = await manifest.prefetch(this.browser);
var cache = {
type: "Link:Manifest",
href: target.href,
manifest: JSON.stringify(data),
tabID: this.id
};
GlobalEventDispatcher.sendRequest(cache);
} catch (err) {
Log.e("Browser", "error when makeManifestMessage:" + err);
}
},
sendOpenSearchMessage: function(eventTarget) {
@ -4200,7 +4208,8 @@ Tab.prototype = {
} else if (list.indexOf("[manifest]") != -1 &&
aEvent.type == "DOMLinkAdded" &&
SharedPreferences.forApp().getBoolPref("android.not_a_preference.pwa")){
jsonMessage = this.makeManifestMessage(target);
this.makeManifestMessage(target);
return;
}
if (!jsonMessage)
return;