mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c
This commit is contained in:
commit
a9fefc1dc8
@ -81,3 +81,6 @@ function testShowPanel(assert, panel) {
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
//Test disabled because of bug 911071
|
||||
module.exports = {}
|
||||
|
@ -164,6 +164,8 @@ exports["test Document Reload"] = function(assert, done) {
|
||||
assert.pass('Panel was created');
|
||||
};
|
||||
|
||||
// Test disabled because of bug 910230
|
||||
/*
|
||||
exports["test Parent Resize Hack"] = function(assert, done) {
|
||||
const { Panel } = require('sdk/panel');
|
||||
|
||||
@ -216,6 +218,7 @@ exports["test Parent Resize Hack"] = function(assert, done) {
|
||||
|
||||
panel.show();
|
||||
}
|
||||
*/
|
||||
|
||||
exports["test Resize Panel"] = function(assert, done) {
|
||||
const { Panel } = require('sdk/panel');
|
||||
|
@ -25,7 +25,7 @@
|
||||
<div id="status" class="banner-box">
|
||||
<div class="banner-content">
|
||||
<span template='{"type":"localizedContent","property":"connection.connectedToDevice","paths":["device.description.name"]}'></span>
|
||||
<button class="action-cancel" onclick="UI.disconnect()">&connection.disconnect;</button>
|
||||
<button class="action-cancel" onclick="UI.disconnect()" title="&connection.disconnectTooltip;">&connection.disconnect;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -36,11 +36,11 @@
|
||||
<div class="banner-box">
|
||||
<div class="banner-content">
|
||||
<span>&connection.notConnected;</span>
|
||||
<button class="action-primary left" onclick="UI.connect()" id="connect-button" template='{"type":"localizedContent","property":"connection.connectTo","paths":["connection.host","connection.port"]}'></button>
|
||||
<button class="right" onclick="UI.editConnectionParameters()">&connection.changeHostAndPort;</button>
|
||||
<button class="action-primary left" onclick="UI.connect()" id="connect-button" template='{"type":"localizedContent","property":"connection.connectTo","paths":["connection.host","connection.port"]}' title="&connection.connectTooltip;"></button>
|
||||
<button class="right" onclick="UI.editConnectionParameters()" title="&connection.changeHostAndPortTooltip;">&connection.changeHostAndPort;</button>
|
||||
<div id="start-simulator-box">
|
||||
<span>&connection.or;</span>
|
||||
<button id="start-simulator-button" class="action-primary" onclick="UI.showSimulatorList()">&connection.startSimulator;</button>
|
||||
<button id="start-simulator-button" class="action-primary" onclick="UI.showSimulatorList()" title="&connection.startSimulatorTooltip;">&connection.startSimulator;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -52,7 +52,7 @@
|
||||
<div id="status" class="banner-box">
|
||||
<div class="banner-content">
|
||||
<span>&connection.connecting;</span>
|
||||
<button class="action-cancel" onclick="UI.disconnect()">&connection.cancel;</button>
|
||||
<button class="action-cancel" onclick="UI.disconnect()" title="&connection.cancelConnectTooltip;">&connection.cancel;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -75,7 +75,7 @@
|
||||
<form onsubmit="UI.saveConnectionInfo()">
|
||||
<input class="host" template='{"type":"attribute","path":"connection.host","name":"value"}'></input>
|
||||
<input class="port" pattern="\d+" template='{"type":"attribute","path":"connection.port","name":"value"}' type="number"></input>
|
||||
<button type="submit">&connection.saveConnectionInfo;</button>
|
||||
<button type="submit" title="&connection.saveConnectionInfoTooltip;">&connection.saveConnectionInfo;</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@ -88,13 +88,13 @@
|
||||
<div class="banner-content">
|
||||
<div class="no-simulator">
|
||||
<span>&connection.noSimulatorInstalled;</span>
|
||||
<button class="action-primary" onclick="UI.installSimulator()">&connection.installFirstSimulator;</button>
|
||||
<button class="action-primary" onclick="UI.installSimulator()" title="&connection.installOneSimulatorTooltip;">&connection.installOneSimulator;</button>
|
||||
</div>
|
||||
<div class="found-simulator">
|
||||
<span template-loop='{"arrayPath":"simulators.versions","childSelector":"#simulator-item-template"}'></span>
|
||||
<button class="action-primary" onclick="UI.installSimulator()">&connection.installAnotherSimulator;</button>
|
||||
<button class="action-primary" onclick="UI.installSimulator()" title="&connection.installAnotherSimulatorTooltip;">&connection.installAnotherSimulator;</button>
|
||||
</div>
|
||||
<button class="action-cancel" onclick="UI.cancelShowSimulatorList()">&connection.cancel;</button>
|
||||
<button class="action-cancel" onclick="UI.cancelShowSimulatorList()" title="&connection.cancelShowSimulatorTooltip;">&connection.cancel;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -113,7 +113,7 @@
|
||||
|
||||
<template id="simulator-item-template">
|
||||
<span>
|
||||
<button class="simulator-item" onclick="UI.startSimulator(this.dataset.version)" template='{"type":"attribute","path":"version","name":"data-version"}'>
|
||||
<button class="simulator-item" onclick="UI.startSimulator(this.dataset.version)" template='{"type":"attribute","path":"version","name":"data-version"}' title="&connection.startSimulatorTooltip;">
|
||||
<span template='{"type":"textContent", "path":"version"}'></span>
|
||||
</button>
|
||||
</span>
|
||||
|
@ -36,10 +36,15 @@
|
||||
</h3>
|
||||
<p template='{"type":"localizedContent","property":"device.deviceSize", "paths":["device.description.width","device.description.height","device.description.dpi"]}'></p>
|
||||
</header>
|
||||
<button onclick="UI.screenshot()">&device.screenshot;</button>
|
||||
<button onclick="UI.screenshot()" title="&device.screenshotTooltip;">&device.screenshot;</button>
|
||||
<div id="tabs-headers">
|
||||
<div onclick="UI.setTab('apps')" class="tab sidebar-item apps">&device.installedApps;</div>
|
||||
<div onclick="UI.setTab('permissions')" class="tab sidebar-item permissions">&device.permissions;</div>
|
||||
<div onclick="UI.setTab('apps')" class="tab sidebar-item apps" title="&device.installedAppsTooltip;">&device.installedApps;</div>
|
||||
<div onclick="UI.setTab('permissions')" class="tab sidebar-item permissions" title="&device.permissionsTooltip;">
|
||||
&device.permissions;
|
||||
<a target="_blank" href="&device.permissionsHelpLink;">
|
||||
<button class="help">&device.help;</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
@ -59,9 +64,9 @@
|
||||
<section template-loop='{"arrayPath":"device.permissions","childSelector":"#permission-template"}'></section>
|
||||
</div>
|
||||
<div class="permission-table-footer">
|
||||
<div class="allow-label">&device.allow;</div>
|
||||
<div class="prompt-label">&device.prompt;</div>
|
||||
<div class="deny-label">&device.deny;</div>
|
||||
<div class="allow-label" title="&device.allowTooltip;">&device.allow;</div>
|
||||
<div class="prompt-label" title="&device.promptTooltip;">&device.prompt;</div>
|
||||
<div class="deny-label" title="&device.denyTooltip;">&device.deny;</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -84,9 +89,9 @@
|
||||
<img class="app-icon" template='{"type":"attribute","path":"iconURL","name":"src"}'></img>
|
||||
<span class="app-name" template='{"type":"textContent","path":"name"}'></span>
|
||||
<div class="app-buttons">
|
||||
<button class="button-debug" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.openToolbox(this.dataset.manifest)">&device.debugApp;</button>
|
||||
<button class="button-start" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.startApp(this.dataset.manifest)">&device.startApp;</button>
|
||||
<button class="button-stop" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.stopApp(this.dataset.manifest)">&device.stopApp;</button>
|
||||
<button class="button-debug" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.openToolbox(this.dataset.manifest)" title="&device.debugAppTooltip;">&device.debugApp;</button>
|
||||
<button class="button-start" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.startApp(this.dataset.manifest)" title="&device.startAppTooltip;">&device.startApp;</button>
|
||||
<button class="button-stop" template='{"type":"attribute","path":"manifestURL","name":"data-manifest"}' onclick="UI.stopApp(this.dataset.manifest)" title="&device.stopAppTooltip;">&device.stopApp;</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -22,11 +22,11 @@
|
||||
<div template-loop='{"arrayPath":"projects","childSelector":"#project-item-template"}'></div>
|
||||
<div id="no-project">&projects.noProjects;</div>
|
||||
</div>
|
||||
<div id="new-packaged-project" onclick="UI.addPackaged()">&projects.addPackaged;</div>
|
||||
<div id="new-packaged-project" onclick="UI.addPackaged()" title="&projects.addPackagedTooltip;">&projects.addPackaged;</div>
|
||||
<div id="new-hosted-project">&projects.addHosted;
|
||||
<form onsubmit="UI.addHosted(); return false;" id="new-hosted-project-wrapper">
|
||||
<input value="" id="url-input" type="url" pattern="https?://.+" placeholder="&projects.hostedManifestPlaceHolder2;" size="50" />
|
||||
<div onclick="UI.addHosted()" id="new-hosted-project-click"></div>
|
||||
<div onclick="UI.addHosted()" id="new-hosted-project-click" title="&projects.addHostedTooltip;"></div>
|
||||
<input type="submit" hidden="true"></input>
|
||||
</form>
|
||||
</div>
|
||||
@ -39,7 +39,7 @@
|
||||
<div class="project-item-status" template='{"type":"attribute","path":"validationStatus","name":"status"}'></div>
|
||||
<img class="project-item-icon" template='{"type":"attribute","path":"icon","name":"src"}' />
|
||||
<div class="project-item-meta">
|
||||
<div class="button-remove" onclick="UI.remove(this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}' title="&projects.removeApp;"></div>
|
||||
<div class="button-remove" onclick="UI.remove(this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}' title="&projects.removeAppFromList;"></div>
|
||||
<strong template='{"type":"textContent","path":"name"}'></strong>
|
||||
<span class="project-item-type" template='{"type":"textContent","path":"type"}'></span>
|
||||
<p class="project-item-description" template='{"type":"textContent","path":"manifest.description"}'></p>
|
||||
|
@ -7,42 +7,64 @@
|
||||
<!ENTITY index.device2 "Device">
|
||||
|
||||
<!ENTITY device.screenshot "Screenshot">
|
||||
<!ENTITY device.screenshotTooltip "Open a screenshot of the current state of the device in a new tab.">
|
||||
<!ENTITY device.title "Device Control Center">
|
||||
<!ENTITY device.notConnected "Not connected. Please connect your device below.">
|
||||
<!ENTITY device.startApp "Start">
|
||||
<!ENTITY device.startAppTooltip "Start this app on the device.">
|
||||
<!ENTITY device.stopApp "Stop">
|
||||
<!ENTITY device.stopAppTooltip "Stop this app on the device.">
|
||||
<!ENTITY device.debugApp "Debug">
|
||||
<!ENTITY device.debugAppTooltip "Open the Developer Tools connected to this app on the device.">
|
||||
<!ENTITY device.name "Name">
|
||||
<!ENTITY device.app "App">
|
||||
<!ENTITY device.privileged "Privileged">
|
||||
<!ENTITY device.certified "Certified">
|
||||
<!ENTITY device.allow "Allow">
|
||||
<!ENTITY device.allowTooltip "This permission is allowed for apps of this type.">
|
||||
<!ENTITY device.prompt "Prompt">
|
||||
<!ENTITY device.promptTooltip "This permission requires a user prompt for apps of this type.">
|
||||
<!ENTITY device.deny "Deny">
|
||||
<!ENTITY device.denyTooltip "This permission is denied for apps of this type.">
|
||||
<!ENTITY device.installedApps "Installed Apps">
|
||||
<!ENTITY device.installedAppsTooltip "View a list of apps installed on the device. Some apps, such as certified apps, may be excluded from this view.">
|
||||
<!ENTITY device.permissions "Permissions">
|
||||
<!ENTITY device.permissionsTooltip "View a table of the permissions accessible to the different types of apps.">
|
||||
<!ENTITY device.permissionsHelpLink "https://developer.mozilla.org/docs/Web/Apps/App_permissions">
|
||||
<!ENTITY device.help "Help">
|
||||
|
||||
<!ENTITY connection.connectTooltip "Connect to the device.">
|
||||
<!ENTITY connection.disconnect "Disconnect">
|
||||
<!ENTITY connection.disconnectTooltip "Disconnect from the current device or simulator.">
|
||||
<!ENTITY connection.showDeviceCtrlCenter "Click for More Details">
|
||||
<!ENTITY connection.notConnected "Not Connected">
|
||||
<!ENTITY connection.changeHostAndPort "Change">
|
||||
<!ENTITY connection.changeHostAndPortTooltip "Change the host and port used to connect to the device. (Defaults to localhost:6000)">
|
||||
<!ENTITY connection.startSimulator "Start Simulator">
|
||||
<!ENTITY connection.startSimulatorTooltip "Start an instance of the Simulator and connect to it.">
|
||||
<!ENTITY connection.saveConnectionInfo "Save">
|
||||
<!ENTITY connection.saveConnectionInfoTooltip "Save the host and port.">
|
||||
<!ENTITY connection.connecting "Connecting…">
|
||||
<!ENTITY connection.disconnecting "Disconnecting…">
|
||||
<!ENTITY connection.cancel "Cancel">
|
||||
<!ENTITY connection.cancelConnectTooltip "Cancel the connection in progress.">
|
||||
<!ENTITY connection.cancelShowSimulatorTooltip "Exit the Simulator connection mode and return to the initial prompt.">
|
||||
<!ENTITY connection.or "or">
|
||||
<!ENTITY connection.noSimulatorInstalled "No simulator installed.">
|
||||
<!ENTITY connection.installFirstSimulator "Install simulator.">
|
||||
<!ENTITY connection.installOneSimulator "Install Simulator">
|
||||
<!ENTITY connection.installOneSimulatorTooltip "Install a version of the Simulator by downloading the relevant add-on.">
|
||||
<!ENTITY connection.installAnotherSimulator "Add">
|
||||
<!ENTITY connection.installAnotherSimulatorTooltip "Install an additional version of the Simulator by downloading the relevant add-on.">
|
||||
|
||||
<!ENTITY projects.localApps "Local Apps">
|
||||
<!ENTITY projects.addApp "Add">
|
||||
<!ENTITY projects.addPackaged "Add Packaged App">
|
||||
<!ENTITY projects.addPackagedTooltip "Add a new packaged app (a directory) from your computer.">
|
||||
<!ENTITY projects.addHosted "Add Hosted App">
|
||||
<!ENTITY projects.addHostedTooltip "Add a new hosted app (link to a manifest.webapp file) from a remote website.">
|
||||
<!ENTITY projects.title "Local Apps">
|
||||
<!ENTITY projects.appDetails "App Details">
|
||||
<!ENTITY projects.removeApp "Remove">
|
||||
<!ENTITY projects.removeAppFromList "Remove this app from the list of apps you are working on. This will not remove it from a device or a simulator.">
|
||||
<!ENTITY projects.reloadFiles "Refresh">
|
||||
<!ENTITY projects.installApp "Install">
|
||||
<!ENTITY projects.startApp "Start">
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 535 B |
@ -273,7 +273,10 @@ button {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
|
||||
.help {
|
||||
float: right;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
/***************** HEADER *****************/
|
||||
|
||||
|
@ -108,9 +108,6 @@ abstract public class BrowserApp extends GeckoApp
|
||||
private View mHomePagerContainer;
|
||||
protected Telemetry.Timer mAboutHomeStartupTimer = null;
|
||||
|
||||
// Set the default session restore value
|
||||
private int mSessionRestore = -1;
|
||||
|
||||
private static final int GECKO_TOOLS_MENU = -1;
|
||||
private static final int ADDON_MENU_OFFSET = 1000;
|
||||
private class MenuItemInfo {
|
||||
@ -385,15 +382,6 @@ abstract public class BrowserApp extends GeckoApp
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSessionRestoreState(Bundle savedInstanceState) {
|
||||
if (mSessionRestore > -1) {
|
||||
return mSessionRestore;
|
||||
}
|
||||
|
||||
return super.getSessionRestoreState(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
mAboutHomeStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_ABOUTHOME");
|
||||
@ -401,8 +389,8 @@ abstract public class BrowserApp extends GeckoApp
|
||||
String args = getIntent().getStringExtra("args");
|
||||
if (args != null && args.contains(GUEST_BROWSING_ARG)) {
|
||||
mProfile = GeckoProfile.createGuestProfile(this);
|
||||
} else if (GeckoProfile.maybeCleanupGuestProfile(this)) {
|
||||
mSessionRestore = RESTORE_NORMAL;
|
||||
} else {
|
||||
GeckoProfile.maybeCleanupGuestProfile(this);
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -463,6 +451,20 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnStartEditingListener(new BrowserToolbar.OnStartEditingListener() {
|
||||
public void onStartEditing() {
|
||||
// Temporarily disable doorhanger notifications.
|
||||
mDoorHangerPopup.disable();
|
||||
}
|
||||
});
|
||||
|
||||
mBrowserToolbar.setOnStopEditingListener(new BrowserToolbar.OnStopEditingListener() {
|
||||
public void onStopEditing() {
|
||||
// Re-enable doorhanger notifications.
|
||||
mDoorHangerPopup.enable();
|
||||
}
|
||||
});
|
||||
|
||||
// Intercept key events for gamepad shortcuts
|
||||
mBrowserToolbar.setOnKeyListener(this);
|
||||
|
||||
@ -826,7 +828,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
@Override
|
||||
protected void loadStartupTab(String url) {
|
||||
// We aren't showing about:home, so cancel the telemetry timer
|
||||
if (url != null || mRestoreMode != RESTORE_NONE) {
|
||||
if (url != null || mShouldRestore) {
|
||||
mAboutHomeStartupTimer.cancel();
|
||||
}
|
||||
|
||||
@ -961,13 +963,6 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
public View getActionBarLayout() {
|
||||
RelativeLayout actionBar = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.browser_toolbar, null);
|
||||
actionBar.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
|
||||
(int) getResources().getDimension(R.dimen.browser_toolbar_height)));
|
||||
return actionBar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTabsSideBar() {
|
||||
return (mTabsPanel != null && mTabsPanel.isSideBar());
|
||||
@ -1411,7 +1406,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
animator.start();
|
||||
}
|
||||
|
||||
void commitEditingMode() {
|
||||
private void commitEditingMode() {
|
||||
if (!mBrowserToolbar.isEditing()) {
|
||||
return;
|
||||
}
|
||||
@ -1486,7 +1481,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
boolean dismissEditingMode() {
|
||||
private boolean dismissEditingMode() {
|
||||
if (!mBrowserToolbar.isEditing()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -101,6 +101,14 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
public void onFilter(String searchText, AutocompleteHandler handler);
|
||||
}
|
||||
|
||||
public interface OnStartEditingListener {
|
||||
public void onStartEditing();
|
||||
}
|
||||
|
||||
public interface OnStopEditingListener {
|
||||
public void onStopEditing();
|
||||
}
|
||||
|
||||
private LayoutParams mAwesomeBarParams;
|
||||
private View mUrlDisplayContainer;
|
||||
private View mUrlEditContainer;
|
||||
@ -128,10 +136,13 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
private LinearLayout mActionItemBar;
|
||||
private MenuPopup mMenuPopup;
|
||||
private List<? extends View> mFocusOrder;
|
||||
|
||||
private OnActivateListener mActivateListener;
|
||||
private OnCommitListener mCommitListener;
|
||||
private OnDismissListener mDismissListener;
|
||||
private OnFilterListener mFilterListener;
|
||||
private OnStartEditingListener mStartEditingListener;
|
||||
private OnStopEditingListener mStopEditingListener;
|
||||
|
||||
final private BrowserApp mActivity;
|
||||
private boolean mHasSoftMenuButton;
|
||||
@ -1181,6 +1192,14 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
mFilterListener = listener;
|
||||
}
|
||||
|
||||
public void setOnStartEditingListener(OnStartEditingListener listener) {
|
||||
mStartEditingListener = listener;
|
||||
}
|
||||
|
||||
public void setOnStopEditingListener(OnStopEditingListener listener) {
|
||||
mStopEditingListener = listener;
|
||||
}
|
||||
|
||||
private void showSoftInput() {
|
||||
InputMethodManager imm =
|
||||
(InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
@ -1268,6 +1287,10 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
mUrlEditText.setText(url != null ? url : "");
|
||||
mIsEditing = true;
|
||||
|
||||
if (mStartEditingListener != null) {
|
||||
mStartEditingListener.onStartEditing();
|
||||
}
|
||||
|
||||
final int entryTranslation = getUrlBarEntryTranslation();
|
||||
final int curveTranslation = getUrlBarCurveTranslation();
|
||||
|
||||
@ -1376,6 +1399,10 @@ public class BrowserToolbar extends GeckoRelativeLayout
|
||||
}
|
||||
mIsEditing = false;
|
||||
|
||||
if (mStopEditingListener != null) {
|
||||
mStopEditingListener.onStopEditing();
|
||||
}
|
||||
|
||||
if (HardwareUtils.isTablet() || Build.VERSION.SDK_INT < 11) {
|
||||
hideUrlEditContainer();
|
||||
|
||||
|
@ -132,7 +132,6 @@ public class CrashReporter extends Activity
|
||||
getSharedPreferences(GeckoApp.PREFS_NAME, 0);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, true);
|
||||
editor.putBoolean(GeckoApp.PREFS_CRASHED, true);
|
||||
editor.commit();
|
||||
|
||||
final CheckBox allowContactCheckBox = (CheckBox) findViewById(R.id.allow_contact);
|
||||
@ -413,6 +412,7 @@ public class CrashReporter extends Activity
|
||||
Intent intent = new Intent(action);
|
||||
intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
|
||||
AppConstants.BROWSER_INTENT_CLASS);
|
||||
intent.putExtra("didRestart", true);
|
||||
Log.i(LOGTAG, intent.toString());
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
|
@ -30,6 +30,9 @@ public class DoorHangerPopup extends ArrowPopup
|
||||
// uniquely identified by its tabId and value.
|
||||
private HashSet<DoorHanger> mDoorHangers;
|
||||
|
||||
// Whether or not the doorhanger popup is disabled.
|
||||
private boolean mDisabled;
|
||||
|
||||
DoorHangerPopup(GeckoApp activity, View anchor) {
|
||||
super(activity, anchor);
|
||||
|
||||
@ -46,6 +49,24 @@ public class DoorHangerPopup extends ArrowPopup
|
||||
Tabs.unregisterOnTabsChangedListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily disables the doorhanger popup. If the popup is disabled,
|
||||
* it will not be shown to the user, but it will continue to process
|
||||
* calls to add/remove doorhanger notifications.
|
||||
*/
|
||||
void disable() {
|
||||
mDisabled = true;
|
||||
updatePopup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enables the doorhanger popup.
|
||||
*/
|
||||
void enable() {
|
||||
mDisabled = false;
|
||||
updatePopup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject geckoObject) {
|
||||
try {
|
||||
@ -246,12 +267,13 @@ public class DoorHangerPopup extends ArrowPopup
|
||||
*
|
||||
* This method must be called on the UI thread.
|
||||
*/
|
||||
void updatePopup() {
|
||||
private void updatePopup() {
|
||||
// Bail if the selected tab is null, if there are no active doorhangers,
|
||||
// or if we haven't inflated the layout yet (this can happen if updatePopup()
|
||||
// is called before the runnable from addDoorHanger() runs).
|
||||
// if we haven't inflated the layout yet (this can happen if updatePopup()
|
||||
// is called before the runnable from addDoorHanger() runs), or if the
|
||||
// doorhanger popup is temporarily disabled.
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
if (tab == null || mDoorHangers.size() == 0 || !mInflated) {
|
||||
if (tab == null || mDoorHangers.size() == 0 || !mInflated || mDisabled) {
|
||||
dismiss();
|
||||
return;
|
||||
}
|
||||
|
@ -149,13 +149,8 @@ abstract public class GeckoApp
|
||||
public static final String PREFS_NAME = "GeckoApp";
|
||||
public static final String PREFS_OOM_EXCEPTION = "OOMException";
|
||||
public static final String PREFS_WAS_STOPPED = "wasStopped";
|
||||
public static final String PREFS_CRASHED = "crashed";
|
||||
public static final String PREFS_VERSION_CODE = "versionCode";
|
||||
|
||||
static public final int RESTORE_NONE = 0;
|
||||
static public final int RESTORE_NORMAL = 1;
|
||||
static public final int RESTORE_CRASH = 2;
|
||||
|
||||
static private final String LOCATION_URL = "https://location.services.mozilla.com/v1/submit";
|
||||
|
||||
// Delay before running one-time "cleanup" tasks that may be needed
|
||||
@ -197,7 +192,7 @@ abstract public class GeckoApp
|
||||
|
||||
private HashMap<String, PowerManager.WakeLock> mWakeLocks = new HashMap<String, PowerManager.WakeLock>();
|
||||
|
||||
protected int mRestoreMode = RESTORE_NONE;
|
||||
protected boolean mShouldRestore;
|
||||
protected boolean mInitialized = false;
|
||||
private Telemetry.Timer mJavaUiStartupTimer;
|
||||
private Telemetry.Timer mGeckoReadyStartupTimer;
|
||||
@ -1243,11 +1238,9 @@ abstract public class GeckoApp
|
||||
mNotificationHelper = new NotificationHelper(this);
|
||||
mToast = new ButtonToast(findViewById(R.id.toast));
|
||||
|
||||
// Check if the last run was exited due to a normal kill while
|
||||
// we were in the background, or a more harsh kill while we were
|
||||
// active.
|
||||
mRestoreMode = getSessionRestoreState(savedInstanceState);
|
||||
if (mRestoreMode == RESTORE_NORMAL && savedInstanceState != null) {
|
||||
// Determine whether we should restore tabs.
|
||||
mShouldRestore = getSessionRestoreState(savedInstanceState);
|
||||
if (mShouldRestore && savedInstanceState != null) {
|
||||
boolean wasInBackground =
|
||||
savedInstanceState.getBoolean(SAVED_STATE_IN_BACKGROUND, false);
|
||||
|
||||
@ -1334,7 +1327,7 @@ abstract public class GeckoApp
|
||||
*/
|
||||
protected void loadStartupTab(String url) {
|
||||
if (url == null) {
|
||||
if (mRestoreMode == RESTORE_NONE) {
|
||||
if (!mShouldRestore) {
|
||||
// Show about:home if we aren't restoring previous session and
|
||||
// there's no external URL
|
||||
Tab tab = Tabs.getInstance().loadUrl("about:home", Tabs.LOADURL_NEW_TAB);
|
||||
@ -1387,24 +1380,26 @@ abstract public class GeckoApp
|
||||
initializeChrome();
|
||||
|
||||
// If we are doing a restore, read the session data and send it to Gecko
|
||||
String restoreMessage = null;
|
||||
if (mRestoreMode != RESTORE_NONE && !mIsRestoringActivity) {
|
||||
try {
|
||||
// restoreSessionTabs() will create simple tab stubs with the
|
||||
// URL and title for each page, but we also need to restore
|
||||
// session history. restoreSessionTabs() will inject the IDs
|
||||
// of the tab stubs into the JSON data (which holds the session
|
||||
// history). This JSON data is then sent to Gecko so session
|
||||
// history can be restored for each tab.
|
||||
restoreMessage = restoreSessionTabs(isExternalURL);
|
||||
} catch (SessionRestoreException e) {
|
||||
// If restore failed, do a normal startup
|
||||
Log.e(LOGTAG, "An error occurred during restore", e);
|
||||
mRestoreMode = RESTORE_NONE;
|
||||
if (!mIsRestoringActivity) {
|
||||
String restoreMessage = null;
|
||||
if (mShouldRestore) {
|
||||
try {
|
||||
// restoreSessionTabs() will create simple tab stubs with the
|
||||
// URL and title for each page, but we also need to restore
|
||||
// session history. restoreSessionTabs() will inject the IDs
|
||||
// of the tab stubs into the JSON data (which holds the session
|
||||
// history). This JSON data is then sent to Gecko so session
|
||||
// history can be restored for each tab.
|
||||
restoreMessage = restoreSessionTabs(isExternalURL);
|
||||
} catch (SessionRestoreException e) {
|
||||
// If restore failed, do a normal startup
|
||||
Log.e(LOGTAG, "An error occurred during restore", e);
|
||||
mShouldRestore = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Session:Restore", restoreMessage));
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Session:Restore", restoreMessage));
|
||||
}
|
||||
|
||||
// External URLs should always be loaded regardless of whether Gecko is
|
||||
// already running.
|
||||
@ -1414,17 +1409,14 @@ abstract public class GeckoApp
|
||||
loadStartupTab(null);
|
||||
}
|
||||
|
||||
if (mRestoreMode == RESTORE_NORMAL) {
|
||||
// If we successfully did an OOM restore, we now have tab stubs
|
||||
// from the last session. Any future tabs should be animated.
|
||||
Tabs.getInstance().notifyListeners(null, Tabs.TabEvents.RESTORED);
|
||||
} else {
|
||||
// Move the session file if it exists
|
||||
getProfile().moveSessionFile();
|
||||
}
|
||||
// We now have tab stubs from the last session. Any future tabs should
|
||||
// be animated.
|
||||
Tabs.getInstance().notifyListeners(null, Tabs.TabEvents.RESTORED);
|
||||
|
||||
if (mRestoreMode == RESTORE_NONE) {
|
||||
Tabs.getInstance().notifyListeners(null, Tabs.TabEvents.RESTORED);
|
||||
// If we're not restoring, move the session file so it can be read for
|
||||
// the last tabs section.
|
||||
if (!mShouldRestore) {
|
||||
getProfile().moveSessionFile();
|
||||
}
|
||||
|
||||
Telemetry.HistogramAdd("FENNEC_STARTUP_GECKOAPP_ACTION", startupAction.ordinal());
|
||||
@ -1595,7 +1587,7 @@ abstract public class GeckoApp
|
||||
// If we are doing an OOM restore, parse the session data and
|
||||
// stub the restored tabs immediately. This allows the UI to be
|
||||
// updated before Gecko has restored.
|
||||
if (mRestoreMode == RESTORE_NORMAL) {
|
||||
if (mShouldRestore) {
|
||||
final JSONArray tabs = new JSONArray();
|
||||
SessionParser parser = new SessionParser() {
|
||||
@Override
|
||||
@ -1633,7 +1625,6 @@ abstract public class GeckoApp
|
||||
}
|
||||
|
||||
JSONObject restoreData = new JSONObject();
|
||||
restoreData.put("normalRestore", mRestoreMode == RESTORE_NORMAL);
|
||||
restoreData.put("sessionString", sessionString);
|
||||
return restoreData.toString();
|
||||
|
||||
@ -1650,9 +1641,15 @@ abstract public class GeckoApp
|
||||
return mProfile;
|
||||
}
|
||||
|
||||
protected int getSessionRestoreState(Bundle savedInstanceState) {
|
||||
/**
|
||||
* Determine whether the session should be restored.
|
||||
*
|
||||
* @param savedInstanceState Saved instance state given to the activity
|
||||
* @return Whether to restore
|
||||
*/
|
||||
protected boolean getSessionRestoreState(Bundle savedInstanceState) {
|
||||
final SharedPreferences prefs = GeckoApp.getAppSharedPreferences();
|
||||
int restoreMode = RESTORE_NONE;
|
||||
boolean shouldRestore = false;
|
||||
|
||||
final int versionCode = getVersionCode();
|
||||
if (prefs.getInt(PREFS_VERSION_CODE, 0) != versionCode) {
|
||||
@ -1667,33 +1664,23 @@ abstract public class GeckoApp
|
||||
}
|
||||
});
|
||||
|
||||
restoreMode = RESTORE_NORMAL;
|
||||
} else if (savedInstanceState != null || PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getString(GeckoPreferences.PREFS_RESTORE_SESSION, "quit")
|
||||
.equals("always")) {
|
||||
// We're coming back from a background kill by the OS or the user
|
||||
// has chosen to always restore, so restore.
|
||||
restoreMode = RESTORE_NORMAL;
|
||||
shouldRestore = true;
|
||||
} else if (savedInstanceState != null || getSessionRestorePreference().equals("always") || getRestartFromIntent()) {
|
||||
// We're coming back from a background kill by the OS, the user
|
||||
// has chosen to always restore, or we just restarted.
|
||||
shouldRestore = true;
|
||||
}
|
||||
|
||||
// We record crashes in the crash reporter. If sessionstore.js
|
||||
// exists, but we didn't flag a crash in the crash reporter, we
|
||||
// were probably just force killed by the user, so we shouldn't do
|
||||
// a restore.
|
||||
if (prefs.getBoolean(PREFS_CRASHED, false)) {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
prefs.edit()
|
||||
.putBoolean(PREFS_CRASHED, false)
|
||||
.commit();
|
||||
}
|
||||
});
|
||||
return shouldRestore;
|
||||
}
|
||||
|
||||
restoreMode = RESTORE_CRASH;
|
||||
}
|
||||
private String getSessionRestorePreference() {
|
||||
return PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getString(GeckoPreferences.PREFS_RESTORE_SESSION, "quit");
|
||||
}
|
||||
|
||||
return restoreMode;
|
||||
private boolean getRestartFromIntent() {
|
||||
return getIntent().getBooleanExtra("didRestart", false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2155,12 +2142,14 @@ abstract public class GeckoApp
|
||||
Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
if (args != null)
|
||||
intent.putExtra("args", args);
|
||||
intent.putExtra("didRestart", true);
|
||||
Log.d(LOGTAG, "Restart intent: " + intent.toString());
|
||||
GeckoAppShell.killAnyZombies();
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Error effecting restart.", e);
|
||||
}
|
||||
|
||||
finish();
|
||||
// Give the restart process time to start before we die
|
||||
GeckoAppShell.waitForAnotherGeckoProc();
|
||||
|
@ -152,9 +152,9 @@ public class WebAppImpl extends GeckoApp {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSessionRestoreState(Bundle savedInstanceState) {
|
||||
protected boolean getSessionRestoreState(Bundle savedInstanceState) {
|
||||
// for now webapps never restore your session
|
||||
return RESTORE_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,17 +70,10 @@ interface nsISessionStore : nsISupports
|
||||
*/
|
||||
void deleteTabValue(in jsval aTab, in AString aKey);
|
||||
|
||||
/**
|
||||
* @returns A boolean indicating we should restore previous browser session
|
||||
*/
|
||||
boolean shouldRestore();
|
||||
|
||||
/**
|
||||
* Restores the previous browser session using a fast, lightweight strategy
|
||||
* @param aNormalRestore True for a normal session restore; false for a crash
|
||||
* restore.
|
||||
* @param aSessionString The session string to restore from. If null, the
|
||||
* backup session file is read from.
|
||||
*/
|
||||
void restoreLastSession(in boolean aNormalRestore, in AString aSessionString);
|
||||
void restoreLastSession(in AString aSessionString);
|
||||
};
|
||||
|
@ -44,7 +44,6 @@ SessionStore.prototype = {
|
||||
_lastSaveTime: 0,
|
||||
_interval: 10000,
|
||||
_maxTabsUndo: 1,
|
||||
_shouldRestore: false,
|
||||
|
||||
init: function ss_init() {
|
||||
// Get file references
|
||||
@ -57,12 +56,6 @@ SessionStore.prototype = {
|
||||
|
||||
this._interval = Services.prefs.getIntPref("browser.sessionstore.interval");
|
||||
this._maxTabsUndo = Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
|
||||
|
||||
// Do we need to restore session just this once, in case of a restart?
|
||||
if (this._sessionFileBackup.exists() && Services.prefs.getBoolPref("browser.sessionstore.resume_session_once")) {
|
||||
Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", false);
|
||||
this._shouldRestore = true;
|
||||
}
|
||||
},
|
||||
|
||||
_clearDisk: function ss_clearDisk() {
|
||||
@ -132,26 +125,9 @@ SessionStore.prototype = {
|
||||
this._loadState = STATE_QUITTING;
|
||||
break;
|
||||
case "quit-application":
|
||||
// If we are restarting, lets restore the tabs
|
||||
if (aData == "restart") {
|
||||
Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
|
||||
|
||||
// Ignore purges when restarting. The notification is fired after "quit-application".
|
||||
Services.obs.removeObserver(this, "browser:purge-session-history");
|
||||
}
|
||||
|
||||
// Freeze the data at what we've got (ignoring closing windows)
|
||||
this._loadState = STATE_QUITTING;
|
||||
|
||||
// Move this session to sessionstore.bak so that:
|
||||
// 1) we can get "tabs from last time" from sessionstore.bak
|
||||
// 2) if sessionstore.js exists on next start, we know we crashed
|
||||
OS.File.move(this._sessionFile.path, this._sessionFileBackup.path).then(null, function onError(reason) {
|
||||
if (!(reason instanceof OS.File.Error && reason.becauseNoSuchFile)) {
|
||||
Cu.reportError("Error moving sessionstore files: " + reason);
|
||||
}
|
||||
});
|
||||
|
||||
observerService.removeObserver(this, "domwindowopened");
|
||||
observerService.removeObserver(this, "domwindowclosed");
|
||||
observerService.removeObserver(this, "browser-lastwindow-close-granted");
|
||||
@ -217,13 +193,7 @@ SessionStore.prototype = {
|
||||
|
||||
// Do a restore, triggered by Java
|
||||
let data = JSON.parse(aData);
|
||||
this.restoreLastSession(data.normalRestore, data.sessionString);
|
||||
} else if (this._shouldRestore) {
|
||||
// Do a restore triggered by Gecko (e.g., if
|
||||
// browser.sessionstore.resume_session_once is true). In these cases,
|
||||
// our Java front-end doesn't know we're doing a restore, so it has
|
||||
// already opened an about:home tab.
|
||||
this.restoreLastSession(false, null);
|
||||
this.restoreLastSession(data.sessionString);
|
||||
} else {
|
||||
// Not doing a restore; just send restore message
|
||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored", "");
|
||||
@ -939,11 +909,7 @@ SessionStore.prototype = {
|
||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||
},
|
||||
|
||||
shouldRestore: function ss_shouldRestore() {
|
||||
return this._shouldRestore;
|
||||
},
|
||||
|
||||
restoreLastSession: function ss_restoreLastSession(aNormalRestore, aSessionString) {
|
||||
restoreLastSession: function ss_restoreLastSession(aSessionString) {
|
||||
let self = this;
|
||||
|
||||
function restoreWindow(data) {
|
||||
@ -959,31 +925,6 @@ SessionStore.prototype = {
|
||||
}
|
||||
|
||||
try {
|
||||
if (!aNormalRestore && !this._shouldRestore) {
|
||||
// If we're here, it means we're restoring from a crash. Check prefs
|
||||
// and other conditions to make sure we want to continue with the
|
||||
// restore.
|
||||
// TODO: Since the tabs have already been created as stubs after
|
||||
// crashing, it's too late to try to abort the restore here. This logic
|
||||
// should be moved to Java; see bug 889722.
|
||||
|
||||
// Disable crash recovery if it has been turned off.
|
||||
if (!Services.prefs.getBoolPref("browser.sessionstore.resume_from_crash")) {
|
||||
throw "Restore is disabled via prefs";
|
||||
}
|
||||
|
||||
// Check to see if we've exceeded the maximum number of crashes to
|
||||
// avoid a crash loop
|
||||
let maxCrashes = Services.prefs.getIntPref("browser.sessionstore.max_resumed_crashes");
|
||||
let recentCrashes = Services.prefs.getIntPref("browser.sessionstore.recent_crashes") + 1;
|
||||
Services.prefs.setIntPref("browser.sessionstore.recent_crashes", recentCrashes);
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
if (recentCrashes > maxCrashes) {
|
||||
throw "Exceeded maximum number of allowed restores";
|
||||
}
|
||||
}
|
||||
|
||||
// Normally, we'll receive the session string from Java, but there are
|
||||
// cases where we may want to restore that Java cannot detect (e.g., if
|
||||
// browser.sessionstore.resume_session_once is true). In these cases, the
|
||||
|
Loading…
Reference in New Issue
Block a user