1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- 2 * ***** BEGIN LICENSE BLOCK ***** 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 6 * You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * ***** END LICENSE BLOCK ***** */ 9 10 package org.mozilla.gecko; 11 12 import java.util.LinkedList; 13 14 import org.json.JSONArray; 15 import org.json.JSONException; 16 import org.json.JSONObject; 17 18 import android.util.Log; 19 20 public abstract class SessionParser { 21 private static final String LOGTAG = "GeckoSessionParser"; 22 23 public static final class SessionTab { 24 final private String mTitle; 25 final private String mUrl; 26 final private JSONObject mTabObject; 27 private boolean mIsSelected; 28 SessionTab(String title, String url, boolean isSelected, JSONObject tabObject)29 private SessionTab(String title, String url, boolean isSelected, JSONObject tabObject) { 30 mTitle = title; 31 mUrl = url; 32 mIsSelected = isSelected; 33 mTabObject = tabObject; 34 } 35 getTitle()36 public String getTitle() { 37 return mTitle; 38 } 39 getUrl()40 public String getUrl() { 41 return mUrl; 42 } 43 isSelected()44 public boolean isSelected() { 45 return mIsSelected; 46 } 47 getTabObject()48 public JSONObject getTabObject() { 49 return mTabObject; 50 } 51 52 /** 53 * Is this tab pointing to about:home and does not contain any other history? 54 */ isAboutHomeWithoutHistory()55 public boolean isAboutHomeWithoutHistory() { 56 JSONArray entries = mTabObject.optJSONArray("entries"); 57 return entries != null && entries.length() == 1 && AboutPages.isAboutHome(mUrl); 58 } 59 }; 60 onTabRead(SessionTab tab)61 abstract public void onTabRead(SessionTab tab); 62 63 /** 64 * Placeholder method that must be overloaded to handle closedTabs while parsing session data. 65 * 66 * @param closedTabs, JSONArray of recently closed tab entries. 67 * @throws JSONException 68 */ onClosedTabsRead(final JSONArray closedTabs)69 public void onClosedTabsRead(final JSONArray closedTabs) throws JSONException { 70 } 71 72 /** 73 * Parses the provided session store data and calls onTabRead for each tab that has been found. 74 * 75 * @param sessionStrings One or more strings containing session store data. 76 * @return False if any of the session strings provided didn't contain valid session store data. 77 */ parse(String... sessionStrings)78 public boolean parse(String... sessionStrings) { 79 final LinkedList<SessionTab> sessionTabs = new LinkedList<SessionTab>(); 80 int totalCount = 0; 81 int selectedIndex = -1; 82 try { 83 for (String sessionString : sessionStrings) { 84 final JSONArray windowsArray = new JSONObject(sessionString).getJSONArray("windows"); 85 if (windowsArray.length() == 0) { 86 // Session json can be empty if the user has opted out of session restore. 87 Log.d(LOGTAG, "Session restore file is empty, no session entries found."); 88 continue; 89 } 90 91 final JSONObject window = windowsArray.getJSONObject(0); 92 final JSONArray tabs = window.getJSONArray("tabs"); 93 final int optSelected = window.optInt("selected", -1); 94 final JSONArray closedTabs = window.optJSONArray("closedTabs"); 95 if (closedTabs != null) { 96 onClosedTabsRead(closedTabs); 97 } 98 99 for (int i = 0; i < tabs.length(); i++) { 100 final JSONObject tab = tabs.getJSONObject(i); 101 final int index = tab.getInt("index"); 102 final JSONArray entries = tab.getJSONArray("entries"); 103 if (index < 1 || entries.length() < index) { 104 Log.w(LOGTAG, "Session entries and index don't agree."); 105 continue; 106 } 107 final JSONObject entry = entries.getJSONObject(index - 1); 108 final String url = entry.getString("url"); 109 110 String title = entry.optString("title"); 111 if (title.length() == 0) { 112 title = url; 113 } 114 115 totalCount++; 116 boolean selected = false; 117 if (optSelected == i + 1) { 118 selected = true; 119 selectedIndex = totalCount; 120 } 121 sessionTabs.add(new SessionTab(title, url, selected, tab)); 122 } 123 } 124 } catch (JSONException e) { 125 Log.e(LOGTAG, "JSON error", e); 126 return false; 127 } 128 129 // If no selected index was found, select the first tab. 130 if (selectedIndex == -1 && sessionTabs.size() > 0) { 131 sessionTabs.getFirst().mIsSelected = true; 132 } 133 134 for (SessionTab tab : sessionTabs) { 135 onTabRead(tab); 136 } 137 138 return true; 139 } 140 } 141