merge fx-team to mozilla-central
@ -11,9 +11,9 @@
|
||||
#endif
|
||||
oncommand="MultiplexHandler(event)"
|
||||
#ifdef OMIT_ACCESSKEYS
|
||||
onpopupshowing="CharsetMenu.build(event);"
|
||||
#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__');"
|
||||
#else
|
||||
onpopupshowing="CharsetMenu.build(event, true);"
|
||||
#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__', true);"
|
||||
#endif
|
||||
onpopupshown="UpdateMenus(event);">
|
||||
<menupopup>
|
||||
|
@ -276,8 +276,8 @@
|
||||
#endif
|
||||
/>
|
||||
|
||||
<key id="key_devToolboxMenuItem" keycode="&devToolboxMenuItem.keycode;"
|
||||
keytext="&devToolboxMenuItem.keytext;" command="Tools:DevToolbox" key="&devToolboxMenuItem.keytext;"
|
||||
<key id="key_devToolboxMenuItem" keytext="&devToolboxMenuItem.keytext;"
|
||||
command="Tools:DevToolbox" key="&devToolboxMenuItem.keytext;"
|
||||
#ifdef XP_MACOSX
|
||||
modifiers="accel,alt"
|
||||
#else
|
||||
|
@ -9,6 +9,7 @@ let Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NotificationDB.jsm");
|
||||
Cu.import("resource:///modules/RecentWindow.jsm");
|
||||
Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
@ -1151,14 +1152,10 @@ var gBrowserInit = {
|
||||
Cu.reportError("Could not end startup crash tracking: " + ex);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
gMetroPrefs.prefDomain.forEach(function(prefName) {
|
||||
gMetroPrefs.pushDesktopControlledPrefToMetro(prefName);
|
||||
Services.prefs.addObserver(prefName, gMetroPrefs, false);
|
||||
}, this);
|
||||
#endif
|
||||
#endif
|
||||
if (typeof WindowsPrefSync !== 'undefined') {
|
||||
// Pulls in Metro controlled prefs and pushes out Desktop controlled prefs
|
||||
WindowsPrefSync.init();
|
||||
}
|
||||
|
||||
if (gMultiProcessBrowser) {
|
||||
// Bug 862519 - Backspace doesn't work in electrolysis builds.
|
||||
@ -1280,13 +1277,9 @@ var gBrowserInit = {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
gMetroPrefs.prefDomain.forEach(function(prefName) {
|
||||
Services.prefs.removeObserver(prefName, gMetroPrefs);
|
||||
});
|
||||
#endif
|
||||
#endif
|
||||
if (typeof WindowsPrefSync !== 'undefined') {
|
||||
WindowsPrefSync.uninit();
|
||||
}
|
||||
|
||||
BrowserOffline.uninit();
|
||||
OfflineApps.uninit();
|
||||
@ -2460,6 +2453,49 @@ function BrowserFullScreen()
|
||||
window.fullScreen = !window.fullScreen;
|
||||
}
|
||||
|
||||
function _checkDefaultAndSwitchToMetro() {
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
let shell = Components.classes["@mozilla.org/browser/shell-service;1"].
|
||||
getService(Components.interfaces.nsIShellService);
|
||||
let isDefault = shell.isDefaultBrowser(false, false);
|
||||
|
||||
if (isDefault) {
|
||||
let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
|
||||
getService(Components.interfaces.nsIAppStartup);
|
||||
|
||||
Services.prefs.setBoolPref('browser.sessionstore.resume_session_once', true);
|
||||
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
|
||||
Components.interfaces.nsIAppStartup.eRestartTouchEnvironment);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
function SwitchToMetro() {
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
if (this._checkDefaultAndSwitchToMetro()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let shell = Components.classes["@mozilla.org/browser/shell-service;1"].
|
||||
getService(Components.interfaces.nsIShellService);
|
||||
|
||||
shell.setDefaultBrowser(false, false);
|
||||
|
||||
let intervalID = window.setInterval(this._checkDefaultAndSwitchToMetro, 1000);
|
||||
window.setTimeout(function() { window.clearInterval(intervalID); }, 10000);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
function onFullScreen(event) {
|
||||
FullScreen.toggle(event);
|
||||
}
|
||||
@ -4149,6 +4185,14 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let addToPanel = popup.querySelector(".customize-context-addToPanel");
|
||||
let removeFromToolbar = popup.querySelector(".customize-context-removeFromToolbar");
|
||||
// View -> Toolbars menu doesn't have the addToPanel or removeFromToolbar items.
|
||||
if (!addToPanel || !removeFromToolbar) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The explicitOriginalTarget can be a nested child element of a toolbaritem.
|
||||
let toolbarItem = aEvent.explicitOriginalTarget;
|
||||
|
||||
@ -4167,17 +4211,10 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
||||
|
||||
// Right-clicking on an empty part of the tabstrip will exit
|
||||
// the above loop with toolbarItem being the xul:document.
|
||||
if (!toolbarItem.parentNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let addToPanel = popup.querySelector(".customize-context-addToPanel");
|
||||
let removeFromToolbar = popup.querySelector(".customize-context-removeFromToolbar");
|
||||
// View -> Toolbars menu doesn't have the addToPanel or removeFromToolbar items.
|
||||
if (!addToPanel || !removeFromToolbar) {
|
||||
return;
|
||||
}
|
||||
let movable = toolbarItem && CustomizableUI.isWidgetRemovable(toolbarItem);
|
||||
// That has no parentNode, and we should disable the items in
|
||||
// this case.
|
||||
let movable = toolbarItem && toolbarItem.parentNode &&
|
||||
CustomizableUI.isWidgetRemovable(toolbarItem);
|
||||
if (movable) {
|
||||
addToPanel.removeAttribute("disabled");
|
||||
removeFromToolbar.removeAttribute("disabled");
|
||||
@ -4639,60 +4676,6 @@ function fireSidebarFocusedEvent() {
|
||||
sidebar.contentWindow.dispatchEvent(event);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
/**
|
||||
* Some prefs that have consequences in both Metro and Desktop such as
|
||||
* app-update prefs, are automatically pushed from Desktop here for use
|
||||
* in Metro.
|
||||
*/
|
||||
var gMetroPrefs = {
|
||||
prefDomain: ["app.update.auto", "app.update.enabled",
|
||||
"app.update.service.enabled",
|
||||
"app.update.metro.enabled"],
|
||||
observe: function (aSubject, aTopic, aPrefName)
|
||||
{
|
||||
if (aTopic != "nsPref:changed")
|
||||
return;
|
||||
|
||||
this.pushDesktopControlledPrefToMetro(aPrefName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes the pref to HKCU in the registry and adds a pref-observer to keep
|
||||
* the registry in sync with changes to the value.
|
||||
*/
|
||||
pushDesktopControlledPrefToMetro: function(aPrefName) {
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
var prefType = Services.prefs.getPrefType(aPrefName);
|
||||
let prefFunc;
|
||||
if (prefType == Components.interfaces.nsIPrefBranch.PREF_INT)
|
||||
prefFunc = "getIntPref";
|
||||
else if (prefType == Components.interfaces.nsIPrefBranch.PREF_BOOL)
|
||||
prefFunc = "getBoolPref";
|
||||
else if (prefType == Components.interfaces.nsIPrefBranch.PREF_STRING)
|
||||
prefFunc = "getCharPref";
|
||||
else
|
||||
throw "Unsupported pref type";
|
||||
|
||||
let prefValue = Services.prefs[prefFunc](aPrefName);
|
||||
registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Mozilla\\Firefox\\Metro\\Prefs\\" + prefType,
|
||||
Ci.nsIWindowsRegKey.ACCESS_WRITE);
|
||||
// Always write as string, but the registry subfolder will determine
|
||||
// how Metro interprets that string value.
|
||||
registry.writeStringValue(aPrefName, prefValue);
|
||||
} catch (ex) {
|
||||
Components.utils.reportError("Couldn't push pref " + aPrefName + ": " + ex);
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
var gHomeButton = {
|
||||
prefDomain: "browser.startup.homepage",
|
||||
@ -5087,7 +5070,7 @@ function MultiplexHandler(event)
|
||||
SelectDetector(event, false);
|
||||
} else if (name == 'charsetGroup') {
|
||||
var charset = node.getAttribute('id');
|
||||
charset = charset.substring('charset.'.length, charset.length)
|
||||
charset = charset.substring(charset.indexOf('charset.') + 'charset.'.length);
|
||||
BrowserSetForcedCharacterSet(charset);
|
||||
} else if (name == 'charsetCustomize') {
|
||||
//do nothing - please remove this else statement, once the charset prefs moves to the pref window
|
||||
@ -5100,7 +5083,7 @@ function MultiplexHandler(event)
|
||||
function SelectDetector(event, doReload)
|
||||
{
|
||||
var uri = event.target.getAttribute("id");
|
||||
var prefvalue = uri.substring('chardet.'.length, uri.length);
|
||||
var prefvalue = uri.substring(uri.indexOf('chardet.') + 'chardet.'.length);
|
||||
if ("off" == prefvalue) { // "off" is special value to turn off the detectors
|
||||
prefvalue = "";
|
||||
}
|
||||
|
@ -472,13 +472,6 @@ var gSyncSetup = {
|
||||
Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase();
|
||||
this._handleNoScript(false);
|
||||
Weave.Svc.Prefs.set("firstSync", "newAccount");
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
if (document.getElementById("metroSetupCheckbox").checked) {
|
||||
Services.metro.storeSyncInfo(email, password, Weave.Service.identity.syncKey);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
this.wizardFinish();
|
||||
return false;
|
||||
}
|
||||
|
@ -172,20 +172,6 @@
|
||||
<label class="status" value=" "/>
|
||||
</hbox>
|
||||
</row>
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
<row id="metroRow" align="center">
|
||||
<spacer/>
|
||||
<hbox align="center">
|
||||
<checkbox label="&setup.setupMetro.label;"
|
||||
accesskey="&setup.setupMetro.accesskey;"
|
||||
control="weavePasswordConfirm"
|
||||
id="metroSetupCheckbox"
|
||||
checked="true"/>
|
||||
</hbox>
|
||||
</row>
|
||||
#endif
|
||||
#endif
|
||||
<row id="TOSRow" align="center">
|
||||
<spacer/>
|
||||
<hbox align="center">
|
||||
|
@ -220,8 +220,11 @@ const PanelUI = {
|
||||
CustomizableUI.registerMenuPanel(this.contents);
|
||||
} else {
|
||||
this.beginBatchUpdate();
|
||||
CustomizableUI.registerMenuPanel(this.contents);
|
||||
this.endBatchUpdate();
|
||||
try {
|
||||
CustomizableUI.registerMenuPanel(this.contents);
|
||||
} finally {
|
||||
this.endBatchUpdate();
|
||||
}
|
||||
}
|
||||
this.panel.hidden = false;
|
||||
}.bind(this)).then(null, Cu.reportError);
|
||||
|
@ -193,29 +193,32 @@
|
||||
// Get a list of items only in the new list
|
||||
let newIds = [id for (id of newVal) if (oldIds.indexOf(id) == -1)];
|
||||
CustomizableUI.beginBatchUpdate();
|
||||
for (let newId of newIds) {
|
||||
oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
|
||||
let nextId = newId;
|
||||
let pos;
|
||||
do {
|
||||
// Get the next item
|
||||
nextId = newVal[newVal.indexOf(nextId) + 1];
|
||||
// Figure out where it is in the old list
|
||||
pos = oldIds.indexOf(nextId);
|
||||
// If it's not in the old list, repeat:
|
||||
} while (pos == -1 && nextId);
|
||||
if (pos == -1) {
|
||||
pos = null; // We didn't find anything, insert at the end
|
||||
try {
|
||||
for (let newId of newIds) {
|
||||
oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
|
||||
let nextId = newId;
|
||||
let pos;
|
||||
do {
|
||||
// Get the next item
|
||||
nextId = newVal[newVal.indexOf(nextId) + 1];
|
||||
// Figure out where it is in the old list
|
||||
pos = oldIds.indexOf(nextId);
|
||||
// If it's not in the old list, repeat:
|
||||
} while (pos == -1 && nextId);
|
||||
if (pos == -1) {
|
||||
pos = null; // We didn't find anything, insert at the end
|
||||
}
|
||||
CustomizableUI.addWidgetToArea(newId, this.id, pos);
|
||||
}
|
||||
CustomizableUI.addWidgetToArea(newId, this.id, pos);
|
||||
}
|
||||
|
||||
let currentIds = this.currentSet.split(',');
|
||||
let removedIds = [id for (id of currentIds) if (newIds.indexOf(id) == -1 && newVal.indexOf(id) == -1)];
|
||||
for (let removedId of removedIds) {
|
||||
CustomizableUI.removeWidgetFromArea(removedId);
|
||||
let currentIds = this.currentSet.split(',');
|
||||
let removedIds = [id for (id of currentIds) if (newIds.indexOf(id) == -1 && newVal.indexOf(id) == -1)];
|
||||
for (let removedId of removedIds) {
|
||||
CustomizableUI.removeWidgetFromArea(removedId);
|
||||
}
|
||||
} finally {
|
||||
CustomizableUI.endBatchUpdate();
|
||||
}
|
||||
CustomizableUI.endBatchUpdate();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
|
@ -141,8 +141,28 @@ let CustomizableUIInternal = {
|
||||
"fullscreen-button",
|
||||
"find-button",
|
||||
"preferences-button",
|
||||
"add-ons-button",
|
||||
"add-ons-button"
|
||||
];
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
// Show switch-to-metro-button if in Windows 8.
|
||||
let isMetroCapable = false;
|
||||
try {
|
||||
// Windows 8 is version 6.2.
|
||||
let version = Cc["@mozilla.org/system-info;1"]
|
||||
.getService(Ci.nsIPropertyBag2)
|
||||
.getProperty("version");
|
||||
isMetroCapable = (parseFloat(version) >= 6.2);
|
||||
} catch (ex) { }
|
||||
|
||||
if (isMetroCapable) {
|
||||
// TODO: Bug 942915 - Place 'Metro Mode' button as a default
|
||||
// for Windows 8 in the customization panel.
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
let showCharacterEncoding = Services.prefs.getComplexValue(
|
||||
"browser.menu.showCharacterEncoding",
|
||||
Ci.nsIPrefLocalizedString
|
||||
@ -279,15 +299,18 @@ let CustomizableUIInternal = {
|
||||
|
||||
// Move all the widgets out
|
||||
this.beginBatchUpdate();
|
||||
let placements = gPlacements.get(aName);
|
||||
placements.forEach(this.removeWidgetFromArea, this);
|
||||
try {
|
||||
let placements = gPlacements.get(aName);
|
||||
placements.forEach(this.removeWidgetFromArea, this);
|
||||
|
||||
// Delete all remaining traces.
|
||||
gAreas.delete(aName);
|
||||
gPlacements.delete(aName);
|
||||
gFuturePlacements.delete(aName);
|
||||
gBuildAreas.delete(aName);
|
||||
this.endBatchUpdate(true);
|
||||
// Delete all remaining traces.
|
||||
gAreas.delete(aName);
|
||||
gPlacements.delete(aName);
|
||||
gFuturePlacements.delete(aName);
|
||||
gBuildAreas.delete(aName);
|
||||
} finally {
|
||||
this.endBatchUpdate(true);
|
||||
}
|
||||
},
|
||||
|
||||
registerToolbarNode: function(aToolbar, aExistingChildren) {
|
||||
@ -295,7 +318,6 @@ let CustomizableUIInternal = {
|
||||
if (gBuildAreas.has(area) && gBuildAreas.get(area).has(aToolbar)) {
|
||||
return;
|
||||
}
|
||||
this.beginBatchUpdate();
|
||||
let document = aToolbar.ownerDocument;
|
||||
let areaProperties = gAreas.get(area);
|
||||
|
||||
@ -303,44 +325,48 @@ let CustomizableUIInternal = {
|
||||
throw new Error("Unknown customization area: " + area);
|
||||
}
|
||||
|
||||
let placements = gPlacements.get(area);
|
||||
if (!placements && areaProperties.has("legacy")) {
|
||||
let legacyState = aToolbar.getAttribute("currentset");
|
||||
if (legacyState) {
|
||||
legacyState = legacyState.split(",").filter(s => s);
|
||||
this.beginBatchUpdate();
|
||||
try {
|
||||
let placements = gPlacements.get(area);
|
||||
if (!placements && areaProperties.has("legacy")) {
|
||||
let legacyState = aToolbar.getAttribute("currentset");
|
||||
if (legacyState) {
|
||||
legacyState = legacyState.split(",").filter(s => s);
|
||||
}
|
||||
|
||||
// Manually restore the state here, so the legacy state can be converted.
|
||||
this.restoreStateForArea(area, legacyState);
|
||||
placements = gPlacements.get(area);
|
||||
}
|
||||
|
||||
// Manually restore the state here, so the legacy state can be converted.
|
||||
this.restoreStateForArea(area, legacyState);
|
||||
placements = gPlacements.get(area);
|
||||
}
|
||||
// Check that the current children and the current placements match. If
|
||||
// not, mark it as dirty:
|
||||
if (aExistingChildren.length != placements.length ||
|
||||
aExistingChildren.every((id, i) => id == placements[i])) {
|
||||
gDirtyAreaCache.add(area);
|
||||
}
|
||||
|
||||
// Check that the current children and the current placements match. If
|
||||
// not, mark it as dirty:
|
||||
if (aExistingChildren.length != placements.length ||
|
||||
aExistingChildren.every((id, i) => id == placements[i])) {
|
||||
gDirtyAreaCache.add(area);
|
||||
}
|
||||
if (areaProperties.has("overflowable")) {
|
||||
aToolbar.overflowable = new OverflowableToolbar(aToolbar);
|
||||
}
|
||||
|
||||
if (areaProperties.has("overflowable")) {
|
||||
aToolbar.overflowable = new OverflowableToolbar(aToolbar);
|
||||
}
|
||||
this.registerBuildArea(area, aToolbar);
|
||||
|
||||
this.registerBuildArea(area, aToolbar);
|
||||
|
||||
// We only build the toolbar if it's been marked as "dirty". Dirty means
|
||||
// one of the following things:
|
||||
// 1) Items have been added, moved or removed from this toolbar before.
|
||||
// 2) The number of children of the toolbar does not match the length of
|
||||
// the placements array for that area.
|
||||
//
|
||||
// This notion of being "dirty" is stored in a cache which is persisted
|
||||
// in the saved state.
|
||||
if (gDirtyAreaCache.has(area)) {
|
||||
this.buildArea(area, placements, aToolbar);
|
||||
// We only build the toolbar if it's been marked as "dirty". Dirty means
|
||||
// one of the following things:
|
||||
// 1) Items have been added, moved or removed from this toolbar before.
|
||||
// 2) The number of children of the toolbar does not match the length of
|
||||
// the placements array for that area.
|
||||
//
|
||||
// This notion of being "dirty" is stored in a cache which is persisted
|
||||
// in the saved state.
|
||||
if (gDirtyAreaCache.has(area)) {
|
||||
this.buildArea(area, placements, aToolbar);
|
||||
}
|
||||
aToolbar.setAttribute("currentset", placements.join(","));
|
||||
} finally {
|
||||
this.endBatchUpdate();
|
||||
}
|
||||
aToolbar.setAttribute("currentset", placements.join(","));
|
||||
this.endBatchUpdate();
|
||||
},
|
||||
|
||||
buildArea: function(aArea, aPlacements, aAreaNode) {
|
||||
@ -354,110 +380,112 @@ let CustomizableUIInternal = {
|
||||
+ " to have a customizationTarget attribute.");
|
||||
}
|
||||
|
||||
this.beginBatchUpdate();
|
||||
|
||||
// Restore nav-bar visibility since it may have been hidden
|
||||
// through a migration path (bug 938980) or an add-on.
|
||||
if (aArea == CustomizableUI.AREA_NAVBAR) {
|
||||
aAreaNode.collapsed = false;
|
||||
}
|
||||
|
||||
let currentNode = container.firstChild;
|
||||
let placementsToRemove = new Set();
|
||||
for (let id of aPlacements) {
|
||||
while (currentNode && currentNode.getAttribute("skipintoolbarset") == "true") {
|
||||
currentNode = currentNode.nextSibling;
|
||||
}
|
||||
this.beginBatchUpdate();
|
||||
|
||||
if (currentNode && currentNode.id == id) {
|
||||
currentNode = currentNode.nextSibling;
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
let currentNode = container.firstChild;
|
||||
let placementsToRemove = new Set();
|
||||
for (let id of aPlacements) {
|
||||
while (currentNode && currentNode.getAttribute("skipintoolbarset") == "true") {
|
||||
currentNode = currentNode.nextSibling;
|
||||
}
|
||||
|
||||
let [provider, node] = this.getWidgetNode(id, window);
|
||||
if (!node) {
|
||||
LOG("Unknown widget: " + id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the placements have items in them which are (now) no longer removable,
|
||||
// we shouldn't be moving them:
|
||||
if (node.parentNode != container && !this.isWidgetRemovable(node)) {
|
||||
placementsToRemove.add(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inPrivateWindow && provider == CustomizableUI.PROVIDER_API) {
|
||||
let widget = gPalette.get(id);
|
||||
if (!widget.showInPrivateBrowsing && inPrivateWindow) {
|
||||
if (currentNode && currentNode.id == id) {
|
||||
currentNode = currentNode.nextSibling;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.ensureButtonContextMenu(node, aAreaNode);
|
||||
if (node.localName == "toolbarbutton" && aArea == CustomizableUI.AREA_PANEL) {
|
||||
node.setAttribute("tabindex", "0");
|
||||
if (!node.hasAttribute("type")) {
|
||||
node.setAttribute("type", "wrap");
|
||||
let [provider, node] = this.getWidgetNode(id, window);
|
||||
if (!node) {
|
||||
LOG("Unknown widget: " + id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.insertWidgetBefore(node, currentNode, container, aArea);
|
||||
if (gResetting) {
|
||||
this.notifyListeners("onWidgetReset", id, aArea);
|
||||
}
|
||||
}
|
||||
// If the placements have items in them which are (now) no longer removable,
|
||||
// we shouldn't be moving them:
|
||||
if (node.parentNode != container && !this.isWidgetRemovable(node)) {
|
||||
placementsToRemove.add(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentNode) {
|
||||
let palette = aAreaNode.toolbox ? aAreaNode.toolbox.palette : null;
|
||||
let limit = currentNode.previousSibling;
|
||||
let node = container.lastChild;
|
||||
while (node && node != limit) {
|
||||
let previousSibling = node.previousSibling;
|
||||
// Nodes opt-in to removability. If they're removable, and we haven't
|
||||
// seen them in the placements array, then we toss them into the palette
|
||||
// if one exists. If no palette exists, we just remove the node. If the
|
||||
// node is not removable, we leave it where it is. However, we can only
|
||||
// safely touch elements that have an ID - both because we depend on
|
||||
// IDs, and because such elements are not intended to be widgets
|
||||
// (eg, titlebar-placeholder elements).
|
||||
if (node.id && node.getAttribute("skipintoolbarset") != "true") {
|
||||
if (this.isWidgetRemovable(node)) {
|
||||
if (palette && !this.isSpecialWidget(node.id)) {
|
||||
palette.appendChild(node);
|
||||
this.removeLocationAttributes(node);
|
||||
} else {
|
||||
container.removeChild(node);
|
||||
}
|
||||
} else {
|
||||
this.setLocationAttributes(currentNode, aArea);
|
||||
node.setAttribute("removable", false);
|
||||
LOG("Adding non-removable widget to placements of " + aArea + ": " +
|
||||
node.id);
|
||||
gPlacements.get(aArea).push(node.id);
|
||||
gDirty = true;
|
||||
if (inPrivateWindow && provider == CustomizableUI.PROVIDER_API) {
|
||||
let widget = gPalette.get(id);
|
||||
if (!widget.showInPrivateBrowsing && inPrivateWindow) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
node = previousSibling;
|
||||
|
||||
this.ensureButtonContextMenu(node, aAreaNode);
|
||||
if (node.localName == "toolbarbutton" && aArea == CustomizableUI.AREA_PANEL) {
|
||||
node.setAttribute("tabindex", "0");
|
||||
if (!node.hasAttribute("type")) {
|
||||
node.setAttribute("type", "wrap");
|
||||
}
|
||||
}
|
||||
|
||||
this.insertWidgetBefore(node, currentNode, container, aArea);
|
||||
if (gResetting) {
|
||||
this.notifyListeners("onWidgetReset", id, aArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are placements in here which aren't removable from their original area,
|
||||
// we remove them from this area's placement array. They will (have) be(en) added
|
||||
// to their original area's placements array in the block above this one.
|
||||
if (placementsToRemove.size) {
|
||||
let placementAry = gPlacements.get(aArea);
|
||||
for (let id of placementsToRemove) {
|
||||
let index = placementAry.indexOf(id);
|
||||
placementAry.splice(index, 1);
|
||||
if (currentNode) {
|
||||
let palette = aAreaNode.toolbox ? aAreaNode.toolbox.palette : null;
|
||||
let limit = currentNode.previousSibling;
|
||||
let node = container.lastChild;
|
||||
while (node && node != limit) {
|
||||
let previousSibling = node.previousSibling;
|
||||
// Nodes opt-in to removability. If they're removable, and we haven't
|
||||
// seen them in the placements array, then we toss them into the palette
|
||||
// if one exists. If no palette exists, we just remove the node. If the
|
||||
// node is not removable, we leave it where it is. However, we can only
|
||||
// safely touch elements that have an ID - both because we depend on
|
||||
// IDs, and because such elements are not intended to be widgets
|
||||
// (eg, titlebar-placeholder elements).
|
||||
if (node.id && node.getAttribute("skipintoolbarset") != "true") {
|
||||
if (this.isWidgetRemovable(node)) {
|
||||
if (palette && !this.isSpecialWidget(node.id)) {
|
||||
palette.appendChild(node);
|
||||
this.removeLocationAttributes(node);
|
||||
} else {
|
||||
container.removeChild(node);
|
||||
}
|
||||
} else {
|
||||
this.setLocationAttributes(currentNode, aArea);
|
||||
node.setAttribute("removable", false);
|
||||
LOG("Adding non-removable widget to placements of " + aArea + ": " +
|
||||
node.id);
|
||||
gPlacements.get(aArea).push(node.id);
|
||||
gDirty = true;
|
||||
}
|
||||
}
|
||||
node = previousSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gResetting) {
|
||||
this.notifyListeners("onAreaReset", aArea);
|
||||
}
|
||||
// If there are placements in here which aren't removable from their original area,
|
||||
// we remove them from this area's placement array. They will (have) be(en) added
|
||||
// to their original area's placements array in the block above this one.
|
||||
if (placementsToRemove.size) {
|
||||
let placementAry = gPlacements.get(aArea);
|
||||
for (let id of placementsToRemove) {
|
||||
let index = placementAry.indexOf(id);
|
||||
placementAry.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.endBatchUpdate();
|
||||
if (gResetting) {
|
||||
this.notifyListeners("onAreaReset", aArea);
|
||||
}
|
||||
} finally {
|
||||
this.endBatchUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
addPanelCloseListeners: function(aPanel) {
|
||||
@ -958,6 +986,12 @@ let CustomizableUIInternal = {
|
||||
"' not found!");
|
||||
}
|
||||
}
|
||||
|
||||
if (aWidget.id == "switch-to-metro-button") {
|
||||
let brandBundle = aDocument.getElementById("bundle_brand");
|
||||
let brandShortName = brandBundle.getString("brandShortName");
|
||||
additionalTooltipArguments = [brandShortName];
|
||||
}
|
||||
let tooltip = this.getLocalizedProperty(aWidget, "tooltiptext", additionalTooltipArguments);
|
||||
node.setAttribute("tooltiptext", tooltip);
|
||||
node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional");
|
||||
@ -1382,51 +1416,54 @@ let CustomizableUIInternal = {
|
||||
}
|
||||
|
||||
this.beginBatchUpdate();
|
||||
gRestoring = true;
|
||||
try {
|
||||
gRestoring = true;
|
||||
|
||||
let restored = false;
|
||||
gPlacements.set(aArea, []);
|
||||
let restored = false;
|
||||
gPlacements.set(aArea, []);
|
||||
|
||||
if (gSavedState && aArea in gSavedState.placements) {
|
||||
LOG("Restoring " + aArea + " from saved state");
|
||||
let placements = gSavedState.placements[aArea];
|
||||
for (let id of placements)
|
||||
this.addWidgetToArea(id, aArea);
|
||||
gDirty = false;
|
||||
restored = true;
|
||||
}
|
||||
|
||||
if (!restored && aLegacyState) {
|
||||
LOG("Restoring " + aArea + " from legacy state");
|
||||
for (let id of aLegacyState)
|
||||
this.addWidgetToArea(id, aArea);
|
||||
// Don't override dirty state, to ensure legacy state is saved here and
|
||||
// therefore only used once.
|
||||
restored = true;
|
||||
}
|
||||
|
||||
if (!restored) {
|
||||
LOG("Restoring " + aArea + " from default state");
|
||||
let defaults = gAreas.get(aArea).get("defaultPlacements");
|
||||
if (defaults) {
|
||||
for (let id of defaults)
|
||||
this.addWidgetToArea(id, aArea, null, true);
|
||||
if (gSavedState && aArea in gSavedState.placements) {
|
||||
LOG("Restoring " + aArea + " from saved state");
|
||||
let placements = gSavedState.placements[aArea];
|
||||
for (let id of placements)
|
||||
this.addWidgetToArea(id, aArea);
|
||||
gDirty = false;
|
||||
restored = true;
|
||||
}
|
||||
gDirty = false;
|
||||
|
||||
if (!restored && aLegacyState) {
|
||||
LOG("Restoring " + aArea + " from legacy state");
|
||||
for (let id of aLegacyState)
|
||||
this.addWidgetToArea(id, aArea);
|
||||
// Don't override dirty state, to ensure legacy state is saved here and
|
||||
// therefore only used once.
|
||||
restored = true;
|
||||
}
|
||||
|
||||
if (!restored) {
|
||||
LOG("Restoring " + aArea + " from default state");
|
||||
let defaults = gAreas.get(aArea).get("defaultPlacements");
|
||||
if (defaults) {
|
||||
for (let id of defaults)
|
||||
this.addWidgetToArea(id, aArea, null, true);
|
||||
}
|
||||
gDirty = false;
|
||||
}
|
||||
|
||||
// Finally, add widgets to the area that were added before the it was able
|
||||
// to be restored. This can occur when add-ons register widgets for a
|
||||
// lazily-restored area before it's been restored.
|
||||
if (gFuturePlacements.has(aArea)) {
|
||||
for (let id of gFuturePlacements.get(aArea))
|
||||
this.addWidgetToArea(id, aArea);
|
||||
}
|
||||
|
||||
LOG("Placements for " + aArea + ":\n\t" + gPlacements.get(aArea).join("\n\t"));
|
||||
|
||||
gRestoring = false;
|
||||
} finally {
|
||||
this.endBatchUpdate();
|
||||
}
|
||||
|
||||
// Finally, add widgets to the area that were added before the it was able
|
||||
// to be restored. This can occur when add-ons register widgets for a
|
||||
// lazily-restored area before it's been restored.
|
||||
if (gFuturePlacements.has(aArea)) {
|
||||
for (let id of gFuturePlacements.get(aArea))
|
||||
this.addWidgetToArea(id, aArea);
|
||||
}
|
||||
|
||||
LOG("Placements for " + aArea + ":\n\t" + gPlacements.get(aArea).join("\n\t"));
|
||||
|
||||
gRestoring = false;
|
||||
this.endBatchUpdate();
|
||||
},
|
||||
|
||||
saveState: function() {
|
||||
@ -1581,17 +1618,19 @@ let CustomizableUIInternal = {
|
||||
// seen before, then add it to its default area so it can be used.
|
||||
if (autoAdd && !widget.currentArea && !gSeenWidgets.has(widget.id)) {
|
||||
this.beginBatchUpdate();
|
||||
gSeenWidgets.add(widget.id);
|
||||
try {
|
||||
gSeenWidgets.add(widget.id);
|
||||
|
||||
if (widget.defaultArea) {
|
||||
if (this.isAreaLazy(widget.defaultArea)) {
|
||||
gFuturePlacements.get(widget.defaultArea).add(widget.id);
|
||||
} else {
|
||||
this.addWidgetToArea(widget.id, widget.defaultArea);
|
||||
if (widget.defaultArea) {
|
||||
if (this.isAreaLazy(widget.defaultArea)) {
|
||||
gFuturePlacements.get(widget.defaultArea).add(widget.id);
|
||||
} else {
|
||||
this.addWidgetToArea(widget.id, widget.defaultArea);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.endBatchUpdate(true);
|
||||
}
|
||||
|
||||
this.endBatchUpdate(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1642,6 +1681,10 @@ let CustomizableUIInternal = {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (aData.id == "switch-to-metro-button") {
|
||||
widget.showInPrivateBrowsing = false;
|
||||
}
|
||||
|
||||
delete widget.implementation.currentArea;
|
||||
widget.implementation.__defineGetter__("currentArea", function() widget.currentArea);
|
||||
|
||||
|
@ -259,6 +259,18 @@ const CustomizableWidgets = [{
|
||||
aEvent.target.removeEventListener("command",
|
||||
win.PanelUI.onCommandHandler);
|
||||
}
|
||||
}, {
|
||||
id: "switch-to-metro-button",
|
||||
removable: true,
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.target &&
|
||||
aEvent.target.ownerDocument &&
|
||||
aEvent.target.ownerDocument.defaultView;
|
||||
if (win && typeof win.SwitchToMetro == "function") {
|
||||
win.SwitchToMetro();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: "add-ons-button",
|
||||
removable: true,
|
||||
|
@ -93,6 +93,9 @@ CustomizeMode.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let window = this.window;
|
||||
let document = this.document;
|
||||
|
||||
Task.spawn(function() {
|
||||
// We shouldn't start customize mode until after browser-delayed-startup has finished:
|
||||
if (!this.window.gBrowserInit.delayedStartupFinished) {
|
||||
@ -115,9 +118,6 @@ CustomizeMode.prototype = {
|
||||
this.dispatchToolboxEvent("beforecustomization");
|
||||
CustomizableUI.notifyStartCustomizing(this.window);
|
||||
|
||||
let window = this.window;
|
||||
let document = this.document;
|
||||
|
||||
// Add a keypress listener to the document so that we can quickly exit
|
||||
// customization mode when pressing ESC.
|
||||
document.addEventListener("keypress", this);
|
||||
@ -159,7 +159,6 @@ CustomizeMode.prototype = {
|
||||
}
|
||||
|
||||
this._showPanelCustomizationPlaceholders();
|
||||
CustomizableUI.addListener(this);
|
||||
|
||||
yield this._wrapToolbarItems();
|
||||
yield this.populatePalette();
|
||||
@ -184,11 +183,16 @@ CustomizeMode.prototype = {
|
||||
for (let toolbar of customizableToolbars)
|
||||
toolbar.setAttribute("customizing", true);
|
||||
|
||||
CustomizableUI.addListener(this);
|
||||
window.PanelUI.endBatchUpdate();
|
||||
this._customizing = true;
|
||||
this._transitioning = false;
|
||||
this.dispatchToolboxEvent("customizationready");
|
||||
}.bind(this)).then(null, ERROR);
|
||||
}.bind(this)).then(null, function(e) {
|
||||
ERROR(e);
|
||||
// We should ensure this has been called, and calling it again doesn't hurt:
|
||||
window.PanelUI.endBatchUpdate();
|
||||
});
|
||||
},
|
||||
|
||||
exit: function() {
|
||||
@ -298,7 +302,11 @@ CustomizeMode.prototype = {
|
||||
this._transitioning = false;
|
||||
this.dispatchToolboxEvent("aftercustomization");
|
||||
CustomizableUI.notifyEndCustomizing(this.window);
|
||||
}.bind(this)).then(null, ERROR);
|
||||
}.bind(this)).then(null, function(e) {
|
||||
ERROR(e);
|
||||
// We should ensure this has been called, and calling it again doesn't hurt:
|
||||
window.PanelUI.endBatchUpdate();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1591,7 +1591,7 @@ BrowserGlue.prototype = {
|
||||
// be set to the version it has been added in, we will compare its value
|
||||
// to users' smartBookmarksVersion and add new smart bookmarks without
|
||||
// recreating old deleted ones.
|
||||
const SMART_BOOKMARKS_VERSION = 4;
|
||||
const SMART_BOOKMARKS_VERSION = 5;
|
||||
const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
|
||||
const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
|
||||
|
||||
@ -1652,7 +1652,21 @@ BrowserGlue.prototype = {
|
||||
parent: PlacesUtils.bookmarksMenuFolderId,
|
||||
position: menuIndex++,
|
||||
newInVersion: 1
|
||||
}
|
||||
},
|
||||
FirefoxTouch: {
|
||||
title: bundle.GetStringFromName("firefoxTouchTitle"),
|
||||
uri: NetUtil.newURI("place:folder=" +
|
||||
PlacesUtils.annotations.getItemsWithAnnotation('metro/bookmarksRoot', {})[0] +
|
||||
"&queryType=" +
|
||||
Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
|
||||
"&sort=" +
|
||||
Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
|
||||
"&maxResults=" + MAX_RESULTS +
|
||||
"&excludeQueries=1"),
|
||||
parent: PlacesUtils.bookmarksMenuFolderId,
|
||||
position: menuIndex++,
|
||||
newInVersion: 5
|
||||
},
|
||||
};
|
||||
|
||||
// Set current itemId, parent and position if Smart Bookmark exists,
|
||||
|
@ -63,9 +63,9 @@ let (XULAppInfo = {
|
||||
}
|
||||
|
||||
// Smart bookmarks constants.
|
||||
const SMART_BOOKMARKS_VERSION = 4;
|
||||
const SMART_BOOKMARKS_VERSION = 5;
|
||||
const SMART_BOOKMARKS_ON_TOOLBAR = 1;
|
||||
const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator.
|
||||
const SMART_BOOKMARKS_ON_MENU = 4; // Takes in count the additional separator.
|
||||
|
||||
// Default bookmarks constants.
|
||||
const DEFAULT_BOOKMARKS_ON_TOOLBAR = 1;
|
||||
|
@ -650,6 +650,16 @@ let SessionStoreInternal = {
|
||||
TabState.onBrowserContentsSwapped(browser, otherBrowser);
|
||||
TabStateCache.onBrowserContentsSwapped(browser, otherBrowser);
|
||||
break;
|
||||
case "UserTypedValueChanged":
|
||||
browser = aEvent.currentTarget;
|
||||
if (browser.userTypedValue) {
|
||||
TabStateCache.updateField(browser, "userTypedValue", browser.userTypedValue);
|
||||
TabStateCache.updateField(browser, "userTypedClear", browser.userTypedClear);
|
||||
} else {
|
||||
TabStateCache.removeField(browser, "userTypedValue");
|
||||
TabStateCache.removeField(browser, "userTypedClear");
|
||||
}
|
||||
break;
|
||||
case "TabOpen":
|
||||
this.onTabAdd(win, aEvent.originalTarget);
|
||||
break;
|
||||
@ -1235,6 +1245,7 @@ let SessionStoreInternal = {
|
||||
let browser = aTab.linkedBrowser;
|
||||
browser.addEventListener("load", this, true);
|
||||
browser.addEventListener("SwapDocShells", this, true);
|
||||
browser.addEventListener("UserTypedValueChanged", this, true);
|
||||
|
||||
let mm = browser.messageManager;
|
||||
MESSAGES.forEach(msg => mm.addMessageListener(msg, this));
|
||||
@ -1262,6 +1273,7 @@ let SessionStoreInternal = {
|
||||
let browser = aTab.linkedBrowser;
|
||||
browser.removeEventListener("load", this, true);
|
||||
browser.removeEventListener("SwapDocShells", this, true);
|
||||
browser.removeEventListener("UserTypedValueChanged", this, true);
|
||||
|
||||
let mm = browser.messageManager;
|
||||
MESSAGES.forEach(msg => mm.removeMessageListener(msg, this));
|
||||
|
@ -236,7 +236,6 @@ let TabStateCacheInternal = {
|
||||
if (data) {
|
||||
data[aField] = aValue;
|
||||
}
|
||||
TabStateCacheTelemetry.recordAccess(!!data);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -252,7 +251,6 @@ let TabStateCacheInternal = {
|
||||
if (data && aField in data) {
|
||||
delete data[aField];
|
||||
}
|
||||
TabStateCacheTelemetry.recordAccess(!!data);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -189,14 +189,17 @@ let DebuggerView = {
|
||||
dumpn("Initializing the DebuggerView editor");
|
||||
|
||||
let extraKeys = {};
|
||||
let tokenSearch = document.getElementById("tokenSearchKey").getAttribute("key");
|
||||
let globalSearch = document.getElementById("globalSearchKey").getAttribute("key");
|
||||
let tokenSearchShortcut = Editor.accel(tokenSearch);
|
||||
let globalSearchShortcut = Editor.accel(globalSearch, { alt: true });
|
||||
extraKeys[tokenSearchShortcut] = () => this.Filtering._doTokenSearch();
|
||||
extraKeys[globalSearchShortcut] = () => this.Filtering._doGlobalSearch();
|
||||
bindKey("_doTokenSearch", "tokenSearchKey");
|
||||
bindKey("_doGlobalSearch", "globalSearchKey", { alt: true });
|
||||
bindKey("_doFunctionSearch", "functionSearchKey");
|
||||
extraKeys[Editor.keyFor("jumpToLine")] = false;
|
||||
|
||||
function bindKey(func, key, modifiers = {}) {
|
||||
let key = document.getElementById(key).getAttribute("key");
|
||||
let shortcut = Editor.accel(key, modifiers);
|
||||
extraKeys[shortcut] = () => DebuggerView.Filtering[func]();
|
||||
}
|
||||
|
||||
this.editor = new Editor({
|
||||
mode: Editor.modes.text,
|
||||
readOnly: true,
|
||||
|
@ -258,7 +258,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||
<!ENTITY devToolbar.keytext "F2">
|
||||
<!ENTITY devToolboxMenuItem.label "Toggle Tools">
|
||||
<!ENTITY devToolboxMenuItem.accesskey "T">
|
||||
<!ENTITY devToolboxMenuItem.keycode "I">
|
||||
<!ENTITY devToolboxMenuItem.keytext "I">
|
||||
|
||||
<!ENTITY devToolbarToolsButton.tooltip "Toggle developer tools">
|
||||
@ -434,6 +433,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||
<!ENTITY bookmarkThisFrameCmd.accesskey "m">
|
||||
<!ENTITY emailPageCmd.label "Email Link…">
|
||||
<!ENTITY emailPageCmd.accesskey "E">
|
||||
<!ENTITY switchToMetroCmd.label "Relaunch in Windows 8 style &brandShortName;">
|
||||
<!ENTITY savePageCmd.label "Save Page As…">
|
||||
<!ENTITY savePageCmd.accesskey "A">
|
||||
<!-- alternate for content area context menu -->
|
||||
|
@ -31,6 +31,10 @@ add-ons-button.label = Add-ons
|
||||
# LOCALIZATION NOTE(add-ons-button.tooltiptext): %S is the keyboard shortcut
|
||||
add-ons-button.tooltiptext = Add-ons Manager (%S)
|
||||
|
||||
switch-to-metro-button.label = Metro Mode
|
||||
# LOCALIZATION NOTE(switch-to-metro-button.tooltiptext): %S is the brand short name
|
||||
switch-to-metro-button.tooltiptext = Relaunch in Windows 8 style %S
|
||||
|
||||
preferences-button.label = Preferences
|
||||
# LOCALIZATION NOTE (preferences-button.tooltiptext): Use the unicode ellipsis char,
|
||||
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
|
@ -70,6 +70,7 @@ detailsPane.itemsCountLabel=One item;#1 items
|
||||
mostVisitedTitle=Most Visited
|
||||
recentlyBookmarkedTitle=Recently Bookmarked
|
||||
recentTagsTitle=Recent Tags
|
||||
firefoxTouchTitle=Firefox Touch
|
||||
|
||||
OrganizerQueryHistory=History
|
||||
OrganizerQueryDownloads=Downloads
|
||||
|
@ -33,8 +33,6 @@
|
||||
<!ENTITY setup.choosePassword.accesskey "P">
|
||||
<!ENTITY setup.confirmPassword.label "Confirm Password">
|
||||
<!ENTITY setup.confirmPassword.accesskey "m">
|
||||
<!ENTITY setup.setupMetro.label "Sync with Windows 8 style &brandShortName;">
|
||||
<!ENTITY setup.setupMetro.accesskey "S">
|
||||
|
||||
<!-- LOCALIZATION NOTE: tosAgree1, tosLink, tosAgree2, ppLink, tosAgree3 are
|
||||
joined with implicit white space, so spaces in the strings aren't necessary -->
|
||||
|
@ -8,7 +8,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
# application.ini
|
||||
|
||||
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID)
|
||||
DEFINES += -DGRE_BUILDID=$(GRE_BUILDID) -DMOZ_APP_BASENAME=$(MOZ_APP_BASENAME)
|
||||
|
||||
# 'application.ini' breaks firefox build config. So we use something different.
|
||||
metroapp.ini: metroapp.ini.in $(DEPTH)/config/buildid $(topsrcdir)/config/milestone.txt
|
||||
|
@ -126,16 +126,7 @@ var Appbar = {
|
||||
if (!Services.metro.immersive)
|
||||
typesArray.push("open-jsshell");
|
||||
|
||||
try {
|
||||
// If we have a valid http or https URI then show the view on desktop
|
||||
// menu item.
|
||||
let uri = Services.io.newURI(Browser.selectedBrowser.currentURI.spec,
|
||||
null, null);
|
||||
if (uri.schemeIs('http') || uri.schemeIs('https')) {
|
||||
typesArray.push("view-on-desktop");
|
||||
}
|
||||
} catch(ex) {
|
||||
}
|
||||
typesArray.push("view-on-desktop");
|
||||
|
||||
var x = this.menuButton.getBoundingClientRect().left;
|
||||
var y = Elements.toolbar.getBoundingClientRect().top;
|
||||
@ -153,16 +144,12 @@ var Appbar = {
|
||||
},
|
||||
|
||||
onViewOnDesktop: function() {
|
||||
try {
|
||||
// Make sure we have a valid URI so Windows doesn't prompt
|
||||
// with an unrecognized command, select default program window
|
||||
var uri = Services.io.newURI(Browser.selectedBrowser.currentURI.spec,
|
||||
null, null);
|
||||
if (uri.schemeIs('http') || uri.schemeIs('https')) {
|
||||
Services.metro.launchInDesktop(Browser.selectedBrowser.currentURI.spec, "");
|
||||
}
|
||||
} catch(ex) {
|
||||
}
|
||||
let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
|
||||
getService(Components.interfaces.nsIAppStartup);
|
||||
|
||||
Services.prefs.setBoolPref('browser.sessionstore.resume_session_once', true);
|
||||
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
|
||||
Components.interfaces.nsIAppStartup.eRestart);
|
||||
},
|
||||
|
||||
onAutocompleteCloseButton: function () {
|
||||
|
@ -5,6 +5,7 @@
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm")
|
||||
Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
|
||||
|
||||
/**
|
||||
* Constants
|
||||
@ -153,7 +154,10 @@ var BrowserUI = {
|
||||
Util.dumpLn("Exception in delay load module:", ex.message);
|
||||
}
|
||||
|
||||
BrowserUI._pullDesktopControlledPrefs();
|
||||
if (WindowsPrefSync) {
|
||||
// Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
|
||||
WindowsPrefSync.init();
|
||||
}
|
||||
|
||||
// check for left over crash reports and submit them if found.
|
||||
BrowserUI.startupCrashCheck();
|
||||
@ -189,6 +193,9 @@ var BrowserUI = {
|
||||
MetroDownloadsView.uninit();
|
||||
SettingsCharm.uninit();
|
||||
PageThumbs.uninit();
|
||||
if (WindowsPrefSync) {
|
||||
WindowsPrefSync.uninit();
|
||||
}
|
||||
this.stopDebugServer();
|
||||
},
|
||||
|
||||
@ -638,37 +645,6 @@ var BrowserUI = {
|
||||
* Internal utils
|
||||
*/
|
||||
|
||||
/**
|
||||
* Some prefs that have consequences in both Metro and Desktop such as
|
||||
* app-update prefs, are automatically pulled from Desktop here.
|
||||
*/
|
||||
_pullDesktopControlledPrefs: function() {
|
||||
function pullDesktopControlledPrefType(prefType, prefFunc) {
|
||||
try {
|
||||
registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Mozilla\\Firefox\\Metro\\Prefs\\" + prefType,
|
||||
Ci.nsIWindowsRegKey.ACCESS_ALL);
|
||||
for (let i = 0; i < registry.valueCount; i++) {
|
||||
let prefName = registry.getValueName(i);
|
||||
let prefValue = registry.readStringValue(prefName);
|
||||
if (prefType == Ci.nsIPrefBranch.PREF_BOOL) {
|
||||
prefValue = prefValue == "true";
|
||||
}
|
||||
Services.prefs[prefFunc](prefName, prefValue);
|
||||
}
|
||||
} catch (ex) {
|
||||
Util.dumpLn("Could not pull for prefType " + prefType + ": " + ex);
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
}
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
pullDesktopControlledPrefType(Ci.nsIPrefBranch.PREF_INT, "setIntPref");
|
||||
pullDesktopControlledPrefType(Ci.nsIPrefBranch.PREF_BOOL, "setBoolPref");
|
||||
pullDesktopControlledPrefType(Ci.nsIPrefBranch.PREF_STRING, "setCharPref");
|
||||
},
|
||||
|
||||
_titleChanged: function(aBrowser) {
|
||||
let url = this.getDisplayURI(aBrowser);
|
||||
|
||||
@ -1327,11 +1303,15 @@ var SettingsCharm = {
|
||||
label: Strings.browser.GetStringFromName("optionsCharm"),
|
||||
onselected: function() FlyoutPanelsUI.show('PrefsFlyoutPanel')
|
||||
});
|
||||
/*
|
||||
* Temporarily disabled until we can have sync prefs together with the
|
||||
* Desktop browser's sync prefs.
|
||||
// Sync
|
||||
this.addEntry({
|
||||
label: Strings.brand.GetStringFromName("syncBrandShortName"),
|
||||
onselected: function() FlyoutPanelsUI.show('SyncFlyoutPanel')
|
||||
});
|
||||
*/
|
||||
// About
|
||||
this.addEntry({
|
||||
label: Strings.browser.GetStringFromName("aboutCharm1"),
|
||||
|
@ -142,10 +142,14 @@
|
||||
<!-- development/testing -->
|
||||
<key id="key_console" key="&jsConsole.key;" modifiers="accel,shift" oncommand="PanelUI.show('console-container')"/>
|
||||
<key id="key_options" key="&optionsFlyout.key;" modifiers="accel,shift" oncommand="FlyoutPanelsUI.show('PrefsFlyoutPanel')" />
|
||||
<key id="key_options" key="&aboutFlyout.key;" modifiers="accel,shift" oncommand="FlyoutPanelsUI.show('AboutFlyoutPanel')" />
|
||||
<!--
|
||||
Temporarily disabled until we can have sync prefs together with the
|
||||
Desktop browser's sync prefs.
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
<key id="key_options" key="&syncFlyout.key;" modifiers="accel,shift" oncommand="FlyoutPanelsUI.show('SyncFlyoutPanel')" />
|
||||
#endif
|
||||
<key id="key_options" key="&aboutFlyout.key;" modifiers="accel,shift" oncommand="FlyoutPanelsUI.show('AboutFlyoutPanel')" />
|
||||
-->
|
||||
|
||||
<!-- manage tabs -->
|
||||
<key id="key_newTab" key="&newTab.key;" modifiers="accel" command="cmd_newTab"/>
|
||||
@ -784,7 +788,7 @@
|
||||
<label value="&appbarFindInPage2.label;"/>
|
||||
</richlistitem>
|
||||
<richlistitem id="context-viewondesktop" type="view-on-desktop" onclick="ContextCommands.viewOnDesktop();">
|
||||
<label value="&appbarViewOnDesktop2.label;"/>
|
||||
<label value="&appbarRelaunchInDesktop.label;"/>
|
||||
</richlistitem>
|
||||
<richlistitem id="context-msmetadata" type="ms-meta-data" onclick="ContextCommands.openWindowsStoreLink();">
|
||||
<label value="&appbarMSMetaData2.label;"/>
|
||||
|
@ -279,7 +279,7 @@ appUpdater.prototype =
|
||||
}
|
||||
|
||||
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
|
||||
Components.interfaces.nsIAppStartup.eRestart);
|
||||
Components.interfaces.nsIAppStartup.eRestartTouchEnvironment);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,12 @@
|
||||
|
||||
<!ENTITY autocompleteResultsHeader.label "Your Results">
|
||||
|
||||
<!ENTITY appbarErrorConsole.label "Open error console">
|
||||
<!ENTITY appbarJSShell.label "Open JavaScript shell">
|
||||
<!ENTITY appbarFindInPage2.label "Find in page">
|
||||
<!ENTITY appbarViewOnDesktop2.label "View on desktop">
|
||||
<!ENTITY appbarMSMetaData2.label "Get app for this site">
|
||||
<!ENTITY appbarViewPageSource.label "View page source">
|
||||
<!ENTITY appbarErrorConsole.label "Open error console">
|
||||
<!ENTITY appbarJSShell.label "Open JavaScript shell">
|
||||
<!ENTITY appbarFindInPage2.label "Find in page">
|
||||
<!ENTITY appbarRelaunchInDesktop.label "Relaunch in Desktop">
|
||||
<!ENTITY appbarMSMetaData2.label "Get app for this site">
|
||||
<!ENTITY appbarViewPageSource.label "View page source">
|
||||
|
||||
<!ENTITY topSitesHeader.label "Top Sites">
|
||||
<!ENTITY bookmarksHeader.label "Bookmarks">
|
||||
|
@ -1,7 +1,7 @@
|
||||
#filter substitution
|
||||
[App]
|
||||
Vendor=Mozilla
|
||||
Name=MetroFirefox
|
||||
Name=@MOZ_APP_BASENAME@
|
||||
UAName=Firefox
|
||||
Version=@GRE_MILESTONE@
|
||||
BuildID=@GRE_BUILDID@
|
||||
|
@ -81,7 +81,7 @@ IsImmersiveProcessDynamic(HANDLE process)
|
||||
}
|
||||
|
||||
bool
|
||||
IsImmersiveProcessRunning(const wchar_t *processName)
|
||||
IsProcessRunning(const wchar_t *processName, bool bCheckIfMetro)
|
||||
{
|
||||
bool exists = false;
|
||||
PROCESSENTRY32W entry;
|
||||
@ -93,7 +93,9 @@ IsImmersiveProcessRunning(const wchar_t *processName)
|
||||
while (!exists && Process32Next(snapshot, &entry)) {
|
||||
if (!_wcsicmp(entry.szExeFile, processName)) {
|
||||
HANDLE process = OpenProcess(GENERIC_READ, FALSE, entry.th32ProcessID);
|
||||
if (IsImmersiveProcessDynamic(process)) {
|
||||
bool isImmersiveProcess = IsImmersiveProcessDynamic(process);
|
||||
if ((bCheckIfMetro && isImmersiveProcess) ||
|
||||
(!bCheckIfMetro && !isImmersiveProcess)) {
|
||||
exists = true;
|
||||
}
|
||||
CloseHandle(process);
|
||||
|
@ -28,4 +28,4 @@ bool IsDX10Available();
|
||||
bool GetDWORDRegKey(LPCWSTR name, DWORD &value);
|
||||
bool SetDWORDRegKey(LPCWSTR name, DWORD value);
|
||||
bool IsImmersiveProcessDynamic(HANDLE process);
|
||||
bool IsImmersiveProcessRunning(const wchar_t *processName);
|
||||
bool IsProcessRunning(const wchar_t *processName, bool bCheckIfMetro);
|
||||
|
@ -44,6 +44,7 @@ static const WCHAR* kFirefoxExe = L"firefox.exe";
|
||||
static const WCHAR* kMetroFirefoxExe = L"firefox.exe";
|
||||
static const WCHAR* kDefaultMetroBrowserIDPathKey = L"FirefoxURL";
|
||||
static const WCHAR* kMetroRestartCmdLine = L"--metro-restart";
|
||||
static const WCHAR* kDesktopRestartCmdLine = L"--desktop-restart";
|
||||
|
||||
static bool GetDefaultBrowserPath(CStringW& aPathBuffer);
|
||||
|
||||
@ -104,7 +105,9 @@ public:
|
||||
mTargetIsBrowser(false),
|
||||
mIsDesktopRequest(true),
|
||||
mIsRestartMetroRequest(false),
|
||||
mRequestMet(false)
|
||||
mIsRestartDesktopRequest(false),
|
||||
mRequestMet(false),
|
||||
mVerb(L"open")
|
||||
{
|
||||
}
|
||||
|
||||
@ -152,6 +155,8 @@ public:
|
||||
|
||||
if (_wcsicmp(aParameters, kMetroRestartCmdLine) == 0) {
|
||||
mIsRestartMetroRequest = true;
|
||||
} else if (_wcsicmp(aParameters, kDesktopRestartCmdLine) == 0) {
|
||||
mIsRestartDesktopRequest = true;
|
||||
} else {
|
||||
mParameters = aParameters;
|
||||
}
|
||||
@ -260,11 +265,24 @@ public:
|
||||
*aLaunchType = AHE_DESKTOP;
|
||||
mIsDesktopRequest = true;
|
||||
|
||||
if (!mIsRestartMetroRequest && IsProcessRunning(kFirefoxExe, false)) {
|
||||
return S_OK;
|
||||
} else if (!mIsRestartDesktopRequest && IsProcessRunning(kMetroFirefoxExe, true)) {
|
||||
*aLaunchType = AHE_IMMERSIVE;
|
||||
mIsDesktopRequest = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!mUnkSite) {
|
||||
Log(L"No mUnkSite.");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (mIsRestartDesktopRequest) {
|
||||
Log(L"Restarting in desktop host environment.");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
IServiceProvider* pSvcProvider = nullptr;
|
||||
hr = mUnkSite->QueryInterface(IID_IServiceProvider, (void**)&pSvcProvider);
|
||||
@ -416,6 +434,7 @@ private:
|
||||
DWORD mKeyState;
|
||||
bool mIsDesktopRequest;
|
||||
bool mIsRestartMetroRequest;
|
||||
bool mIsRestartDesktopRequest;
|
||||
bool mRequestMet;
|
||||
};
|
||||
|
||||
@ -574,6 +593,48 @@ bool CExecuteCommandVerb::SetTargetPath(IShellItem* aItem)
|
||||
* Desktop launch - Launch the destop browser to display the current
|
||||
* target using shellexecute.
|
||||
*/
|
||||
void LaunchDesktopBrowserWithParams(CStringW& aBrowserPath, CStringW& aVerb, CStringW& aTarget, CStringW& aParameters,
|
||||
bool aTargetIsDefaultBrowser, bool aTargetIsBrowser)
|
||||
{
|
||||
// If a taskbar shortcut, link or local file is clicked, the target will
|
||||
// be the browser exe or file. Don't pass in -url for the target if the
|
||||
// target is known to be a browser. Otherwise, one instance of Firefox
|
||||
// will try to open another instance.
|
||||
CStringW params;
|
||||
if (!aTargetIsDefaultBrowser && !aTargetIsBrowser && !aTarget.IsEmpty()) {
|
||||
// Fallback to the module path if it failed to get the default browser.
|
||||
GetDefaultBrowserPath(aBrowserPath);
|
||||
params += "-url ";
|
||||
params += "\"";
|
||||
params += aTarget;
|
||||
params += "\"";
|
||||
}
|
||||
|
||||
// Tack on any extra parameters we received (for example -profilemanager)
|
||||
if (!aParameters.IsEmpty()) {
|
||||
params += " ";
|
||||
params += aParameters;
|
||||
}
|
||||
|
||||
Log(L"Desktop Launch: verb:%s exe:%s params:%s", aVerb, aBrowserPath, params);
|
||||
|
||||
SHELLEXECUTEINFOW seinfo;
|
||||
memset(&seinfo, 0, sizeof(seinfo));
|
||||
seinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||
seinfo.fMask = SEE_MASK_FLAG_LOG_USAGE;
|
||||
seinfo.lpVerb = aVerb;
|
||||
seinfo.lpFile = aBrowserPath;
|
||||
seinfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
// Relaunch in Desktop mode uses a special URL to trick Windows into
|
||||
// switching environments. We shouldn't actually try to open this URL
|
||||
if (_wcsicmp(aTarget, L"http://-desktop/") != 0) {
|
||||
seinfo.lpParameters = params;
|
||||
}
|
||||
|
||||
ShellExecuteEx(&seinfo);
|
||||
}
|
||||
|
||||
void CExecuteCommandVerb::LaunchDesktopBrowser()
|
||||
{
|
||||
CStringW browserPath;
|
||||
@ -581,40 +642,7 @@ void CExecuteCommandVerb::LaunchDesktopBrowser()
|
||||
return;
|
||||
}
|
||||
|
||||
// If a taskbar shortcut, link or local file is clicked, the target will
|
||||
// be the browser exe or file. Don't pass in -url for the target if the
|
||||
// target is known to be a browser. Otherwise, one instance of Firefox
|
||||
// will try to open another instance.
|
||||
CStringW params;
|
||||
if (!mTargetIsDefaultBrowser && !mTargetIsBrowser && !mTarget.IsEmpty()) {
|
||||
// Fallback to the module path if it failed to get the default browser.
|
||||
GetDefaultBrowserPath(browserPath);
|
||||
params += "-url ";
|
||||
params += "\"";
|
||||
params += mTarget;
|
||||
params += "\"";
|
||||
}
|
||||
|
||||
// Tack on any extra parameters we received (for example -profilemanager)
|
||||
if (!mParameters.IsEmpty()) {
|
||||
params += " ";
|
||||
params += mParameters;
|
||||
}
|
||||
|
||||
Log(L"Desktop Launch: verb:%s exe:%s params:%s", mVerb, browserPath, params);
|
||||
|
||||
SHELLEXECUTEINFOW seinfo;
|
||||
memset(&seinfo, 0, sizeof(seinfo));
|
||||
seinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||
seinfo.fMask = 0;
|
||||
seinfo.hwnd = nullptr;
|
||||
seinfo.lpVerb = nullptr;
|
||||
seinfo.lpFile = browserPath;
|
||||
seinfo.lpParameters = params;
|
||||
seinfo.lpDirectory = nullptr;
|
||||
seinfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
ShellExecuteExW(&seinfo);
|
||||
LaunchDesktopBrowserWithParams(browserPath, mVerb, mTarget, mParameters, mTargetIsDefaultBrowser, mTargetIsBrowser);
|
||||
}
|
||||
|
||||
class AutoSetRequestMet
|
||||
@ -664,7 +692,7 @@ DelayedExecuteThread(LPVOID param)
|
||||
|
||||
size_t currentWaitTime = 0;
|
||||
while(currentWaitTime < RESTART_WAIT_TIMEOUT) {
|
||||
if (!IsImmersiveProcessRunning(kMetroFirefoxExe))
|
||||
if (!IsProcessRunning(kMetroFirefoxExe, true))
|
||||
break;
|
||||
currentWaitTime += RESTART_WAIT_PER_RETRY;
|
||||
Sleep(RESTART_WAIT_PER_RETRY);
|
||||
@ -705,6 +733,21 @@ IFACEMETHODIMP CExecuteCommandVerb::Execute()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (mIsRestartDesktopRequest) {
|
||||
CStringW browserPath;
|
||||
if (!GetDesktopBrowserPath(browserPath)) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
LaunchDesktopBrowserWithParams(browserPath,
|
||||
mVerb,
|
||||
mTarget,
|
||||
mParameters,
|
||||
mTargetIsDefaultBrowser,
|
||||
mTargetIsBrowser);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// We shut down when this flips to true
|
||||
AutoSetRequestMet asrm(&mRequestMet);
|
||||
|
||||
@ -728,8 +771,7 @@ IFACEMETHODIMP CExecuteCommandVerb::Execute()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Log(L"Metro Launch: verb:%s appid:%s params:%s", mVerb, appModelID, mTarget);
|
||||
|
||||
Log(L"Metro Launch: verb:%s appid:%s params:%s", mVerb, appModelID, mTarget);
|
||||
|
||||
// shortcuts to the application
|
||||
DWORD processID;
|
||||
|
@ -82,7 +82,7 @@ const kPinned = [
|
||||
];
|
||||
|
||||
this.CharsetMenu = Object.freeze({
|
||||
build: function BuildCharsetMenu(event, showAccessKeys) {
|
||||
build: function BuildCharsetMenu(event, idPrefix="", showAccessKeys=false) {
|
||||
let parent = event.target;
|
||||
if (parent.lastChild.localName != "menuseparator") {
|
||||
// Detector menu or charset menu already built
|
||||
@ -108,7 +108,7 @@ this.CharsetMenu = Object.freeze({
|
||||
// Some items intentionally don't have an accesskey
|
||||
}
|
||||
}
|
||||
menuItem.setAttribute("id", "charset." + encoding);
|
||||
menuItem.setAttribute("id", idPrefix + "charset." + encoding);
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
%filter substitution
|
||||
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button
|
||||
%define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]),.overflowedItem)
|
||||
|
@ -30,6 +30,11 @@ toolbarpaletteitem[place="palette"] > #downloads-button {
|
||||
-moz-image-region: rect(0px, 256px, 32px, 224px);
|
||||
}
|
||||
|
||||
#switch-to-metro-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #switch-to-metro-button {
|
||||
-moz-image-region: rect(0px, 800px, 32px, 768px);
|
||||
}
|
||||
|
||||
#add-ons-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #add-ons-button {
|
||||
-moz-image-region: rect(0px, 288px, 32px, 256px);
|
||||
|
@ -49,6 +49,10 @@
|
||||
-moz-image-region: rect(0, 216px, 18px, 198px);
|
||||
}
|
||||
|
||||
#switch-to-metro-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 648px, 18px, 630px);
|
||||
}
|
||||
|
||||
#open-file-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 234px, 18px, 216px);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 27 KiB |
@ -50,7 +50,6 @@ public class FennecNativeDriver implements Driver {
|
||||
private ClassLoader mClassLoader;
|
||||
private Class mApiClass;
|
||||
private Class mEventListenerClass;
|
||||
private Class mPanningPerfClass;
|
||||
private Method mRegisterEventListener;
|
||||
private Method mGetPixels;
|
||||
private Method mStartFrameRecording;
|
||||
@ -91,14 +90,13 @@ public class FennecNativeDriver implements Driver {
|
||||
|
||||
mApiClass = mClassLoader.loadClass("org.mozilla.gecko.RobocopAPI");
|
||||
mEventListenerClass = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
|
||||
mPanningPerfClass = mClassLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
|
||||
|
||||
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
|
||||
mGetPixels = mApiClass.getMethod("getViewPixels", View.class);
|
||||
mStartFrameRecording = mPanningPerfClass.getDeclaredMethod("startFrameTimeRecording");
|
||||
mStopFrameRecording = mPanningPerfClass.getDeclaredMethod("stopFrameTimeRecording");
|
||||
mStartCheckerboardRecording = mPanningPerfClass.getDeclaredMethod("startCheckerboardRecording");
|
||||
mStopCheckerboardRecording = mPanningPerfClass.getDeclaredMethod("stopCheckerboardRecording");
|
||||
mStartFrameRecording = mApiClass.getDeclaredMethod("startFrameTimeRecording");
|
||||
mStopFrameRecording = mApiClass.getDeclaredMethod("stopFrameTimeRecording");
|
||||
mStartCheckerboardRecording = mApiClass.getDeclaredMethod("startCheckerboardRecording");
|
||||
mStopCheckerboardRecording = mApiClass.getDeclaredMethod("stopCheckerboardRecording");
|
||||
|
||||
mRobocopApi = mApiClass.getConstructor(Activity.class).newInstance(activity);
|
||||
} catch (Exception e) {
|
||||
|
@ -21,6 +21,9 @@ import android.util.Log;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
@WebRTCJNITarget
|
||||
class AudioManagerAndroid {
|
||||
// Most of Google lead devices use 44.1K as the default sampling rate, 44.1K
|
||||
// is also widely used on other android devices.
|
||||
|
@ -20,10 +20,13 @@ import android.media.AudioRecord;
|
||||
import android.media.AudioTrack;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
class WebRTCAudioDevice {
|
||||
private AudioTrack _audioTrack = null;
|
||||
private AudioRecord _audioRecord = null;
|
||||
|
||||
@WebRTCJNITarget
|
||||
private Context _context;
|
||||
private AudioManager _audioManager;
|
||||
|
||||
@ -44,6 +47,7 @@ class WebRTCAudioDevice {
|
||||
private int _bufferedPlaySamples = 0;
|
||||
private int _playPosition = 0;
|
||||
|
||||
@WebRTCJNITarget
|
||||
WebRTCAudioDevice() {
|
||||
try {
|
||||
_playBuffer = ByteBuffer.allocateDirect(2 * 480); // Max 10 ms @ 48
|
||||
@ -59,6 +63,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int InitRecording(int audioSource, int sampleRate) {
|
||||
// get the minimum buffer size that can be used
|
||||
int minRecBufSize = AudioRecord.getMinBufferSize(
|
||||
@ -104,6 +109,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int StartRecording() {
|
||||
if (_isPlaying == false) {
|
||||
SetAudioMode(true);
|
||||
@ -123,6 +129,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int InitPlayback(int sampleRate) {
|
||||
// get the minimum buffer size that can be used
|
||||
int minPlayBufSize = AudioTrack.getMinBufferSize(
|
||||
@ -180,6 +187,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int StartPlayback() {
|
||||
if (_isRecording == false) {
|
||||
SetAudioMode(true);
|
||||
@ -199,6 +207,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int StopRecording() {
|
||||
_recLock.lock();
|
||||
try {
|
||||
@ -234,6 +243,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int StopPlayback() {
|
||||
_playLock.lock();
|
||||
try {
|
||||
@ -271,6 +281,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int PlayAudio(int lengthInBytes) {
|
||||
|
||||
int bufferedSamples = 0;
|
||||
@ -331,6 +342,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int RecordAudio(int lengthInBytes) {
|
||||
_recLock.lock();
|
||||
|
||||
@ -376,6 +388,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int SetPlayoutSpeaker(boolean loudspeakerOn) {
|
||||
// create audio manager if needed
|
||||
if (_audioManager == null && _context != null) {
|
||||
@ -425,6 +438,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int SetPlayoutVolume(int level) {
|
||||
|
||||
// create audio manager if needed
|
||||
@ -445,6 +459,7 @@ class WebRTCAudioDevice {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@WebRTCJNITarget
|
||||
private int GetPlayoutVolume() {
|
||||
|
||||
// create audio manager if needed
|
||||
|
@ -10,6 +10,9 @@
|
||||
|
||||
package org.webrtc.videoengine;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
@WebRTCJNITarget
|
||||
public class CaptureCapabilityAndroid {
|
||||
public int width = 0;
|
||||
public int height = 0;
|
||||
|
@ -37,6 +37,7 @@ import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoAppShell.AppStateListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
|
||||
@ -107,6 +108,8 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
// Invoked every time there's a new Camera preview frame
|
||||
}
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public static
|
||||
void DeleteVideoCaptureAndroid(VideoCaptureAndroid captureAndroid) {
|
||||
Log.d(TAG, "DeleteVideoCaptureAndroid");
|
||||
@ -313,6 +316,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public int StartCapture(int width, int height, int frameRate) {
|
||||
Log.d(TAG, "StartCapture width " + width +
|
||||
" height " + height +" frame rate " + frameRate);
|
||||
|
@ -24,6 +24,8 @@ import android.hardware.Camera;
|
||||
import android.hardware.Camera.Size;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
public class VideoCaptureDeviceInfoAndroid {
|
||||
|
||||
//Context
|
||||
@ -34,6 +36,7 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
private final static String TAG = "WEBRTC";
|
||||
|
||||
// Private class with info about all available cameras and the capabilities
|
||||
@WebRTCJNITarget
|
||||
public class AndroidVideoCaptureDevice {
|
||||
AndroidVideoCaptureDevice() {
|
||||
frontCameraType = FrontFacingCameraType.None;
|
||||
@ -62,6 +65,7 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
int id;
|
||||
List<AndroidVideoCaptureDevice> deviceList;
|
||||
|
||||
@WebRTCJNITarget
|
||||
public static VideoCaptureDeviceInfoAndroid
|
||||
CreateVideoCaptureDeviceInfoAndroid(int in_id, Context in_context) {
|
||||
Log.d(TAG,
|
||||
@ -213,10 +217,12 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
}
|
||||
|
||||
// Returns the number of Capture devices that is supported
|
||||
@WebRTCJNITarget
|
||||
public int NumberOfDevices() {
|
||||
return deviceList.size();
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public String GetDeviceUniqueName(int deviceNumber) {
|
||||
if(deviceNumber < 0 || deviceNumber >= deviceList.size()) {
|
||||
return null;
|
||||
@ -224,6 +230,7 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
return deviceList.get(deviceNumber).deviceUniqueName;
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public CaptureCapabilityAndroid[] GetCapabilityArray (String deviceUniqueId)
|
||||
{
|
||||
for (AndroidVideoCaptureDevice device: deviceList) {
|
||||
@ -236,6 +243,7 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
|
||||
// Returns the camera orientation as described by
|
||||
// android.hardware.Camera.CameraInfo.orientation
|
||||
@WebRTCJNITarget
|
||||
public int GetOrientation(String deviceUniqueId) {
|
||||
for (AndroidVideoCaptureDevice device: deviceList) {
|
||||
if(device.deviceUniqueName.equals(deviceUniqueId)) {
|
||||
@ -246,6 +254,7 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
}
|
||||
|
||||
// Returns an instance of VideoCaptureAndroid.
|
||||
@WebRTCJNITarget
|
||||
public VideoCaptureAndroid AllocateCamera(int id, long context,
|
||||
String deviceUniqueId) {
|
||||
try {
|
||||
@ -296,6 +305,7 @@ public class VideoCaptureDeviceInfoAndroid {
|
||||
}
|
||||
|
||||
// Searches for a front facing camera device. This is device specific code.
|
||||
@WebRTCJNITarget
|
||||
private Camera.Parameters
|
||||
SearchOldFrontFacingCameras(AndroidVideoCaptureDevice newDevice)
|
||||
throws SecurityException, IllegalArgumentException,
|
||||
|
@ -25,6 +25,8 @@ import android.graphics.PixelFormat;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
public class ViEAndroidGLES20 extends GLSurfaceView
|
||||
implements GLSurfaceView.Renderer {
|
||||
private static String TAG = "WEBRTC-JR";
|
||||
@ -40,6 +42,7 @@ public class ViEAndroidGLES20 extends GLSurfaceView
|
||||
private int viewWidth = 0;
|
||||
private int viewHeight = 0;
|
||||
|
||||
@WebRTCJNITarget
|
||||
public static boolean UseOpenGL2(Object renderWindow) {
|
||||
return ViEAndroidGLES20.class.isInstance(renderWindow);
|
||||
}
|
||||
@ -49,6 +52,7 @@ public class ViEAndroidGLES20 extends GLSurfaceView
|
||||
init(false, 0, 0);
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public ViEAndroidGLES20(Context context, boolean translucent,
|
||||
int depth, int stencil) {
|
||||
super(context);
|
||||
@ -341,6 +345,7 @@ public class ViEAndroidGLES20 extends GLSurfaceView
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void RegisterNativeObject(long nativeObject) {
|
||||
nativeFunctionLock.lock();
|
||||
this.nativeObject = nativeObject;
|
||||
@ -348,6 +353,7 @@ public class ViEAndroidGLES20 extends GLSurfaceView
|
||||
nativeFunctionLock.unlock();
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void DeRegisterNativeObject() {
|
||||
nativeFunctionLock.lock();
|
||||
nativeFunctionsRegisted = false;
|
||||
@ -356,6 +362,7 @@ public class ViEAndroidGLES20 extends GLSurfaceView
|
||||
nativeFunctionLock.unlock();
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void ReDraw() {
|
||||
if(surfaceCreated) {
|
||||
// Request the renderer to redraw using the render thread context.
|
||||
|
@ -26,6 +26,8 @@ import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.SurfaceHolder.Callback;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
public class ViESurfaceRenderer implements Callback {
|
||||
|
||||
private final static String TAG = "WEBRTC";
|
||||
@ -43,6 +45,7 @@ public class ViESurfaceRenderer implements Callback {
|
||||
private float dstLeftScale = 0;
|
||||
private float dstRightScale = 1;
|
||||
|
||||
@WebRTCJNITarget
|
||||
public ViESurfaceRenderer(SurfaceView view) {
|
||||
surfaceHolder = view.getHolder();
|
||||
if(surfaceHolder == null)
|
||||
@ -122,6 +125,7 @@ public class ViESurfaceRenderer implements Callback {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public ByteBuffer CreateByteBuffer(int width, int height) {
|
||||
Log.d(TAG, "CreateByteBuffer " + width + ":" + height);
|
||||
if (bitmap == null) {
|
||||
@ -131,6 +135,7 @@ public class ViESurfaceRenderer implements Callback {
|
||||
return byteBuffer;
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void SetCoordinates(float left, float top,
|
||||
float right, float bottom) {
|
||||
Log.d(TAG, "SetCoordinates " + left + "," + top + ":" +
|
||||
@ -142,6 +147,7 @@ public class ViESurfaceRenderer implements Callback {
|
||||
}
|
||||
|
||||
// It saves bitmap data to a JPEG picture, this function is for debug only.
|
||||
@WebRTCJNITarget
|
||||
private void saveBitmapToJPEG(int width, int height) {
|
||||
ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteOutStream);
|
||||
@ -159,6 +165,7 @@ public class ViESurfaceRenderer implements Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void DrawByteBuffer() {
|
||||
if(byteBuffer == null)
|
||||
return;
|
||||
|
@ -23,6 +23,8 @@ import android.view.SurfaceView;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
class CodecState {
|
||||
private static final String TAG = "CodecState";
|
||||
|
||||
@ -41,6 +43,7 @@ class CodecState {
|
||||
|
||||
private long mLastMediaTimeUs;
|
||||
|
||||
@WebRTCJNITarget
|
||||
public CodecState(
|
||||
ViEMediaCodecDecoder view,
|
||||
MediaFormat format,
|
||||
@ -245,6 +248,7 @@ class ViEMediaCodecDecoder {
|
||||
|
||||
private Thread mLooperThread;
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void configure(SurfaceView surfaceView, int width, int height) {
|
||||
mSurfaceView = surfaceView;
|
||||
Log.d(TAG, "configure " + "width" + width + "height" + height + mSurfaceView.toString());
|
||||
@ -267,6 +271,7 @@ class ViEMediaCodecDecoder {
|
||||
initMediaCodecView();
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void setEncodedImage(ByteBuffer buffer, long renderTimeMs) {
|
||||
// TODO(dwkang): figure out why exceptions just make this thread finish.
|
||||
try {
|
||||
@ -354,6 +359,7 @@ class ViEMediaCodecDecoder {
|
||||
Log.d(TAG, "initMediaCodecView end");
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public void start() {
|
||||
Log.d(TAG, "start");
|
||||
|
||||
|
@ -59,6 +59,7 @@ import android.widget.TabHost.TabSpec;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.webrtc.videoengine.ViERenderer;
|
||||
import org.mozilla.gecko.mozglue.WebRTCJNITarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -1046,6 +1047,7 @@ public class WebRTCDemo extends TabActivity implements IViEAndroidCallback,
|
||||
Log.d(TAG, "No setting selected");
|
||||
}
|
||||
|
||||
@WebRTCJNITarget
|
||||
public int updateStats(int inFrameRateI, int inBitRateI,
|
||||
int inPacketLoss, int inFrameRateO, int inBitRateO) {
|
||||
frameRateI = inFrameRateI;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
/**
|
||||
* A collection of constants that pertain to the build and runtime state of the
|
||||
* application. Typically these are sourced from build-time definitions (see
|
||||
@ -15,6 +16,7 @@ package org.mozilla.gecko;
|
||||
* See also SysInfo.java, which includes some of the values available from
|
||||
* nsSystemInfo inside Gecko.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public class AppConstants {
|
||||
public static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
|
||||
public static final String BROWSER_INTENT_CLASS = ANDROID_PACKAGE_NAME + ".App";
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -87,6 +88,7 @@ public final class Distribution {
|
||||
*
|
||||
* @param packagePath where to look for the distribution directory.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public static void init(final Context context, final String packagePath, final String prefsPath) {
|
||||
// Read/write preferences and files on the background thread.
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
|
@ -10,6 +10,7 @@ import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PanZoomController;
|
||||
import org.mozilla.gecko.mozglue.JNITarget;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
@ -391,7 +392,6 @@ public class GeckoAppShell
|
||||
} catch (NoSuchElementException e) {}
|
||||
}
|
||||
|
||||
/* This method is referenced by Robocop via reflection. */
|
||||
public static void sendEventToGecko(GeckoEvent e) {
|
||||
if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
|
||||
notifyGeckoOfEvent(e);
|
||||
@ -859,6 +859,7 @@ public class GeckoAppShell
|
||||
});
|
||||
}
|
||||
|
||||
@JNITarget
|
||||
static public int getPreferredIconSize() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
ActivityManager am = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE);
|
||||
@ -2320,8 +2321,6 @@ public class GeckoAppShell
|
||||
* with an event that is currently being processed has the properly-defined behaviour that
|
||||
* any added listeners will not be invoked on the event currently being processed, but
|
||||
* will be invoked on future events of that type.
|
||||
*
|
||||
* This method is referenced by Robocop via reflection.
|
||||
*/
|
||||
public static void registerEventListener(String event, GeckoEventListener listener) {
|
||||
sEventDispatcher.registerEventListener(event, listener);
|
||||
@ -2337,8 +2336,6 @@ public class GeckoAppShell
|
||||
* with an event that is currently being processed has the properly-defined behaviour that
|
||||
* any removed listeners will still be invoked on the event currently being processed, but
|
||||
* will not be invoked on future events of that type.
|
||||
*
|
||||
* This method is referenced by Robocop via reflection.
|
||||
*/
|
||||
public static void unregisterEventListener(String event, GeckoEventListener listener) {
|
||||
sEventDispatcher.unregisterEventListener(event, listener);
|
||||
|
@ -7,6 +7,7 @@ package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.DisplayPortMetrics;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
import org.mozilla.gecko.mozglue.JNITarget;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.GeneratorOptions;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
|
||||
|
||||
@ -36,11 +37,13 @@ import java.nio.ByteBuffer;
|
||||
/* This class is referenced by Robocop via reflection; use care when
|
||||
* modifying the signature.
|
||||
*/
|
||||
@JNITarget
|
||||
public class GeckoEvent {
|
||||
private static final String LOGTAG = "GeckoEvent";
|
||||
|
||||
// Make sure to keep these values in sync with the enum in
|
||||
// AndroidGeckoEvent in widget/android/AndroidJavaWrapper.h
|
||||
@JNITarget
|
||||
private enum NativeGeckoEvent {
|
||||
NATIVE_POKE(0),
|
||||
KEY_EVENT(1),
|
||||
@ -103,6 +106,7 @@ public class GeckoEvent {
|
||||
}
|
||||
|
||||
// Encapsulation of common IME actions.
|
||||
@JNITarget
|
||||
public enum ImeAction {
|
||||
IME_SYNCHRONIZE(0),
|
||||
IME_REPLACE_TEXT(1),
|
||||
|
@ -6,12 +6,12 @@
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
@ -28,6 +28,7 @@ import java.util.Locale;
|
||||
public class GeckoThread extends Thread implements GeckoEventListener {
|
||||
private static final String LOGTAG = "GeckoThread";
|
||||
|
||||
@RobocopTarget
|
||||
public enum LaunchState {
|
||||
Launching,
|
||||
WaitForDebugger,
|
||||
@ -187,6 +188,7 @@ public class GeckoThread extends Thread implements GeckoEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static boolean checkLaunchState(LaunchState checkState) {
|
||||
synchronized (sLock) {
|
||||
return sLaunchState == checkState;
|
||||
|
@ -7,6 +7,7 @@ package org.mozilla.gecko;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
|
||||
import android.content.Context;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
public class NSSBridge {
|
||||
private static final String LOGTAG = "NSSBridge";
|
||||
@ -14,6 +15,7 @@ public class NSSBridge {
|
||||
private static native String nativeEncrypt(String aDb, String aValue);
|
||||
private static native String nativeDecrypt(String aDb, String aValue);
|
||||
|
||||
@RobocopTarget
|
||||
static public String encrypt(Context context, String aValue)
|
||||
throws Exception {
|
||||
String resourcePath = context.getPackageResourcePath();
|
||||
@ -23,6 +25,7 @@ public class NSSBridge {
|
||||
return nativeEncrypt(path, aValue);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
static public String encrypt(Context context, String profilePath, String aValue)
|
||||
throws Exception {
|
||||
String resourcePath = context.getPackageResourcePath();
|
||||
@ -31,6 +34,7 @@ public class NSSBridge {
|
||||
return nativeEncrypt(profilePath, aValue);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
static public String decrypt(Context context, String aValue)
|
||||
throws Exception {
|
||||
String resourcePath = context.getPackageResourcePath();
|
||||
@ -40,6 +44,7 @@ public class NSSBridge {
|
||||
return nativeDecrypt(path, aValue);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
static public String decrypt(Context context, String profilePath, String aValue)
|
||||
throws Exception {
|
||||
String resourcePath = context.getPackageResourcePath();
|
||||
|
@ -6,7 +6,9 @@ package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PanningPerfAPI;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridge;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
@ -15,7 +17,27 @@ import android.database.Cursor;
|
||||
import android.view.View;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class to provide wrapper methods around methods wanted by Robocop.
|
||||
*
|
||||
* This class provides fixed entry points into code that is liable to be optimised by Proguard without
|
||||
* needing to prevent Proguard from optimising the wrapped methods.
|
||||
* Wrapping in this way still slightly hinders Proguard's ability to optimise.
|
||||
*
|
||||
* If you find yourself wanting to add a method to this class - proceed with caution. If you're writing
|
||||
* a test that's not about manipulating the UI, you might be better off using JUnit (Or similar)
|
||||
* instead of Robocop.
|
||||
*
|
||||
* Alternatively, you might be able to get what you want by reflecting on a method annotated for the
|
||||
* benefit of the C++ wrapper generator - these methods are sure to not disappear at compile-time.
|
||||
*
|
||||
* Finally, you might be able to get what you want via Reflection on Android's libraries. Those are
|
||||
* also not prone to vanishing at compile-time, but doing this might substantially complicate your
|
||||
* work, ultimately not proving worth the extra effort to avoid making a slight mess here.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public class RobocopAPI {
|
||||
private final GeckoApp mGeckoApp;
|
||||
|
||||
@ -59,4 +81,21 @@ public class RobocopAPI {
|
||||
public IntBuffer getViewPixels(View view) {
|
||||
return ((LayerView)view).getPixels();
|
||||
}
|
||||
|
||||
// PanningPerfAPI.
|
||||
public static void startFrameTimeRecording() {
|
||||
PanningPerfAPI.startFrameTimeRecording();
|
||||
}
|
||||
|
||||
public static List<Long> stopFrameTimeRecording() {
|
||||
return PanningPerfAPI.stopFrameTimeRecording();
|
||||
}
|
||||
|
||||
public static void startCheckerboardRecording() {
|
||||
PanningPerfAPI.startCheckerboardRecording();
|
||||
}
|
||||
|
||||
public static List<Float> stopCheckerboardRecording() {
|
||||
return PanningPerfAPI.stopCheckerboardRecording();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ package org.mozilla.gecko;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.favicons.Favicons;
|
||||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.mozglue.JNITarget;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
@ -374,6 +376,7 @@ public class Tabs implements GeckoEventListener {
|
||||
private static final Tabs INSTANCE = new Tabs();
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static Tabs getInstance() {
|
||||
return Tabs.TabsInstanceHolder.INSTANCE;
|
||||
}
|
||||
@ -666,6 +669,7 @@ public class Tabs implements GeckoEventListener {
|
||||
*
|
||||
* @param url URL of page to load, or search term used if searchEngine is given
|
||||
*/
|
||||
@RobocopTarget
|
||||
public Tab loadUrl(String url) {
|
||||
return loadUrl(url, LOADURL_NONE);
|
||||
}
|
||||
@ -797,9 +801,8 @@ public class Tabs implements GeckoEventListener {
|
||||
|
||||
/**
|
||||
* Gets the next tab ID.
|
||||
*
|
||||
* This method is invoked via JNI.
|
||||
*/
|
||||
@JNITarget
|
||||
public static int getNextTabId() {
|
||||
return sTabId.getAndIncrement();
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ package org.mozilla.gecko.db;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
|
||||
import android.net.Uri;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
@RobocopTarget
|
||||
public class BrowserContract {
|
||||
public static final String AUTHORITY = AppConstants.ANDROID_PACKAGE_NAME + ".db.browser";
|
||||
public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
|
||||
@ -50,31 +52,37 @@ public class BrowserContract {
|
||||
return order.toString();
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public interface CommonColumns {
|
||||
public static final String _ID = "_id";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public interface DateSyncColumns {
|
||||
public static final String DATE_CREATED = "created";
|
||||
public static final String DATE_MODIFIED = "modified";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public interface SyncColumns extends DateSyncColumns {
|
||||
public static final String GUID = "guid";
|
||||
public static final String IS_DELETED = "deleted";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public interface URLColumns {
|
||||
public static final String URL = "url";
|
||||
public static final String TITLE = "title";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public interface FaviconColumns {
|
||||
public static final String FAVICON = "favicon";
|
||||
public static final String FAVICON_ID = "favicon_id";
|
||||
public static final String FAVICON_URL = "favicon_url";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public interface HistoryColumns {
|
||||
public static final String DATE_LAST_VISITED = "date";
|
||||
public static final String VISITS = "visits";
|
||||
@ -86,6 +94,7 @@ public class BrowserContract {
|
||||
public static final String TIME_DELETED = "timeDeleted";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static final class Favicons implements CommonColumns, DateSyncColumns {
|
||||
private Favicons() {}
|
||||
|
||||
@ -96,6 +105,7 @@ public class BrowserContract {
|
||||
public static final String PAGE_URL = "page_url";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static final class Thumbnails implements CommonColumns {
|
||||
private Thumbnails() {}
|
||||
|
||||
@ -105,6 +115,7 @@ public class BrowserContract {
|
||||
public static final String DATA = "data";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static final class Bookmarks implements CommonColumns, URLColumns, FaviconColumns, SyncColumns {
|
||||
private Bookmarks() {}
|
||||
|
||||
@ -145,6 +156,7 @@ public class BrowserContract {
|
||||
public static final String KEYWORD = "keyword";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static final class History implements CommonColumns, URLColumns, HistoryColumns, FaviconColumns, SyncColumns {
|
||||
private History() {}
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "history");
|
||||
@ -154,6 +166,7 @@ public class BrowserContract {
|
||||
}
|
||||
|
||||
// Combined bookmarks and history
|
||||
@RobocopTarget
|
||||
public static final class Combined implements CommonColumns, URLColumns, HistoryColumns, FaviconColumns {
|
||||
private Combined() {}
|
||||
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "combined");
|
||||
|
@ -7,6 +7,7 @@ package org.mozilla.gecko.db;
|
||||
|
||||
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
|
||||
import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
@ -36,6 +37,7 @@ public class BrowserDB {
|
||||
public interface BrowserDBIface {
|
||||
public void invalidateCachedState();
|
||||
|
||||
@RobocopTarget
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit);
|
||||
|
||||
// This should onlyl return frecent sites, BrowserDB.getTopSites will do the
|
||||
@ -49,6 +51,7 @@ public class BrowserDB {
|
||||
public void updateHistoryEntry(ContentResolver cr, String uri, String title,
|
||||
long date, int visits);
|
||||
|
||||
@RobocopTarget
|
||||
public Cursor getAllVisitedHistory(ContentResolver cr);
|
||||
|
||||
public Cursor getRecentHistory(ContentResolver cr, int limit);
|
||||
@ -57,28 +60,34 @@ public class BrowserDB {
|
||||
|
||||
public void removeHistoryEntry(ContentResolver cr, int id);
|
||||
|
||||
@RobocopTarget
|
||||
public void removeHistoryEntry(ContentResolver cr, String url);
|
||||
|
||||
public void clearHistory(ContentResolver cr);
|
||||
|
||||
@RobocopTarget
|
||||
public Cursor getBookmarksInFolder(ContentResolver cr, long folderId);
|
||||
|
||||
public boolean isVisited(ContentResolver cr, String uri);
|
||||
|
||||
public int getReadingListCount(ContentResolver cr);
|
||||
|
||||
@RobocopTarget
|
||||
public boolean isBookmark(ContentResolver cr, String uri);
|
||||
|
||||
public boolean isReadingListItem(ContentResolver cr, String uri);
|
||||
|
||||
public String getUrlForKeyword(ContentResolver cr, String keyword);
|
||||
|
||||
@RobocopTarget
|
||||
public void addBookmark(ContentResolver cr, String title, String uri);
|
||||
|
||||
public void removeBookmark(ContentResolver cr, int id);
|
||||
|
||||
@RobocopTarget
|
||||
public void removeBookmarksWithURL(ContentResolver cr, String uri);
|
||||
|
||||
@RobocopTarget
|
||||
public void updateBookmark(ContentResolver cr, int id, String uri, String title, String keyword);
|
||||
|
||||
public void addReadingListItem(ContentResolver cr, String title, String uri);
|
||||
@ -93,10 +102,12 @@ public class BrowserDB {
|
||||
|
||||
public void updateThumbnailForUrl(ContentResolver cr, String uri, BitmapDrawable thumbnail);
|
||||
|
||||
@RobocopTarget
|
||||
public byte[] getThumbnailForUrl(ContentResolver cr, String uri);
|
||||
|
||||
public Cursor getThumbnailsForUrls(ContentResolver cr, List<String> urls);
|
||||
|
||||
@RobocopTarget
|
||||
public void removeThumbnails(ContentResolver cr);
|
||||
|
||||
public void registerBookmarkObserver(ContentResolver cr, ContentObserver observer);
|
||||
@ -113,6 +124,7 @@ public class BrowserDB {
|
||||
|
||||
public Cursor getPinnedSites(ContentResolver cr, int limit);
|
||||
|
||||
@RobocopTarget
|
||||
public Cursor getBookmarkForUrl(ContentResolver cr, String url);
|
||||
}
|
||||
|
||||
@ -129,6 +141,7 @@ public class BrowserDB {
|
||||
sDb.invalidateCachedState();
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return sDb.filter(cr, constraint, limit);
|
||||
}
|
||||
@ -160,6 +173,7 @@ public class BrowserDB {
|
||||
}
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static Cursor getAllVisitedHistory(ContentResolver cr) {
|
||||
return (sAreContentProvidersEnabled ? sDb.getAllVisitedHistory(cr) : null);
|
||||
}
|
||||
@ -181,14 +195,17 @@ public class BrowserDB {
|
||||
sDb.removeHistoryEntry(cr, id);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static void removeHistoryEntry(ContentResolver cr, String url) {
|
||||
sDb.removeHistoryEntry(cr, url);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static void clearHistory(ContentResolver cr) {
|
||||
sDb.clearHistory(cr);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static Cursor getBookmarksInFolder(ContentResolver cr, long folderId) {
|
||||
return sDb.getBookmarksInFolder(cr, folderId);
|
||||
}
|
||||
@ -205,6 +222,7 @@ public class BrowserDB {
|
||||
return sDb.getReadingListCount(cr);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static boolean isBookmark(ContentResolver cr, String uri) {
|
||||
return (sAreContentProvidersEnabled && sDb.isBookmark(cr, uri));
|
||||
}
|
||||
@ -221,10 +239,12 @@ public class BrowserDB {
|
||||
sDb.removeBookmark(cr, id);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static void removeBookmarksWithURL(ContentResolver cr, String uri) {
|
||||
sDb.removeBookmarksWithURL(cr, uri);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static void updateBookmark(ContentResolver cr, int id, String uri, String title, String keyword) {
|
||||
sDb.updateBookmark(cr, id, uri, title, keyword);
|
||||
}
|
||||
@ -253,6 +273,7 @@ public class BrowserDB {
|
||||
sDb.updateThumbnailForUrl(cr, uri, thumbnail);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static byte[] getThumbnailForUrl(ContentResolver cr, String uri) {
|
||||
return sDb.getThumbnailForUrl(cr, uri);
|
||||
}
|
||||
@ -261,6 +282,7 @@ public class BrowserDB {
|
||||
return sDb.getThumbnailsForUrls(cr, urls);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static void removeThumbnails(ContentResolver cr) {
|
||||
sDb.removeThumbnails(cr);
|
||||
}
|
||||
@ -297,6 +319,7 @@ public class BrowserDB {
|
||||
return sDb.getPinnedSites(cr, limit);
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static Cursor getBookmarkForUrl(ContentResolver cr, String url) {
|
||||
return sDb.getBookmarkForUrl(cr, url);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import org.mozilla.gecko.db.BrowserContract.SyncColumns;
|
||||
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
|
||||
import org.mozilla.gecko.db.BrowserContract.URLColumns;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.util.GeckoJarReader;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
@ -1991,6 +1992,7 @@ public class BrowserProvider extends ContentProvider {
|
||||
return dbHelper;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public String getDatabasePath(String profile, boolean isTest) {
|
||||
trace("Getting database path for profile: " + profile);
|
||||
|
||||
|
@ -12,9 +12,7 @@ import java.util.Map;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.db.BrowserContract.Clients;
|
||||
import org.mozilla.gecko.db.BrowserContract.Tabs;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.db.DBUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
@ -248,6 +246,7 @@ public class TabsProvider extends ContentProvider {
|
||||
return dbHelper;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
private String getDatabasePath(String profile) {
|
||||
trace("Getting database path for profile: " + profile);
|
||||
|
||||
|
@ -5,16 +5,15 @@
|
||||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.BrowserApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.ZoomConstraints;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
|
||||
import org.mozilla.gecko.util.EventDispatcher;
|
||||
import org.mozilla.gecko.util.FloatUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
@ -56,7 +55,6 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
||||
*/
|
||||
private ImmutableViewportMetrics mFrameMetrics;
|
||||
|
||||
/* Used by robocop for testing purposes */
|
||||
private DrawListener mDrawListener;
|
||||
|
||||
/* Used as temporaries by syncViewportInfo */
|
||||
@ -975,11 +973,13 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! */
|
||||
@RobocopTarget
|
||||
public void setDrawListener(DrawListener listener) {
|
||||
mDrawListener = listener;
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! */
|
||||
@RobocopTarget
|
||||
public static interface DrawListener {
|
||||
public void drawFinished();
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import android.graphics.RectF;
|
||||
import android.opengl.GLES20;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.mozglue.JNITarget;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@ -81,7 +82,6 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
private boolean mProfileRender;
|
||||
private long mProfileOutputTime;
|
||||
|
||||
/* Used by robocop for testing purposes */
|
||||
private IntBuffer mPixelBuffer;
|
||||
|
||||
// Used by GLES 2.0
|
||||
@ -489,6 +489,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
}
|
||||
|
||||
/** This function is invoked via JNI; be careful when modifying signature. */
|
||||
@JNITarget
|
||||
public void beginDrawing() {
|
||||
mFrameStartTime = System.nanoTime();
|
||||
|
||||
@ -578,6 +579,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
}
|
||||
|
||||
/** This function is invoked via JNI; be careful when modifying signature. */
|
||||
@JNITarget
|
||||
public void drawBackground() {
|
||||
// Any GL state which is changed here must be restored in
|
||||
// CompositorOGL::RestoreState
|
||||
@ -612,7 +614,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
rootLayer.draw(mPageContext);
|
||||
}
|
||||
|
||||
/** This function is invoked via JNI; be careful when modifying signature. */
|
||||
@JNITarget
|
||||
public void drawForeground() {
|
||||
// Any GL state which is changed here must be restored in
|
||||
// CompositorOGL::RestoreState
|
||||
@ -666,6 +668,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
||||
}
|
||||
|
||||
/** This function is invoked via JNI; be careful when modifying signature. */
|
||||
@JNITarget
|
||||
public void endDrawing() {
|
||||
// If a layer update requires further work, schedule another redraw
|
||||
if (!mUpdated)
|
||||
|
@ -15,6 +15,7 @@ import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.SearchEngine;
|
||||
import org.mozilla.gecko.home.SearchLoader.SearchCursorLoader;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
import org.mozilla.gecko.toolbar.AutocompleteHandler;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
@ -27,10 +28,8 @@ import org.json.JSONObject;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
@ -96,6 +95,7 @@ public class BrowserSearch extends HomeFragment
|
||||
private HomeListView mList;
|
||||
|
||||
// Client that performs search suggestion queries
|
||||
@RobocopTarget
|
||||
private volatile SuggestClient mSuggestClient;
|
||||
|
||||
// List of search engines from gecko
|
||||
|
@ -13,6 +13,7 @@ import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
@ -53,8 +54,13 @@ class SuggestClient {
|
||||
mCheckNetwork = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor is used exclusively by Robocop.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public SuggestClient(Context context, String suggestTemplate, int timeout) {
|
||||
this(context, suggestTemplate, timeout, Integer.MAX_VALUE);
|
||||
mCheckNetwork = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,8 +18,11 @@ mgjar.sources += [
|
||||
'mozglue/generatorannotations/OptionalGeneratedParameter.java',
|
||||
'mozglue/generatorannotations/WrapElementForJNI.java',
|
||||
'mozglue/generatorannotations/WrapEntireClassForJNI.java',
|
||||
'mozglue/JNITarget.java',
|
||||
'mozglue/NativeReference.java',
|
||||
'mozglue/NativeZip.java',
|
||||
'mozglue/RobocopTarget.java',
|
||||
'mozglue/WebRTCJNITarget.java',
|
||||
]
|
||||
mgjar.generated_sources += [
|
||||
'org/mozilla/gecko/mozglue/GeckoLoader.java',
|
||||
|
11
mobile/android/base/mozglue/JNITarget.java
Normal file
@ -0,0 +1,11 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.mozglue;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface JNITarget {}
|
12
mobile/android/base/mozglue/RobocopTarget.java
Normal file
@ -0,0 +1,12 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.mozglue;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface RobocopTarget {}
|
||||
|
11
mobile/android/base/mozglue/WebRTCJNITarget.java
Normal file
@ -0,0 +1,11 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.mozglue;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface WebRTCJNITarget {}
|
@ -10,6 +10,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map.Entry;
|
||||
@ -120,7 +121,7 @@ public class SQLiteBridge {
|
||||
return rawQuery(sb.toString(), selectionArgs);
|
||||
}
|
||||
|
||||
/* This method is referenced by Robocop via reflection. */
|
||||
@RobocopTarget
|
||||
public Cursor rawQuery(String sql, String[] selectionArgs)
|
||||
throws SQLiteBridgeException {
|
||||
return internalQuery(sql, selectionArgs);
|
||||
|
@ -106,14 +106,10 @@ public class testSearchSuggestions extends BaseTest {
|
||||
ClassLoader classLoader = getActivity().getApplicationContext().getClassLoader();
|
||||
Class suggestClass = classLoader.loadClass("org.mozilla.gecko.home.SuggestClient");
|
||||
Constructor suggestConstructor = suggestClass.getConstructor(
|
||||
new Class[] { Context.class, String.class, int.class, int.class });
|
||||
new Class[] { Context.class, String.class, int.class });
|
||||
String suggestTemplate = getAbsoluteRawUrl(SUGGESTION_TEMPLATE);
|
||||
Object client = suggestConstructor.newInstance(activity, suggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
|
||||
|
||||
// enable offline HTTP requests for testing
|
||||
final Field checkNetworkField = suggestClass.getDeclaredField("mCheckNetwork");
|
||||
checkNetworkField.setAccessible(true);
|
||||
checkNetworkField.setBoolean(client, false);
|
||||
Object client = suggestConstructor.newInstance(activity, suggestTemplate, SUGGESTION_TIMEOUT);
|
||||
|
||||
// replace mSuggestClient with test client
|
||||
final Class browserSearchClass = classLoader.loadClass("org.mozilla.gecko.home.BrowserSearch");
|
||||
|
@ -6,10 +6,9 @@
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
/* This class is referenced by Robocop via reflection; use care when
|
||||
* modifying the signature.
|
||||
*/
|
||||
@RobocopTarget
|
||||
public interface GeckoEventListener {
|
||||
void handleMessage(String event, JSONObject message);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -98,7 +99,7 @@ public final class GeckoJarReader {
|
||||
return new NativeZip(fileUrl.getPath());
|
||||
}
|
||||
|
||||
// Public for testing only.
|
||||
@RobocopTarget
|
||||
public static InputStream getStream(String url) {
|
||||
Stack<String> jarUrls = parseUrl(url);
|
||||
try {
|
||||
|
@ -141,7 +141,8 @@ nsAppStartup::nsAppStartup() :
|
||||
mRestart(false),
|
||||
mInterrupted(false),
|
||||
mIsSafeModeNecessary(false),
|
||||
mStartupCrashTrackingEnded(false)
|
||||
mStartupCrashTrackingEnded(false),
|
||||
mRestartTouchEnvironment(false)
|
||||
{ }
|
||||
|
||||
|
||||
@ -269,7 +270,14 @@ nsAppStartup::Run(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return mRestart ? NS_SUCCESS_RESTART_APP : NS_OK;
|
||||
nsresult retval = NS_OK;
|
||||
if (mRestartTouchEnvironment) {
|
||||
retval = NS_SUCCESS_RESTART_METRO_APP;
|
||||
} else if (mRestart) {
|
||||
retval = NS_SUCCESS_RESTART_APP;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@ -360,7 +368,12 @@ nsAppStartup::Quit(uint32_t aMode)
|
||||
gRestartMode = (aMode & 0xF0);
|
||||
}
|
||||
|
||||
if (mRestart) {
|
||||
if (!mRestartTouchEnvironment) {
|
||||
mRestartTouchEnvironment = (aMode & eRestartTouchEnvironment) != 0;
|
||||
gRestartMode = (aMode & 0xF0);
|
||||
}
|
||||
|
||||
if (mRestart || mRestartTouchEnvironment) {
|
||||
// Mark the next startup as a restart.
|
||||
PR_SetEnv("MOZ_APP_RESTART=1");
|
||||
|
||||
@ -430,7 +443,8 @@ nsAppStartup::Quit(uint32_t aMode)
|
||||
NS_NAMED_LITERAL_STRING(shutdownStr, "shutdown");
|
||||
NS_NAMED_LITERAL_STRING(restartStr, "restart");
|
||||
obsService->NotifyObservers(nullptr, "quit-application",
|
||||
mRestart ? restartStr.get() : shutdownStr.get());
|
||||
(mRestart || mRestartTouchEnvironment) ?
|
||||
restartStr.get() : shutdownStr.get());
|
||||
}
|
||||
|
||||
if (!mRunning) {
|
||||
@ -553,6 +567,14 @@ nsAppStartup::GetWasRestarted(bool *aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAppStartup::GetRestartingTouchEnvironment(bool *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = mRestartTouchEnvironment;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAppStartup::SetInterrupted(bool aInterrupted)
|
||||
{
|
||||
|
@ -62,6 +62,7 @@ private:
|
||||
bool mInterrupted; // Was startup interrupted by an interactive prompt?
|
||||
bool mIsSafeModeNecessary; // Whether safe mode is necessary
|
||||
bool mStartupCrashTrackingEnded; // Whether startup crash tracking has already ended
|
||||
bool mRestartTouchEnvironment; // Quit (eRestartTouchEnvironment)
|
||||
|
||||
#if defined(XP_WIN)
|
||||
//Interaction with OS-provided profiling probes
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
interface nsICmdLineService;
|
||||
|
||||
[scriptable, uuid(9edef217-e664-4938-85a7-2fe84baa1755)]
|
||||
[scriptable, uuid(bc0cb41f-4924-4c69-a65b-e35225a8650f)]
|
||||
|
||||
interface nsIAppStartup : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -30,6 +31,11 @@ interface nsIAppStartup : nsISupports
|
||||
* @returnCode NS_SUCCESS_RESTART_APP
|
||||
* This return code indicates that the application should be
|
||||
* restarted because quit was called with the eRestart flag.
|
||||
|
||||
* @returnCode NS_SUCCESS_RESTART_METRO_APP
|
||||
* This return code indicates that the application should be
|
||||
* restarted in metro because quit was called with the
|
||||
* eRestartTouchEnviroment flag.
|
||||
*/
|
||||
void run();
|
||||
|
||||
@ -121,6 +127,13 @@ interface nsIAppStartup : nsISupports
|
||||
*/
|
||||
const uint32_t eRestartx86_64 = 0x40;
|
||||
|
||||
/**
|
||||
* Restart the application in a touch-optimized environment (such as Metro)
|
||||
* after quitting. The application will be restarted with the same profile
|
||||
* and an empty command line.
|
||||
*/
|
||||
const uint32_t eRestartTouchEnvironment = 0x80;
|
||||
|
||||
/**
|
||||
* Exit the event loop, and shut down the app.
|
||||
*
|
||||
@ -160,6 +173,12 @@ interface nsIAppStartup : nsISupports
|
||||
*/
|
||||
readonly attribute boolean wasRestarted;
|
||||
|
||||
/**
|
||||
* True if the application is being restarted in a touch-optimized
|
||||
* environment (such as Metro).
|
||||
*/
|
||||
readonly attribute boolean restartingTouchEnvironment;
|
||||
|
||||
/**
|
||||
* Returns an object with main, process, firstPaint, sessionRestored properties.
|
||||
* Properties may not be available depending on platform or application
|
||||
|
@ -673,8 +673,17 @@
|
||||
</field>
|
||||
|
||||
<property name="userTypedValue"
|
||||
onget="return this._userTypedValue;"
|
||||
onset="this.userTypedClear = 0; return this._userTypedValue = val;"/>
|
||||
onget="return this._userTypedValue;">
|
||||
<setter><![CDATA[
|
||||
this.userTypedClear = 0;
|
||||
this._userTypedValue = val;
|
||||
|
||||
let event = new CustomEvent("UserTypedValueChanged");
|
||||
this.dispatchEvent(event);
|
||||
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<field name="mFormFillAttached">
|
||||
false
|
||||
|
161
toolkit/modules/WindowsPrefSync.jsm
Normal file
@ -0,0 +1,161 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_METRO
|
||||
|
||||
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} =
|
||||
Components;
|
||||
const PREF_BASE_KEY = "Software\\Mozilla\\Firefox\\Metro\\Prefs\\";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "WindowsPrefSync" ];
|
||||
|
||||
/**
|
||||
* Manages preferences that need to be pulled and pushed between Metro
|
||||
* and desktop.
|
||||
*/
|
||||
this.WindowsPrefSync = {
|
||||
init: function() {
|
||||
this.pullSharedPrefs();
|
||||
this.prefListToPush.forEach(function(prefName) {
|
||||
this.pushSharedPref(prefName);
|
||||
Services.prefs.addObserver(prefName, this, false);
|
||||
}, this);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
this.prefListToPush.forEach(function(prefName) {
|
||||
Services.prefs.removeObserver(prefName, this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the list of prefs that should be pushed for the current
|
||||
* environment.
|
||||
*/
|
||||
get prefListToPush() {
|
||||
return !Services.metro.immersive ? this.desktopControlledPrefs :
|
||||
this.metroControlledPrefs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the list of prefs that should be pulled for the current
|
||||
* environment.
|
||||
*/
|
||||
get prefListToPull() {
|
||||
return Services.metro.immersive ? this.desktopControlledPrefs :
|
||||
this.metroControlledPrefs;
|
||||
},
|
||||
|
||||
/**
|
||||
* The following preferences will be pushed to registry from Desktop
|
||||
* Firefox and pulled in from Metro Firefox.
|
||||
*
|
||||
* app.update.* prefs are because Metro shares an installation directory with
|
||||
* Firefox, and the options for these are only present in the Desktop options.
|
||||
*
|
||||
* browser.sessionstore.resume_session_once is mainly for the switch to Metro
|
||||
* and switch to Desktop feature.
|
||||
*/
|
||||
desktopControlledPrefs: ["app.update.auto",
|
||||
"app.update.enabled",
|
||||
"app.update.service.enabled",
|
||||
"app.update.metro.enabled",
|
||||
"browser.sessionstore.resume_session_once"],
|
||||
|
||||
/**
|
||||
* The following preferences will be pushed to registry from Metro
|
||||
* Firefox and pulled in from Desktop Firefox.
|
||||
*
|
||||
* browser.sessionstore.resume_session_once is mainly for the switch to Metro
|
||||
* and switch to Desktop feature.
|
||||
*/
|
||||
metroControlledPrefs: ["browser.sessionstore.resume_session_once"],
|
||||
|
||||
/**
|
||||
* Observes preference changes and writes them to the registry, only
|
||||
* the list of preferences initialized will be observed
|
||||
*/
|
||||
observe: function (aSubject, aTopic, aPrefName) {
|
||||
if (aTopic != "nsPref:changed")
|
||||
return;
|
||||
|
||||
this.pushSharedPref(aPrefName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes the pref to HKCU in the registry and adds a pref-observer to keep
|
||||
* the registry in sync with changes to the value.
|
||||
*/
|
||||
pushSharedPref : function(aPrefName) {
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
var prefType = Services.prefs.getPrefType(aPrefName);
|
||||
let prefFunc;
|
||||
if (prefType == Ci.nsIPrefBranch.PREF_INT)
|
||||
prefFunc = "getIntPref";
|
||||
else if (prefType == Ci.nsIPrefBranch.PREF_BOOL)
|
||||
prefFunc = "getBoolPref";
|
||||
else if (prefType == Ci.nsIPrefBranch.PREF_STRING)
|
||||
prefFunc = "getCharPref";
|
||||
else
|
||||
throw "Unsupported pref type";
|
||||
|
||||
let prefValue = Services.prefs[prefFunc](aPrefName);
|
||||
registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
PREF_BASE_KEY + prefType,
|
||||
Ci.nsIWindowsRegKey.ACCESS_WRITE);
|
||||
// Always write as string, but the registry subfolder will determine
|
||||
// how Metro interprets that string value.
|
||||
registry.writeStringValue(aPrefName, prefValue);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Couldn't push pref " + aPrefName + ": " + ex);
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Pulls in all shared prefs from the registry
|
||||
*/
|
||||
pullSharedPrefs: function() {
|
||||
function pullSharedPrefType(prefType, prefFunc) {
|
||||
try {
|
||||
registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
PREF_BASE_KEY + prefType,
|
||||
Ci.nsIWindowsRegKey.ACCESS_ALL);
|
||||
for (let i = 0; i < registry.valueCount; i++) {
|
||||
let prefName = registry.getValueName(i);
|
||||
let prefValue = registry.readStringValue(prefName);
|
||||
if (prefType == Ci.nsIPrefBranch.PREF_BOOL) {
|
||||
prefValue = prefValue == "true";
|
||||
}
|
||||
if (self.prefListToPull.indexOf(prefName) != -1) {
|
||||
Services.prefs[prefFunc](prefName, prefValue);
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
dump("Could not pull for prefType " + prefType + ": " + ex + "\n");
|
||||
} finally {
|
||||
registry.close();
|
||||
}
|
||||
}
|
||||
let self = this;
|
||||
let registry = Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(Ci.nsIWindowsRegKey);
|
||||
pullSharedPrefType(Ci.nsIPrefBranch.PREF_INT, "setIntPref");
|
||||
pullSharedPrefType(Ci.nsIPrefBranch.PREF_BOOL, "setBoolPref");
|
||||
pullSharedPrefType(Ci.nsIPrefBranch.PREF_STRING, "setCharPref");
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
@ -52,6 +52,7 @@ EXTRA_PP_JS_MODULES += [
|
||||
'Troubleshoot.jsm',
|
||||
'UpdateChannel.jsm',
|
||||
'WindowDraggingUtils.jsm',
|
||||
'WindowsPrefSync.jsm',
|
||||
]
|
||||
|
||||
if 'Android' != CONFIG['OS_TARGET']:
|
||||
|
@ -127,6 +127,10 @@
|
||||
#include "nsXREDirProvider.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_METRO)
|
||||
#include "updatehelper.h"
|
||||
#endif
|
||||
|
||||
#include "nsINIParser.h"
|
||||
#include "mozilla/Omnijar.h"
|
||||
#include "mozilla/StartupTimeline.h"
|
||||
@ -4047,12 +4051,18 @@ XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
||||
|
||||
// Check for an application initiated restart. This is one that
|
||||
// corresponds to nsIAppStartup.quit(eRestart)
|
||||
if (rv == NS_SUCCESS_RESTART_APP) {
|
||||
if (rv == NS_SUCCESS_RESTART_APP || rv == NS_SUCCESS_RESTART_METRO_APP) {
|
||||
appInitiatedRestart = true;
|
||||
|
||||
// We have an application restart don't do any shutdown checks here
|
||||
// In particular we don't want to poison IO for checking late-writes.
|
||||
gShutdownChecks = SCM_NOTHING;
|
||||
|
||||
#if defined(MOZ_METRO) && defined(XP_WIN)
|
||||
if (rv == NS_SUCCESS_RESTART_METRO_APP) {
|
||||
LaunchDefaultMetroBrowser();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!mShuttingDown) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
* implementation of this interface for non-Windows systems, for testing and
|
||||
* development purposes only.
|
||||
*/
|
||||
[scriptable, uuid(496b4450-5757-40f7-aeb9-a958ae86dbd1)]
|
||||
[scriptable, uuid(d30daa27-ce2b-4503-80cc-b162f4c24e93)]
|
||||
interface nsIWinMetroUtils : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -84,29 +84,6 @@ interface nsIWinMetroUtils : nsISupports
|
||||
*/
|
||||
bool isTilePinned(in AString aTileID);
|
||||
|
||||
/**
|
||||
* Stores the sync info securely
|
||||
*
|
||||
* @param aEmail The sync account email
|
||||
* @param aPassword The sync account password
|
||||
* @param aKey The sync account key
|
||||
*/
|
||||
void storeSyncInfo(in AString aEmail, in AString aPassword, in AString aKey);
|
||||
|
||||
/**
|
||||
* Loads the sync info
|
||||
*
|
||||
* @param aEmail The sync account email
|
||||
* @param aPassword The sync account password
|
||||
* @param aKey The sync account key
|
||||
*/
|
||||
void loadSyncInfo(out AString aEmail, out AString aPassword, out AString aKey);
|
||||
|
||||
/**
|
||||
* Clears the stored sync info if any.
|
||||
*/
|
||||
void clearSyncInfo();
|
||||
|
||||
/**
|
||||
* Soft keyboard attributes. Used in unison with shown/hidden observer
|
||||
* events sent via FrameworkView.
|
||||
|
@ -125,6 +125,8 @@
|
||||
#include "nsIWidgetListener.h"
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsIAppStartup.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_D3D9_LAYER
|
||||
@ -174,6 +176,10 @@
|
||||
|
||||
#include "npapi.h"
|
||||
|
||||
#if !defined(SM_CONVERTIBLESLATEMODE)
|
||||
#define SM_CONVERTIBLESLATEMODE 0x2003
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
@ -5462,6 +5468,21 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_SETTINGCHANGE:
|
||||
if (IsWin8OrLater() && lParam &&
|
||||
!wcsicmp(L"ConvertibleSlateMode", (wchar_t*)lParam)) {
|
||||
// If we're switching into slate mode, switch to Metro for hardware
|
||||
// that supports this feature.
|
||||
if (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0) {
|
||||
nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
|
||||
if (appStartup) {
|
||||
appStartup->Quit(nsIAppStartup::eForceQuit |
|
||||
nsIAppStartup::eRestartTouchEnvironment);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//*aRetValue = result;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "WinUtils.h"
|
||||
#include "nsIAppStartup.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include <shellapi.h>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::widget;
|
||||
@ -113,7 +114,7 @@ HRESULT SHCreateShellItemArrayFromShellItemDynamic(IShellItem *psi, REFIID riid,
|
||||
}
|
||||
|
||||
BOOL
|
||||
WinLaunchDeferredMetroFirefox()
|
||||
WinLaunchDeferredMetroFirefox(bool aInMetro)
|
||||
{
|
||||
// Create an instance of the Firefox Metro DEH which is used to launch the browser
|
||||
const CLSID CLSID_FirefoxMetroDEH = {0x5100FEC1,0x212B, 0x4BF5 ,{0x9B,0xF8, 0x3E,0x65, 0x0F,0xD7,0x94,0xA3}};
|
||||
@ -159,7 +160,11 @@ WinLaunchDeferredMetroFirefox()
|
||||
if (FAILED(hr))
|
||||
return FALSE;
|
||||
|
||||
hr = executeCommand->SetParameters(L"--metro-restart");
|
||||
if (aInMetro) {
|
||||
hr = executeCommand->SetParameters(L"--metro-restart");
|
||||
} else {
|
||||
hr = executeCommand->SetParameters(L"--desktop-restart");
|
||||
}
|
||||
if (FAILED(hr))
|
||||
return FALSE;
|
||||
|
||||
@ -195,17 +200,36 @@ MetroAppShell::Run(void)
|
||||
mozilla::widget::StopAudioSession();
|
||||
|
||||
nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
|
||||
bool restarting;
|
||||
if (appStartup && NS_SUCCEEDED(appStartup->GetRestarting(&restarting)) && restarting) {
|
||||
if (!WinLaunchDeferredMetroFirefox()) {
|
||||
NS_WARNING("Couldn't deferred launch Metro Firefox.");
|
||||
}
|
||||
bool restartingInMetro = false, restarting = false;
|
||||
|
||||
if (appStartup && NS_SUCCEEDED(appStartup->GetRestartingTouchEnvironment(&restartingInMetro)) &&
|
||||
restartingInMetro) {
|
||||
WinLaunchDeferredMetroFirefox(true);
|
||||
}
|
||||
|
||||
if (!appStartup || NS_FAILED(appStartup->GetRestarting(&restarting))) {
|
||||
WinUtils::Log("appStartup->GetRestarting() unsuccessful");
|
||||
}
|
||||
|
||||
// This calls XRE_metroShutdown() in xre. This will also destroy
|
||||
// MessagePump.
|
||||
sMetroApp->ShutdownXPCOM();
|
||||
|
||||
if (restarting) {
|
||||
SHELLEXECUTEINFOW sinfo;
|
||||
memset(&sinfo, 0, sizeof(SHELLEXECUTEINFOW));
|
||||
sinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||
// Per the Metro style enabled desktop browser, for some reason,
|
||||
// SEE_MASK_FLAG_LOG_USAGE is needed to change from immersive mode
|
||||
// to desktop.
|
||||
sinfo.fMask = SEE_MASK_FLAG_LOG_USAGE;
|
||||
sinfo.lpFile = L"http://-desktop";
|
||||
sinfo.lpVerb = L"open";
|
||||
sinfo.lpParameters = L"--desktop-restart";
|
||||
sinfo.nShow = SW_SHOWNORMAL;
|
||||
ShellExecuteEx(&sinfo);
|
||||
}
|
||||
|
||||
// This will free the real main thread in CoreApplication::Run()
|
||||
// once winrt cleans up this thread.
|
||||
sMetroApp->CoreExit();
|
||||
|
@ -60,6 +60,10 @@ using namespace ABI::Windows::Graphics::Display;
|
||||
extern PRLogModuleInfo* gWindowsLog;
|
||||
#endif
|
||||
|
||||
#if !defined(SM_CONVERTIBLESLATEMODE)
|
||||
#define SM_CONVERTIBLESLATEMODE 0x2003
|
||||
#endif
|
||||
|
||||
static uint32_t gInstanceCount = 0;
|
||||
const PRUnichar* kMetroSubclassThisProp = L"MetroSubclassThisProp";
|
||||
HWND MetroWidget::sICoreHwnd = nullptr;
|
||||
@ -710,6 +714,17 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
|
||||
{
|
||||
if(sDefaultBrowserMsgId == aMsg) {
|
||||
CloseGesture();
|
||||
} else if (WM_SETTINGCHANGE == aMsg) {
|
||||
if (aLParam && !wcsicmp(L"ConvertibleSlateMode", (wchar_t*)aLParam)) {
|
||||
// If we're switching away from slate mode, switch to Desktop for
|
||||
// hardware that supports this feature.
|
||||
if (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) != 0) {
|
||||
nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
|
||||
if (appStartup) {
|
||||
appStartup->Quit(nsIAppStartup::eForceQuit | nsIAppStartup::eRestart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Indicates if we should hand messages to the default windows
|
||||
|
@ -8,14 +8,12 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "FrameworkView.h"
|
||||
#include "MetroApp.h"
|
||||
#include "nsIWindowsRegKey.h"
|
||||
#include "ToastNotificationHandler.h"
|
||||
|
||||
#include <shldisp.h>
|
||||
#include <shellapi.h>
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
#include <windows.ui.startscreen.h>
|
||||
#include <Wincrypt.h>
|
||||
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::UI::StartScreen;
|
||||
@ -35,11 +33,6 @@ extern ComPtr<FrameworkView> sFrameworkView;
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
static LPCWSTR sSyncEmailField = L"sync-e";
|
||||
static LPCWSTR sSyncPasswordField = L"sync-p";
|
||||
static LPCWSTR sSyncKeyField = L"sync-k";
|
||||
static LPCSTR sRegPath = "Software\\Mozilla\\Firefox";
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsWinMetroUtils, nsIWinMetroUtils)
|
||||
|
||||
nsWinMetroUtils::nsWinMetroUtils()
|
||||
@ -176,147 +169,6 @@ nsWinMetroUtils::IsTilePinned(const nsAString &aTileID, bool *aIsPinned)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the sync info securely in Windows
|
||||
*
|
||||
* @param aEmail The sync account email
|
||||
* @param aPassword The sync account password
|
||||
* @param aKey The sync account key
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::StoreSyncInfo(const nsAString &aEmail,
|
||||
const nsAString &aPassword,
|
||||
const nsAString &aKey)
|
||||
{
|
||||
DATA_BLOB emailIn = {
|
||||
(aEmail.Length() + 1) * 2,
|
||||
(BYTE *)aEmail.BeginReading()},
|
||||
passwordIn = {
|
||||
(aPassword.Length() + 1) * 2,
|
||||
(BYTE *)aPassword.BeginReading()},
|
||||
keyIn = {
|
||||
(aKey.Length() + 1) * 2,
|
||||
(BYTE *)aKey.BeginReading()};
|
||||
DATA_BLOB emailOut = { 0, nullptr }, passwordOut = {0, nullptr }, keyOut = { 0, nullptr };
|
||||
bool succeeded = CryptProtectData(&emailIn, nullptr, nullptr, nullptr,
|
||||
nullptr, 0, &emailOut) &&
|
||||
CryptProtectData(&passwordIn, nullptr, nullptr, nullptr,
|
||||
nullptr, 0, &passwordOut) &&
|
||||
CryptProtectData(&keyIn, nullptr, nullptr, nullptr,
|
||||
nullptr, 0, &keyOut);
|
||||
|
||||
if (succeeded) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey
|
||||
(do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_ConvertUTF8toUTF16(sRegPath),
|
||||
nsIWindowsRegKey::ACCESS_SET_VALUE);
|
||||
|
||||
if (NS_FAILED(regKey->WriteBinaryValue(nsDependentString(sSyncEmailField),
|
||||
nsAutoCString((const char *)emailOut.pbData,
|
||||
emailOut.cbData)))) {
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
if (succeeded &&
|
||||
NS_FAILED(regKey->WriteBinaryValue(nsDependentString(sSyncPasswordField),
|
||||
nsAutoCString((const char *)passwordOut.pbData,
|
||||
passwordOut.cbData)))) {
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
if (succeeded &&
|
||||
NS_FAILED(regKey->WriteBinaryValue(nsDependentString(sSyncKeyField),
|
||||
nsAutoCString((const char *)keyOut.pbData,
|
||||
keyOut.cbData)))) {
|
||||
succeeded = false;
|
||||
}
|
||||
regKey->Close();
|
||||
}
|
||||
|
||||
LocalFree(emailOut.pbData);
|
||||
LocalFree(passwordOut.pbData);
|
||||
LocalFree(keyOut.pbData);
|
||||
|
||||
return succeeded ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the sync info securely in Windows
|
||||
*
|
||||
* @param aEmail The sync account email
|
||||
* @param aPassword The sync account password
|
||||
* @param aKey The sync account key
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::LoadSyncInfo(nsAString &aEmail, nsAString &aPassword,
|
||||
nsAString &aKey)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey
|
||||
(do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_ConvertUTF8toUTF16(sRegPath),
|
||||
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
|
||||
|
||||
nsAutoCString email, password, key;
|
||||
if (NS_FAILED(regKey->ReadBinaryValue(nsDependentString(sSyncEmailField), email)) ||
|
||||
NS_FAILED(regKey->ReadBinaryValue(nsDependentString(sSyncPasswordField), password)) ||
|
||||
NS_FAILED(regKey->ReadBinaryValue(nsDependentString(sSyncKeyField), key))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
regKey->Close();
|
||||
|
||||
DATA_BLOB emailIn = { email.Length(), (BYTE*)email.BeginReading() },
|
||||
passwordIn = { password.Length(), (BYTE*)password.BeginReading() },
|
||||
keyIn = { key.Length(), (BYTE*)key.BeginReading() };
|
||||
DATA_BLOB emailOut = { 0, nullptr }, passwordOut = { 0, nullptr }, keyOut = { 0, nullptr };
|
||||
bool succeeded = CryptUnprotectData(&emailIn, nullptr, nullptr, nullptr,
|
||||
nullptr, 0, &emailOut) &&
|
||||
CryptUnprotectData(&passwordIn, nullptr, nullptr, nullptr,
|
||||
nullptr, 0, &passwordOut) &&
|
||||
CryptUnprotectData(&keyIn, nullptr, nullptr, nullptr,
|
||||
nullptr, 0, &keyOut);
|
||||
if (succeeded) {
|
||||
aEmail = reinterpret_cast<wchar_t*>(emailOut.pbData);
|
||||
aPassword = reinterpret_cast<wchar_t*>(passwordOut.pbData);
|
||||
aKey = reinterpret_cast<wchar_t*>(keyOut.pbData);
|
||||
}
|
||||
|
||||
LocalFree(emailOut.pbData);
|
||||
LocalFree(passwordOut.pbData);
|
||||
LocalFree(keyOut.pbData);
|
||||
|
||||
return succeeded ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the stored sync info if any.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::ClearSyncInfo()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey
|
||||
(do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
|
||||
NS_ConvertUTF8toUTF16(sRegPath),
|
||||
nsIWindowsRegKey::ACCESS_WRITE);
|
||||
nsresult rv1 = regKey->RemoveValue(nsDependentString(sSyncEmailField));
|
||||
nsresult rv2 = regKey->RemoveValue(nsDependentString(sSyncPasswordField));
|
||||
nsresult rv3 = regKey->RemoveValue(nsDependentString(sSyncKeyField));
|
||||
regKey->Close();
|
||||
|
||||
if (NS_FAILED(rv1) || NS_FAILED(rv2) || NS_FAILED(rv3)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the specified application with the specified arguments and
|
||||
* switches to Desktop mode if in metro mode.
|
||||
|
@ -856,6 +856,7 @@
|
||||
* the application should be restarted. This condition corresponds to the
|
||||
* case in which nsIAppStartup::Quit was called with the eRestart flag. */
|
||||
ERROR(NS_SUCCESS_RESTART_APP, SUCCESS(1)),
|
||||
ERROR(NS_SUCCESS_RESTART_METRO_APP, SUCCESS(1)),
|
||||
ERROR(NS_SUCCESS_UNORM_NOTFOUND, SUCCESS(17)),
|
||||
|
||||
|
||||
|