Merge m-c to m-i

This commit is contained in:
Phil Ringnalda 2013-09-18 23:28:41 -07:00
commit 95c5bfc8b9
122 changed files with 1951 additions and 864 deletions

View File

@ -66,6 +66,16 @@ WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
endif
endif #LIBXUL_SDK
UA_UPDATE_FILE = ua-update.json
$(UA_UPDATE_FILE): % : %.in
# strip out comment lines, which are not valid in JSON
sed -e "/^ *\\/\\//d" -e "/^ *$$/d" $^ > $@
UA_UPDATE_FILES = $(UA_UPDATE_FILE)
UA_UPDATE_DEST = $(FINAL_TARGET)
INSTALL_TARGETS += UA_UPDATE
# Make sure the standalone glue doesn't try to get libxpcom.so from b2g/app.
NSDISTMODE = copy

View File

@ -736,6 +736,11 @@ pref("memory_info_dumper.watch_fifo.enabled", true);
pref("memory_info_dumper.watch_fifo.directory", "/data/local");
pref("general.useragent.enable_overrides", true);
// See ua-update.json.in for the packaged UA override list
pref("general.useragent.updates.enabled", true);
pref("general.useragent.updates.url", "");
pref("general.useragent.updates.interval", 604800); // 1 week
pref("general.useragent.updates.retry", 86400); // 1 day
// Make <audio> and <video> talk to the AudioChannelService.
pref("media.useAudioChannelService", true);

276
b2g/app/ua-update.json.in Normal file
View File

@ -0,0 +1,276 @@
// Comments must be on their own lines and must start with "//"
// Send these sites a custom user-agent. Bugs to remove each override after
// evangelism are included.
{
// bug 802981, maps.google.com
"maps.google.com": "\\(Mobile#(Android; Mobile",
// bug 826330, uol.com.br
"uol.com.br": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826332, live.com
"live.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826335, globo.com
"globo.com": "\\(Mobile#(Android; Mobile",
// bug 826338, yahoo.com
"yahoo.com": "\\(Mobile#(Android; Mobile",
// bug 826342, mercadolivre.com.br
"mercadolivre.com.br": "\\(Mobile#(Android; Mobile",
// bug 826343, ig.com.br
"ig.com.br": "\\(Mobile#(Android; Mobile",
// bug 826344, abril.com.br
"abril.com.br": "\\(Mobile#(Android; Mobile",
// bug 826347, msn.com
"msn.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826348, linkedin.com
"linkedin.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826353, itau.com.br
"itau.com.br": "\\(Mobile#(Android; Mobile",
// bug 826504, orkut.com.br
"orkut.com.br": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826510, r7.com
"r7.com": "\\(Mobile#(Android; Mobile",
// bug 826514, estadao.com.br
"estadao.com.br": "\\(Mobile#(Android; Mobile",
// bug 826517, letras.mus.br
"letras.mus.br": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826711, bb.com.br
"bb.com.br": "\\(Mobile#(Android; Mobile",
// bug 826712, orkut.com
"orkut.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 826715, noticias.uol.com.br
"noticias.uol.com.br": "\\(Mobile#(Android; Mobile",
// bug 826720, olx.com.br
"olx.com.br": "\\(Mobile#(Android; Mobile",
// bug 826736, bancobrasil.com.br
"bancobrasil.com.br": "\\(Mobile#(Android; Mobile",
// bug 826845, techtudo.com.br
"techtudo.com.br": "\\(Mobile#(Android; Mobile",
// bug 826958, ebay.com
"ebay.com": "\\(Mobile#(Android; Mobile",
// bug 827622, bing.com
"bing.com": "\\(Mobile#(Android; Mobile",
// bug 827625, pagseguro.uol.com.br
"pagseguro.uol.com.br": "\\(Mobile#(Android; Mobile",
// bug 827626, magazineluiza.com.br
"magazineluiza.com.br": "\\(Mobile#(Android; Mobile",
// bug 827627, bol.uol.com.br
"bol.uol.com.br": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 827628, groupon.com.br
"groupon.com.br": "\\(Mobile#(Android; Mobile",
// bug 827630, vagalume.com.br
"vagalume.com.br": "\\(Mobile#(Android; Mobile",
// bug 827631, climatempo.com.br
"climatempo.com.br": "\\(Mobile#(Android; Mobile",
// bug 827632, tecmundo.com.br
"tecmundo.com.br": "\\(Mobile#(Android; Mobile",
// bug 827633, hao123.com
"hao123.com": "\\(Mobile#(Android; Mobile",
// bug 827576, lancenet.com.br
"lancenet.com.br": "\\(Mobile#(Android; Mobile",
// bug 827573, webmotors.com.br
"webmotors.com.br": "\\(Mobile#(Android; Mobile",
// bug 827661, mercadolibre.com.co
"mercadolibre.com.co": "\\(Mobile#(Android; Mobile",
// bug 827664, elespectador.com
"elespectador.com": "\\(Mobile#(Android; Mobile",
// bug 827668, scribd.com
"scribd.com": "\\(Mobile#(Android; Mobile",
// bug 827670, elpais.com.co
"elpais.com.co": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 827672, olx.com.co
"olx.com.co": "\\(Mobile#(Android; Mobile",
// bug 827674, avianca.com
"avianca.com": "\\(Mobile#(Android; Mobile",
// bug 827678, marca.com
"marca.com": "\\(Mobile#(Android; Mobile",
// bug 828354, gazeta.pl
"gazeta.pl": "\\(Mobile#(Android; Mobile",
// bug 828360, sport.pl
"sport.pl": "\\(Mobile#(Android; Mobile",
// bug 828364, nk.pl
"nk.pl": "\\(Mobile#(Android; Mobile",
// bug 828366, wyborcza.biz
"wyborcza.biz": "\\(Mobile#(Android; Mobile",
// bug 828369, money.pl
"money.pl": "\\(Mobile#(Android; Mobile",
// bug 828371, ingbank.pl
"ingbank.pl": "\\(Mobile#(Android; Mobile",
// bug 828376, plotek.pl
"plotek.pl": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 828378, wyborcza.pl
"wyborcza.pl": "\\(Mobile#(Android; Mobile",
// bug 828380, deser.pl
"deser.pl": "\\(Mobile#(Android; Mobile",
// bug 828386, ebay.es
"ebay.es": "\\(Mobile#(Android; Mobile",
// bug 828392, infojobs.net
"infojobs.net": "\\(Mobile#(Android; Mobile",
// bug 828399, antena3.com
"antena3.com": "\\(Mobile#(Android; Mobile",
// bug 828401, ingdirect.es
"ingdirect.es": "\\(Mobile#(Android; Mobile",
// bug 828403, fotocasa.es
"fotocasa.es": "\\(Mobile#(Android; Mobile",
// bug 828406, orange.es
"orange.es": "\\(Mobile#(Android; Mobile",
// bug 828414, paginasamarillas.es
"paginasamarillas.es": "\\(Mobile#(Android; Mobile",
// bug 828416, loteriasyapuestas.es
"loteriasyapuestas.es": "\\(Mobile#(Android; Mobile",
// bug 828418, bbva.es
"bbva.es": "\\(Mobile#(Android; Mobile",
// bug 828422, publico.es
"publico.es": "\\(Mobile#(Android; Mobile",
// bug 828425, mercadolibre.com.ve
"mercadolibre.com.ve": "\\(Mobile#(Android; Mobile",
// bug 828433, olx.com.ve
"olx.com.ve": "\\(Mobile#(Android; Mobile",
// bug 828439, movistar.com.ve
"movistar.com.ve": "\\(Mobile#(Android; Mobile",
// bug 828445, bumeran.com.ve
"bumeran.com.ve": "\\(Mobile#(Android; Mobile",
// bug 828448, petardas.com
"petardas.com": "\\(Mobile#(Android; Mobile",
// bug 827869, mail.google.com
"mail.google.com": "\\(Mobile#(Android; Mobile",
// bug 843109, enfemenino.com
"enfemenino.com": "\\(Mobile#(Android; Mobile",
// bug 843112, movil.bankinter.es
"movil.bankinter.es": "\\(Mobile#(Android; Mobile",
// bug 843114, einforma.com
"einforma.com": "\\(Mobile#(Android; Mobile",
// bug 843116, wwwhatsnew.com
"wwwhatsnew.com": "\\(Mobile#(Android; Mobile",
// bug 843119, askthebuilder.com
"askthebuilder.com": "\\(Mobile#(Android; Mobile",
// bug 843121, tor.com
"tor.com": "\\(Mobile#(Android; Mobile",
// bug 843124, maruccisports.com
"maruccisports.com": "\\(Mobile#(Android; Mobile",
// bug 843126, es.playstation.com
"es.playstation.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 843129, 11870.com
"11870.com": "\\(Mobile#(Android; Mobile",
// bug 843200, iphonejuegosgratis.com
"iphonejuegosgratis.com": "\\(Mobile#(Android; Mobile",
// bug 843132, comunio.es
"comunio.es": "\\(Mobile#(Android; Mobile",
// bug 843134, news.google.com
"news.google.com": "\\(Mobile#(Android; Mobile",
// bug 843136, deviantart.com
"deviantart.com": "\\(Mobile#(Android; Mobile",
// bug 843137, nytimes.com
"nytimes.com": "\\(Mobile#(Android; Mobile",
// bug 843139, consumersearch.com
"consumersearch.com": "\\(Mobile#(Android; Mobile",
// bug 843141, foodily.com
"foodily.com": "\\(Mobile#(Android; Mobile",
// bug 843197, icanhas.cheezburger.com
"icanhas.cheezburger.com": "\\(Mobile#(Android; Mobile",
// bug 843151, citibank.com
"citibank.com": "\\(Mobile#(Android; Mobile",
// bug 843153, games.com
"games.com": "\\(Mobile#(Android; Mobile",
// bug 843156, orbitz.com
"orbitz.com": "\\(Mobile#(Android; Mobile",
// bug 843158, starwoodhotels.com
"starwoodhotels.com": "\\(Mobile#(Android; Mobile",
// bug 843160, ehow.com
"ehow.com": "\\(Mobile#(Android; Mobile",
// bug 843162, urbanspoon.com
"urbanspoon.com": "\\(Mobile#(Android; Mobile",
// bug 843165, virginatlantic.com
"virginatlantic.com": "\\(Mobile#(Android; Mobile",
// bug 843168, cheaptickets.com
"cheaptickets.com": "\\(Mobile#(Android; Mobile",
// bug 843172, zimbio.com
"zimbio.com": "\\(Mobile#(Android; Mobile",
// bug 843176, tylted.com
"tylted.com": "\\(Mobile#(Android; Mobile",
// bug 843178, txt2nite.com
"txt2nite.com": "\\(Mobile#(Android; Mobile",
// bug 843181, slashgear.com
"slashgear.com": "\\(Mobile#(Android; Mobile",
// bug 843186, chevrolet.com
"chevrolet.com": "\\(Mobile#(Android; Mobile",
// bug 848854, deadline.com
"deadline.com": "\\(Mobile#(Android; Mobile",
// bug 866577, 3g.qq.com
"3g.qq.com": "\\(Mobile#(Android; Mobile",
// bug 878222, arukereso.hu
"arukereso.hu": "\\(Mobile#(Android; Mobile",
// bug 878228, blikk.hu
"blikk.hu": "\\(Mobile#(Android; Mobile",
// bug 878230, citromail.hu
"citromail.hu": "\\(Mobile#(Android; Mobile",
// bug 878232, hazipatika.com
"hazipatika.com": "\\(Mobile#(Android; Mobile",
// bug 878234, hvg.hu
"hvg.hu": "\\(Mobile#(Android; Mobile",
// bug 878236, jofogas.hu
"jofogas.hu": "\\(Mobile#(Android; Mobile",
// bug 878238, koponyeg.hu
"koponyeg.hu": "\\(Mobile#(Android; Mobile",
// bug 878240, kuruc.info
"kuruc.info": "\\(Mobile#(Android; Mobile",
// bug 878242, nemzetisport.hu
"nemzetisport.hu": "\\(Mobile#(Android; Mobile",
// bug 878244, nlcafe.hu
"nlcafe.hu": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 878246, port.hu
"port.hu": "\\(Mobile#(Android; Mobile",
// bug 878249, portfolio.hu
"portfolio.hu": "\\(Mobile#(Android; Mobile",
// bug 878253, vatera.hu
"vatera.hu": "\\(Mobile#(Android; Mobile",
// bug 878255, 24sata.hr
"24sata.hr": "\\(Mobile#(Android; Mobile",
// bug 878256, bet365.com
"bet365.com": "\\(Mobile#(Android; Mobile",
// bug 878258, blackhatteam.com
"blackhatteam.com": "\\(Mobile#(Android; Mobile",
// bug 878260, cdm.me
"cdm.me": "\\(Mobile#(Android; Mobile",
// bug 878262, download.com
"download.com": "\\(Mobile#(Android; Mobile",
// bug 878264, haber.ba
"haber.ba": "\\(Mobile#(Android; Mobile",
// bug 878268, jutarnji.hr
"jutarnji.hr": "\\(Mobile#(Android; Mobile",
// bug 878271, kurir-info.rs
"kurir-info.rs": "\\(Mobile#(Android; Mobile",
// bug 878273, livescore.com
"livescore.com": "\\(Mobile#(Android; Mobile",
// bug 878275, mondo.rs
"mondo.rs": "\\(Mobile#(Android; Mobile",
// bug 878277, naslovi.net
"naslovi.net": "\\(Mobile#(Android; Mobile",
// bug 878284, softonic.com
"softonic.com": "\\(Mobile#(Android; Mobile",
// bug 878286, yandex.ru
"yandex.ru": "\\(Mobile#(Android; Mobile",
// bug 878630, ask.com
"ask.com": "\\(Mobile#(Android; Mobile",
// bug 878632, banorte.com
"banorte.com": "\\(Mobile#(Android; Mobile",
// bug 878634, buenastareas.com
"buenastareas.com": "\\(Mobile#(Android; Mobile",
// bug 878635, cnn.com
"cnn.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
// bug 878637, eluniversal.com.mx
"eluniversal.com.mx": "\\(Mobile#(Android; Mobile",
// bug 878640, hootsuite.com
"hootsuite.com": "\\(Mobile#(Android; Mobile",
// bug 878642, mercadolibre.com.mx
"mercadolibre.com.mx": "\\(Mobile#(Android; Mobile",
// bug 878645, olx.com.mx
"olx.com.mx": "\\(Mobile#(Android; Mobile",
// bug 878647, sat.gob.mx
"sat.gob.mx": "\\(Mobile#(Android; Mobile",
// bug 878649, univision.com
"univision.com": "\\(Mobile#(Android; Mobile",
// bug 878653, redstarbelgrade.info
"redstarbelgrade.info": "\\(Mobile#(Android; Mobile",
// bug 878655, vesti-online.com
"vesti-online.com": "\\(Mobile#(Android; Mobile"
}

View File

@ -1342,3 +1342,56 @@ let SensorsListener = {
SensorsListener.init();
#endif
// Calling this observer will cause a shutdown an a profile reset.
// Use eg. : Services.obs.notifyObservers(null, 'b2g-reset-profile', null);
Services.obs.addObserver(function resetProfile(subject, topic, data) {
Services.obs.removeObserver(resetProfile, topic);
// Listening for 'profile-before-change2' which is late in the shutdown
// sequence, but still has xpcom access.
Services.obs.addObserver(function clearProfile(subject, topic, data) {
Services.obs.removeObserver(clearProfile, topic);
#ifdef MOZ_WIDGET_GONK
let json = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
json.initWithPath('/system/b2g/webapps/webapps.json');
let toRemove = json.exists()
// This is a user build, just rm -r /data/local /data/b2g/mozilla
? ['/data/local', '/data/b2g/mozilla']
// This is an eng build. We clear the profile and a set of files
// under /data/local.
: ['/data/b2g/mozilla',
'/data/local/permissions.sqlite',
'/data/local/storage',
'/data/local/OfflineCache'];
toRemove.forEach(function(dir) {
try {
let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
file.initWithPath(dir);
file.remove(true);
} catch(e) { dump(e); }
});
#else
// Desktop builds.
let profile = Services.dirsvc.get('ProfD', Ci.nsIFile);
// We don't want to remove everything from the profile, since this
// would prevent us from starting up.
let whitelist = ['defaults', 'extensions', 'settings.json',
'user.js', 'webapps'];
let enumerator = profile.directoryEntries;
while (enumerator.hasMoreElements()) {
let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
if (whitelist.indexOf(file.leafName) == -1) {
file.remove(true);
}
}
#endif
},
'profile-before-change2', false);
let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
.getService(Ci.nsIAppStartup);
appStartup.quit(Ci.nsIAppStartup.eForceQuit);
}, 'b2g-reset-profile', false);

View File

@ -1,4 +1,4 @@
{
"revision": "d9e4d98a9fba0dec670fe2446bea31e464add944",
"revision": "8547bf51868f3521d96129d4e9060cf98a0bd23e",
"repo_path": "/integration/gaia-central"
}

View File

@ -119,6 +119,7 @@
@BINPATH@/mozsqlt3@DLL_SUFFIX@
#endif
@BINPATH@/blocklist.xml
@BINPATH@/ua-update.json
#ifdef XP_UNIX
#ifndef XP_MACOSX
@BINPATH@/run-mozilla.sh

View File

@ -1119,18 +1119,25 @@ var gBrowserInit = {
// If the user manually opens the download manager before the timeout, the
// downloads will start right away, and getting the service again won't hurt.
setTimeout(function() {
let DownloadsCommon =
Cu.import("resource:///modules/DownloadsCommon.jsm", {}).DownloadsCommon;
if (DownloadsCommon.useJSTransfer) {
// Open the data link without initalizing nsIDownloadManager.
DownloadsCommon.initializeAllDataLinks();
} else {
// Initalizing nsIDownloadManager will trigger the data link.
Services.downloads;
try {
let DownloadsCommon =
Cu.import("resource:///modules/DownloadsCommon.jsm", {}).DownloadsCommon;
if (DownloadsCommon.useJSTransfer) {
// Open the data link without initalizing nsIDownloadManager.
DownloadsCommon.initializeAllDataLinks();
let DownloadsTaskbar =
Cu.import("resource:///modules/DownloadsTaskbar.jsm", {}).DownloadsTaskbar;
DownloadsTaskbar.registerIndicator(window);
} else {
// Initalizing nsIDownloadManager will trigger the data link.
Services.downloads;
let DownloadTaskbarProgress =
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
DownloadTaskbarProgress.onBrowserWindowLoad(window);
}
} catch (ex) {
Cu.reportError(ex);
}
let DownloadTaskbarProgress =
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
DownloadTaskbarProgress.onBrowserWindowLoad(window);
}, 10000);
// The object handling the downloads indicator is also initialized here in the

View File

@ -0,0 +1,180 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
/* 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/. */
/**
* Handles the download progress indicator in the taskbar.
*/
"use strict";
this.EXPORTED_SYMBOLS = [
"DownloadsTaskbar",
];
////////////////////////////////////////////////////////////////////////////////
//// Globals
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function () {
if (!("@mozilla.org/windows-taskbar;1" in Cc)) {
return null;
}
let winTaskbar = Cc["@mozilla.org/windows-taskbar;1"]
.getService(Ci.nsIWinTaskbar);
return winTaskbar.available && winTaskbar;
});
XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function () {
return ("@mozilla.org/widget/macdocksupport;1" in Cc) &&
Cc["@mozilla.org/widget/macdocksupport;1"]
.getService(Ci.nsITaskbarProgress);
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadsTaskbar
/**
* Handles the download progress indicator in the taskbar.
*/
this.DownloadsTaskbar = {
/**
* Underlying DownloadSummary providing the aggregate download information, or
* null if the indicator has never been initialized.
*/
_summary: null,
/**
* nsITaskbarProgress object to which download information is dispatched.
* This can be null if the indicator has never been initialized or if the
* indicator is currently hidden on Windows.
*/
_taskbarProgress: null,
/**
* This method is called after a new browser window is opened, and ensures
* that the download progress indicator is displayed in the taskbar.
*
* On Windows, the indicator is attached to the first browser window that
* calls this method. When the window is closed, the indicator is moved to
* another browser window, if available, in no particular order. When there
* are no browser windows visible, the indicator is hidden.
*
* On Mac OS X, the indicator is initialized globally when this method is
* called for the first time. Subsequent calls have no effect.
*
* @param aBrowserWindow
* nsIDOMWindow object of the newly opened browser window to which the
* indicator may be attached.
*/
registerIndicator: function (aBrowserWindow)
{
if (!this._taskbarProgress) {
if (gMacTaskbarProgress) {
// On Mac OS X, we have to register the global indicator only once.
this._taskbarProgress = gMacTaskbarProgress;
// Free the XPCOM reference on shutdown, to prevent detecting a leak.
Services.obs.addObserver(() => {
this._taskbarProgress = null;
gMacTaskbarProgress = null;
}, "quit-application-granted", false);
} else if (gWinTaskbar) {
// On Windows, the indicator is currently hidden because we have no
// previous browser window, thus we should attach the indicator now.
this._attachIndicator(aBrowserWindow);
} else {
// The taskbar indicator is not available on this platform.
return;
}
}
// Ensure that the DownloadSummary object will be created asynchronously.
if (!this._summary) {
Downloads.getSummary(Downloads.ALL).then(summary => {
// In case the method is re-entered, we simply ignore redundant
// invocations of the callback, instead of keeping separate state.
if (this._summary) {
return;
}
this._summary = summary;
return this._summary.addView(this);
}).then(null, Cu.reportError);
}
},
/**
* On Windows, attaches the taskbar indicator to the specified browser window.
*/
_attachIndicator: function (aWindow)
{
// Activate the indicator on the specified window.
let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow).docShell;
this._taskbarProgress = gWinTaskbar.getTaskbarProgress(docShell);
// If the DownloadSummary object has already been created, we should update
// the state of the new indicator, otherwise it will be updated as soon as
// the DownloadSummary view is registered.
if (this._summary) {
this.onSummaryChanged();
}
aWindow.addEventListener("unload", () => {
// Locate another browser window, excluding the one being closed.
let browserWindow = RecentWindow.getMostRecentBrowserWindow();
if (browserWindow) {
// Move the progress indicator to the other browser window.
this._attachIndicator(browserWindow);
} else {
// The last browser window has been closed. We remove the reference to
// the taskbar progress object so that the indicator will be registered
// again on the next browser window that is opened.
this._taskbarProgress = null;
}
}, false);
},
//////////////////////////////////////////////////////////////////////////////
//// DownloadSummary view
onSummaryChanged: function ()
{
// If the last browser window has been closed, we have no indicator anymore.
if (!this._taskbarProgress) {
return;
}
if (this._summary.allHaveStopped || this._summary.progressTotalBytes == 0) {
this._taskbarProgress.setProgressState(
Ci.nsITaskbarProgress.STATE_NO_PROGRESS, 0, 0);
} else {
// For a brief moment before completion, some download components may
// report more transferred bytes than the total number of bytes. Thus,
// ensure that we never break the expectations of the progress indicator.
let progressCurrentBytes = Math.min(this._summary.progressTotalBytes,
this._summary.progressCurrentBytes);
this._taskbarProgress.setProgressState(
Ci.nsITaskbarProgress.STATE_NORMAL,
progressCurrentBytes,
this._summary.progressTotalBytes);
}
},
};

View File

@ -13,5 +13,6 @@ EXTRA_COMPONENTS += [
EXTRA_JS_MODULES += [
'DownloadsCommon.jsm',
'DownloadsLogger.jsm',
'DownloadsTaskbar.jsm',
]

View File

@ -215,34 +215,27 @@
accesskey="&newWindowsAsTabs.accesskey;"
preference="browser.link.open_newwindow"
onsyncfrompreference="return gMainPane.readLinkTarget();"
onsynctopreference="return gMainPane.writeLinkTarget();"
class="indent"/>
onsynctopreference="return gMainPane.writeLinkTarget();"/>
<checkbox id="warnCloseMultiple" label="&warnCloseMultipleTabs.label;"
accesskey="&warnCloseMultipleTabs.accesskey;"
preference="browser.tabs.warnOnClose"
class="indent"/>
preference="browser.tabs.warnOnClose"/>
<checkbox id="warnOpenMany" label="&warnOpenManyTabs.label;"
accesskey="&warnOpenManyTabs.accesskey;"
preference="browser.tabs.warnOnOpen"
class="indent"/>
preference="browser.tabs.warnOnOpen"/>
<checkbox id="restoreOnDemand" label="&restoreTabsOnDemand.label;"
accesskey="&restoreTabsOnDemand.accesskey;"
preference="browser.sessionstore.restore_on_demand"
class="indent"/>
preference="browser.sessionstore.restore_on_demand"/>
<checkbox id="switchToNewTabs" label="&switchToNewTabs.label;"
accesskey="&switchToNewTabs.accesskey;"
preference="browser.tabs.loadInBackground"
class="indent"/>
preference="browser.tabs.loadInBackground"/>
#ifdef XP_WIN
<checkbox id="showTabsInTaskbar" label="&showTabsInTaskbar.label;"
accesskey="&showTabsInTaskbar.accesskey;"
preference="browser.taskbar.previews.enable"
class="indent"/>
preference="browser.taskbar.previews.enable"/>
#endif
</groupbox>

View File

@ -22,6 +22,7 @@ MOCHITEST_BROWSER_FILES = \
browser_dbg_breakpoints-pane.js \
browser_dbg_chrome-debugging.js \
browser_dbg_clean-exit.js \
browser_dbg_clean-exit-window.js \
browser_dbg_cmd-blackbox.js \
browser_dbg_cmd-break.js \
browser_dbg_cmd-dbg.js \

View File

@ -0,0 +1,90 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that closing a window with the debugger in a paused state exits cleanly.
*/
let gDebuggee, gPanel, gDebugger, gWindow;
const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html";
function test() {
addWindow(TAB_URL)
.then(win => initDebugger(TAB_URL, win))
.then(([aTab, aDebuggee, aPanel, aWindow]) => {
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gWindow = aWindow;
return testCleanExit(gWindow);
})
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
}
function testCleanExit(aWindow) {
let deferred = promise.defer();
gWindow = aWindow;
ok(!!gWindow, "Second window created.");
gWindow.focus();
let topWindow = Services.wm.getMostRecentWindow("navigator:browser");
is(topWindow, gWindow,
"The second window is on top.");
let isActive = promise.defer();
let isLoaded = promise.defer();
promise.all([isActive.promise, isLoaded.promise]).then(() => {
gWindow.BrowserChromeTest.runWhenReady(() => {
waitForSourceAndCaretAndScopes(gPanel, ".html", 16).then(() => {
is(gDebugger.gThreadClient.paused, true,
"Should be paused after the debugger statement.");
gWindow.close();
deferred.resolve();
finish();
});
gDebuggee.runDebuggerStatement();
});
});
let focusManager = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
if (focusManager.activeWindow != gWindow) {
gWindow.addEventListener("activate", function onActivate(aEvent) {
if (aEvent.target != gWindow) {
return;
}
gWindow.removeEventListener("activate", onActivate, true);
isActive.resolve();
}, true);
} else {
isActive.resolve();
}
let contentLocation = gWindow.content.location.href;
if (contentLocation != TAB_URL) {
gWindow.document.addEventListener("load", function onLoad(aEvent) {
if (aEvent.target.documentURI != TAB_URL) {
return;
}
gWindow.document.removeEventListener("load", onLoad, true);
isLoaded.resolve();
}, true);
} else {
isLoaded.resolve();
}
return deferred.promise;
}
registerCleanupFunction(function() {
gWindow = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
});

View File

@ -416,18 +416,18 @@ function backspaceText(aElement, aTimes) {
}
}
function getTab(aTarget) {
function getTab(aTarget, aWindow) {
if (aTarget instanceof XULElement) {
return promise.resolve(aTarget);
} else {
return addTab(aTarget);
return addTab(aTarget, aWindow);
}
}
function initDebugger(aTarget, aWindow) {
info("Initializing a debugger panel.");
return getTab(aTarget).then(aTab => {
return getTab(aTarget, aWindow).then(aTab => {
info("Debugee tab added successfully: " + aTarget);
let deferred = promise.defer();
@ -445,7 +445,7 @@ function initDebugger(aTarget, aWindow) {
info("Debugger client resumed successfully.");
prepareDebugger(debuggerPanel);
deferred.resolve([aTab, debuggee, debuggerPanel]);
deferred.resolve([aTab, debuggee, debuggerPanel, aWindow]);
});
});

View File

@ -180,12 +180,6 @@ function ResponsiveUI(aWindow, aTab)
this.buildUI();
this.checkMenus();
this.docShell = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
this.docShell.deviceSizeIsPageSize = true;
try {
if (Services.prefs.getBoolPref("devtools.responsiveUI.rotate")) {
this.rotate();
@ -258,8 +252,6 @@ ResponsiveUI.prototype = {
this.browser.removeEventListener("load", this.bound_onPageLoad, true);
this.browser.removeEventListener("unload", this.bound_onPageUnload, true);
this.docShell.deviceSizeIsPageSize = false;
if (this._floatingScrollbars)
switchToNativeScrollbars(this.tab);
@ -296,7 +288,6 @@ ResponsiveUI.prototype = {
this.container.removeAttribute("responsivemode");
this.stack.removeAttribute("responsivemode");
delete this.docShell;
delete this.tab.__responsiveUI;
if (this.touchEventHandler)
this.touchEventHandler.stop();

View File

@ -9,7 +9,6 @@ MOCHITEST_BROWSER_FILES := \
browser_responsive_cmd.js \
browser_responsivecomputedview.js \
browser_responsiveui_touch.js \
browser_responsive_devicewidth.js \
touch.html \
head.js \
$(NULL)

View File

@ -1,61 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let instance;
let mgr = ResponsiveUI.ResponsiveUIManager;
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html,mop";
function startTest() {
mgr.once("on", function() {executeSoon(onUIOpen)});
document.getElementById("Tools:ResponsiveUI").doCommand();
}
function onUIOpen() {
instance = gBrowser.selectedTab.__responsiveUI;
instance.stack.setAttribute("notransition", "true");
ok(instance, "instance of the module is attached to the tab.");
let mql = content.matchMedia("(max-device-width:100px)")
ok(!mql.matches, "media query doesn't match.");
mql.addListener(onMediaChange);
instance.setSize(90, 500);
}
function onMediaChange(mql) {
mql.removeListener(onMediaChange);
ok(mql.matches, "media query matches.");
ok(window.screen.width != content.screen.width, "screen.width is not the size of the screen.");
is(content.screen.width, 90, "screen.width is the width of the page.");
is(content.screen.height, 500, "screen.height is the height of the page.");
let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
mql.addListener(onMediaChange2);
docShell.deviceSizeIsPageSize = false;
}
function onMediaChange2(mql) {
mql.removeListener(onMediaChange);
ok(!mql.matches, "media query has been re-evaluated.");
ok(window.screen.width == content.screen.width, "screen.width is not the size of the screen.");
instance.stack.removeAttribute("notransition");
document.getElementById("Tools:ResponsiveUI").doCommand();
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -668,16 +668,13 @@ PropertyView.prototype = {
/**
* Returns the className that should be assigned to the propertyView.
*
* @return string
*/
get propertyHeaderClassName()
{
if (this.visible) {
this.tree._darkStripe = !this.tree._darkStripe;
let darkValue = this.tree._darkStripe ?
"property-view theme-bg-darker" : "property-view";
return darkValue;
let isDark = this.tree._darkStripe = !this.tree._darkStripe;
return isDark ? "property-view theme-bg-darker" : "property-view";
}
return "property-view-hidden";
},
@ -690,49 +687,66 @@ PropertyView.prototype = {
get propertyContentClassName()
{
if (this.visible) {
let darkValue = this.tree._darkStripe ?
"property-content theme-bg-darker" : "property-content";
return darkValue;
let isDark = this.tree._darkStripe;
return isDark ? "property-content theme-bg-darker" : "property-content";
}
return "property-content-hidden";
},
/**
* Build the markup for on computed style
* @return Element
*/
buildMain: function PropertyView_buildMain()
{
let doc = this.tree.styleDocument;
let onToggle = this.onStyleToggle.bind(this);
// Build the container element
this.element = doc.createElementNS(HTML_NS, "div");
this.element.setAttribute("class", this.propertyHeaderClassName);
this.matchedExpander = doc.createElementNS(HTML_NS, "div");
this.matchedExpander.className = "expander theme-twisty";
this.matchedExpander.setAttribute("tabindex", "0");
this.matchedExpander.addEventListener("click",
this.matchedExpanderClick.bind(this), false);
this.matchedExpander.addEventListener("keydown", function(aEvent) {
// Make it keyboard navigable
this.element.setAttribute("tabindex", "0");
this.element.addEventListener("keydown", function(aEvent) {
let keyEvent = Ci.nsIDOMKeyEvent;
if (aEvent.keyCode == keyEvent.DOM_VK_F1) {
this.mdnLinkClick();
}
if (aEvent.keyCode == keyEvent.DOM_VK_RETURN ||
aEvent.keyCode == keyEvent.DOM_VK_SPACE) {
this.matchedExpanderClick(aEvent);
onToggle(aEvent);
}
}.bind(this), false);
// Build the twisty expand/collapse
this.matchedExpander = doc.createElementNS(HTML_NS, "div");
this.matchedExpander.className = "expander theme-twisty";
this.matchedExpander.addEventListener("click", onToggle, false);
this.element.appendChild(this.matchedExpander);
// Build the style name element
this.nameNode = doc.createElementNS(HTML_NS, "div");
this.element.appendChild(this.nameNode);
this.nameNode.setAttribute("class", "property-name theme-fg-color5");
// Reset its tabindex attribute otherwise, if an ellipsis is applied
// it will be reachable via TABing
this.nameNode.setAttribute("tabindex", "");
this.nameNode.textContent = this.nameNode.title = this.name;
this.nameNode.addEventListener("click", function(aEvent) {
this.matchedExpander.focus();
}.bind(this), false);
// Make it hand over the focus to the container
this.nameNode.addEventListener("click", () => this.element.focus(), false);
this.element.appendChild(this.nameNode);
// Build the style value element
this.valueNode = doc.createElementNS(HTML_NS, "div");
this.element.appendChild(this.valueNode);
this.valueNode.setAttribute("class", "property-value theme-fg-color1");
// Reset its tabindex attribute otherwise, if an ellipsis is applied
// it will be reachable via TABing
this.valueNode.setAttribute("tabindex", "");
this.valueNode.setAttribute("dir", "ltr");
this.valueNode.textContent = this.valueNode.title = this.value;
// Make it hand over the focus to the container
this.valueNode.addEventListener("click", () => this.element.focus(), false);
this.element.appendChild(this.valueNode);
return this.element;
},
@ -836,7 +850,7 @@ PropertyView.prototype = {
* @param {Event} aEvent Used to determine the class name of the targets click
* event.
*/
matchedExpanderClick: function PropertyView_matchedExpanderClick(aEvent)
onStyleToggle: function PropertyView_onStyleToggle(aEvent)
{
this.matchedExpanded = !this.matchedExpanded;
this.refreshMatchedSelectors();

View File

@ -36,6 +36,7 @@ MOCHITEST_BROWSER_FILES = \
browser_bug894376_css_value_completion_existing_property_value_pair.js \
browser_ruleview_bug_902966_revert_value_on_ESC.js \
browser_ruleview_pseudoelement.js \
browser_computedview_bug835808_keyboard_nav.js \
head.js \
$(NULL)

View File

@ -0,0 +1,94 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the style inspector works properly
let doc, computedView, inspector;
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onBrowserLoad(evt) {
gBrowser.selectedBrowser.removeEventListener("load", onBrowserLoad, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html,computed view context menu test";
}
function createDocument()
{
doc.body.innerHTML = '<style type="text/css"> ' +
'span { font-variant: small-caps; color: #000000; } ' +
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
'<h1>Some header text</h1>\n' +
'<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
'<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
'solely to provide some things to <span style="color: yellow">' +
'highlight</span> and <span style="font-weight: bold">count</span> ' +
'style list-items in the box at right. If you are reading this, ' +
'you should go do something else instead. Maybe read a book. Or better ' +
'yet, write some test-cases for another bit of code. ' +
'<span style="font-style: italic">some text</span></p>\n' +
'<p id="closing">more text</p>\n' +
'<p>even more text</p>' +
'</div>';
doc.title = "Computed view keyboard navigation test";
openComputedView(startTests);
}
function startTests(aInspector, aComputedView)
{
computedView = aComputedView;
inspector = aInspector;
testTabThrougStyles();
}
function endTests()
{
computedView = inspector = doc = null;
gBrowser.removeCurrentTab();
finish();
}
function testTabThrougStyles()
{
let span = doc.querySelector("span");
inspector.once("computed-view-refreshed", () => {
// Selecting the first computed style in the list
let firstStyle = computedView.styleDocument.querySelector(".property-view");
ok(firstStyle, "First computed style found in panel");
firstStyle.focus();
// Tab to select the 2nd style, press return
EventUtils.synthesizeKey("VK_TAB", {});
EventUtils.synthesizeKey("VK_RETURN", {});
inspector.once("computed-view-property-expanded", () => {
// Verify the 2nd style has been expanded
let secondStyleSelectors = computedView.styleDocument.querySelectorAll(
".property-content .matchedselectors")[1];
ok(secondStyleSelectors.childNodes.length > 0, "Matched selectors expanded");
// Tab back up and test the same thing, with space
EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
EventUtils.synthesizeKey("VK_SPACE", {});
inspector.once("computed-view-property-expanded", () => {
// Verify the 1st style has been expanded too
let firstStyleSelectors = computedView.styleDocument.querySelectorAll(
".property-content .matchedselectors")[0];
ok(firstStyleSelectors.childNodes.length > 0, "Matched selectors expanded");
endTests();
});
});
});
inspector.selection.setNode(span);
}

View File

@ -45,6 +45,7 @@ body {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
outline: 0;
}
.property-value {
@ -58,6 +59,7 @@ body {
background-size: 5px 8px;
background-position: 2px center;
padding-left: 10px;
outline: 0;
}
.other-property-value {

View File

@ -63,6 +63,7 @@ body {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
outline: 0;
}
.property-value {
@ -76,6 +77,7 @@ body {
background-size: 5px 8px;
background-position: 2px center;
padding-left: 10px;
outline: 0;
}
.other-property-value {

View File

@ -63,6 +63,7 @@ body {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
outline: 0;
}
.property-value {
@ -76,6 +77,7 @@ body {
background-size: 5px 8px;
background-position: 2px center;
padding-left: 10px;
outline: 0;
}
.other-property-value {

View File

@ -750,7 +750,6 @@ nsDocShell::nsDocShell():
mIsAppTab(false),
mUseGlobalHistory(false),
mInPrivateBrowsing(false),
mDeviceSizeIsPageSize(false),
mFiredUnloadEvent(false),
mEODForCurrentDocument(false),
mURIResultedInDocument(false),
@ -3933,27 +3932,6 @@ nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
{
if (mDeviceSizeIsPageSize != aValue) {
mDeviceSizeIsPageSize = aValue;
nsRefPtr<nsPresContext> presContext;
GetPresContext(getter_AddRefs(presContext));
if (presContext) {
presContext->MediaFeatureValuesChanged(presContext->eAlwaysRebuildStyle);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetDeviceSizeIsPageSize(bool* aValue)
{
*aValue = mDeviceSizeIsPageSize;
return NS_OK;
}
void
nsDocShell::ClearFrameHistory(nsISHEntry* aEntry)
{

View File

@ -809,7 +809,6 @@ protected:
bool mIsAppTab;
bool mUseGlobalHistory;
bool mInPrivateBrowsing;
bool mDeviceSizeIsPageSize;
// This boolean is set to true right before we fire pagehide and generally
// unset when we embed a new content viewer. While it's true no navigation

View File

@ -916,12 +916,4 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
boolean isCommandEnabled(in string command);
void doCommand(in string command);
/**
* If deviceSizeIsPageSize is set to true, device-width/height media queries
* will be calculated from the page size, not the device size.
*
* Used by the Responsive Design View.
*/
[infallible] attribute boolean deviceSizeIsPageSize;
};

View File

@ -1508,6 +1508,23 @@ nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aSc
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ScrollToCSSPixelsApproximate(float aX, float aY, bool* aRetVal)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
nsIScrollableFrame* sf = static_cast<nsGlobalWindow*>(window.get())->GetScrollFrame();
if (sf) {
sf->ScrollToCSSPixelsApproximate(CSSPoint(aX, aY));
}
if (aRetVal) {
*aRetVal = (sf != nullptr);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetScrollbarSize(bool aFlushLayout, int32_t* aWidth,
int32_t* aHeight)

View File

@ -385,19 +385,6 @@ nsScreen::SlowMozUnlockOrientation()
return NS_OK;
}
bool
nsScreen::IsDeviceSizePageSize()
{
nsPIDOMWindow* owner = GetOwner();
if (owner) {
nsIDocShell* docShell = owner->GetDocShell();
if (docShell) {
return docShell->GetDeviceSizeIsPageSize();
}
}
return false;
}
/* virtual */
JSObject*
nsScreen::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)

View File

@ -51,15 +51,6 @@ public:
int32_t GetWidth(ErrorResult& aRv)
{
nsRect rect;
if (IsDeviceSizePageSize()) {
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (owner) {
int32_t innerWidth = 0;
aRv = owner->GetInnerWidth(&innerWidth);
return innerWidth;
}
}
aRv = GetRect(rect);
return rect.width;
}
@ -67,15 +58,6 @@ public:
int32_t GetHeight(ErrorResult& aRv)
{
nsRect rect;
if (IsDeviceSizePageSize()) {
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (owner) {
int32_t innerHeight = 0;
aRv = owner->GetInnerHeight(&innerHeight);
return innerHeight;
}
}
aRv = GetRect(rect);
return rect.height;
}
@ -155,8 +137,6 @@ private:
LockPermission GetLockOrientationPermission() const;
bool IsDeviceSizePageSize();
nsRefPtr<FullScreenEventListener> mEventListener;
};

View File

@ -43,7 +43,7 @@ interface nsIDOMEventTarget;
interface nsIRunnable;
interface nsICompositionStringSynthesizer;
[scriptable, uuid(dd45c6ae-9d80-46ef-86d7-f2795a48a77b)]
[scriptable, uuid(a1383ae5-e828-4c9a-929d-5293e61beb64)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -652,6 +652,13 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void getScrollXY(in boolean aFlushLayout, out long aScrollX, out long aScrollY);
/**
* Sets the scroll position of the root scroll frame of the window.
* Returns true on success, false on error (if the window didn't have a root
* scroll frame).
*/
boolean scrollToCSSPixelsApproximate(in float aX, in float aY);
/**
* Returns the scrollbar width of the window's scroll frame.
*

View File

@ -1930,13 +1930,11 @@ ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
// If the blob represents a remote blob for this ContentParent then we can
// simply pass its actor back here.
if (nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(aBlob)) {
BlobParent* actor =
static_cast<BlobParent*>(
static_cast<PBlobParent*>(remoteBlob->GetPBlob()));
MOZ_ASSERT(actor);
if (static_cast<ContentParent*>(actor->Manager()) == this) {
return actor;
if (BlobParent* actor = static_cast<BlobParent*>(
static_cast<PBlobParent*>(remoteBlob->GetPBlob()))) {
if (static_cast<ContentParent*>(actor->Manager()) == this) {
return actor;
}
}
}

View File

@ -87,6 +87,7 @@
#include "xpcpublic.h"
#include "nsViewportInfo.h"
#include "JavaScriptChild.h"
#include "APZCCallbackHelper.h"
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -302,29 +303,6 @@ TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t
{
}
// Get the DOMWindowUtils for the window corresponding to the given document.
static already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils(nsIDocument* doc)
{
nsCOMPtr<nsIDOMWindowUtils> utils;
nsCOMPtr<nsIDOMWindow> window = doc->GetDefaultView();
if (window) {
utils = do_GetInterface(window);
}
return utils.forget();
}
// Get the DOMWindowUtils for the window corresponding to the givent content
// element. This might be an iframe inside the tab, for instance.
static already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils(nsIContent* content)
{
nsCOMPtr<nsIDOMWindowUtils> utils;
nsIDocument* doc = content->GetCurrentDoc();
if (doc) {
utils = GetDOMWindowUtils(doc);
}
return utils.forget();
}
NS_IMETHODIMP
TabChild::HandleEvent(nsIDOMEvent* aEvent)
{
@ -348,7 +326,7 @@ TabChild::HandleEvent(nsIDOMEvent* aEvent)
else
content = do_QueryInterface(target);
nsCOMPtr<nsIDOMWindowUtils> utils = ::GetDOMWindowUtils(content);
nsCOMPtr<nsIDOMWindowUtils> utils = APZCCallbackHelper::GetDOMWindowUtils(content);
utils->GetPresShellId(&presShellId);
if (!nsLayoutUtils::FindIDFor(content, &viewId))
@ -1542,12 +1520,8 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
MOZ_ASSERT(aFrameMetrics.mScrollId != FrameMetrics::NULL_SCROLL_ID);
if (aFrameMetrics.mScrollId == FrameMetrics::ROOT_SCROLL_ID) {
uint32_t presShellId;
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
nsresult rv = utils->GetPresShellId(&presShellId);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_SUCCEEDED(rv) && aFrameMetrics.mPresShellId == presShellId) {
if (APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) {
return ProcessUpdateFrame(aFrameMetrics);
}
} else {
@ -1556,7 +1530,8 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(
aFrameMetrics.mScrollId);
if (content) {
return ProcessUpdateSubframe(content, aFrameMetrics);
APZCCallbackHelper::UpdateSubFrame(content, aFrameMetrics);
return true;
}
}
@ -1610,38 +1585,8 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mWebNav);
// set the scroll port size, which determines the scroll range
utils->SetScrollPositionClampingScrollPortSize(
cssCompositedRect.width, cssCompositedRect.height);
// scroll the window to the desired spot
nsIScrollableFrame* sf = static_cast<nsGlobalWindow*>(window.get())->GetScrollFrame();
if (sf) {
sf->ScrollToCSSPixelsApproximate(aFrameMetrics.mScrollOffset);
}
// set the resolution
ParentLayerToLayerScale resolution = aFrameMetrics.mZoom
/ aFrameMetrics.mDevPixelsPerCSSPixel
/ aFrameMetrics.GetParentResolution()
* ScreenToLayerScale(1);
utils->SetResolution(resolution.scale, resolution.scale);
// and set the display port
nsCOMPtr<nsIDOMDocument> domDoc;
mWebNav->GetDocument(getter_AddRefs(domDoc));
if (domDoc) {
nsCOMPtr<nsIDOMElement> element;
domDoc->GetDocumentElement(getter_AddRefs(element));
if (element) {
utils->SetDisplayPortForElement(
aFrameMetrics.mDisplayPort.x, aFrameMetrics.mDisplayPort.y,
aFrameMetrics.mDisplayPort.width, aFrameMetrics.mDisplayPort.height,
element);
}
}
APZCCallbackHelper::UpdateRootFrame(utils, aFrameMetrics);
mLastMetrics = aFrameMetrics;
@ -1656,29 +1601,6 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
return true;
}
bool
TabChild::ProcessUpdateSubframe(nsIContent* aContent,
const FrameMetrics& aMetrics)
{
// scroll the frame to the desired spot
nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(aMetrics.mScrollId);
if (scrollFrame) {
scrollFrame->ScrollToCSSPixelsApproximate(aMetrics.mScrollOffset);
}
nsCOMPtr<nsIDOMWindowUtils> utils(::GetDOMWindowUtils(aContent));
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
if (utils && element) {
// and set the display port
utils->SetDisplayPortForElement(
aMetrics.mDisplayPort.x, aMetrics.mDisplayPort.y,
aMetrics.mDisplayPort.width, aMetrics.mDisplayPort.height,
element);
}
return true;
}
bool
TabChild::RecvHandleDoubleTap(const CSSIntPoint& aPoint)
{

View File

@ -415,7 +415,6 @@ private:
void DestroyWindow();
void SetProcessNameToAppName();
bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
bool ProcessUpdateSubframe(nsIContent* aContent, const FrameMetrics& aMetrics);
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow();

View File

@ -27,7 +27,7 @@ interface nsISocketTransport;
// Once bug 723206 will be fixed, this method could be replaced by
// arguments when instantiating a TCPSocket object. For example it will
// be possible to do (similarly to the WebSocket API):
// var s = new MozTCPSocket(host, port);
// var s = new MozTCPSocket(host, port);
// Bug 797561 - Expose a server tcp socket API to web applications
@ -215,7 +215,7 @@ interface nsIDOMTCPSocket : nsISupports
* Needed to account for multiple possible types that can be provided to
* the socket callbacks as arguments.
*/
[scriptable, uuid(0baa1be1-6a88-4f85-a6c8-29e95f35c122)]
[scriptable, uuid(234c664c-3d6c-4859-b45c-4e9a98cb5bdc)]
interface nsITCPSocketInternal : nsISupports {
// Trigger the callback for |type| and provide a DOMError() object with the given data
void callListenerError(in DOMString type, in DOMString name);
@ -245,17 +245,20 @@ interface nsITCPSocketInternal : nsISupports {
// Create a DOM socket on the child side
// This is called when the socket is accepted on the parent side.
//
//
// @param socketChild
// The socket child object for the IPC implementation.
// @param binaryType
// "arraybuffer" to use ArrayBuffer instances
// "arraybuffer" to use ArrayBuffer instances
// in the ondata callback and as the argument to send.
// @param window
// An object to create ArrayBuffer for this window. See Bug 831107.
nsIDOMTCPSocket createAcceptedChild(in nsITCPSocketChild socketChild,
in DOMString binaryType,
in DOMString binaryType,
in nsIDOMWindow window);
// Set App ID.
void setAppId(in unsigned long appId);
};
/**

View File

@ -38,12 +38,13 @@ interface nsITCPSocketParent : nsISupports
// Intermediate class to handle sending multiple possible data types
// and kicking off the chrome process socket object's connection.
[scriptable, uuid(38bec1ed-b863-40dd-ba69-7bd92e568ee3)]
[scriptable, uuid(be67b1b8-03b0-4171-a791-d004458021b6)]
interface nsITCPSocketIntermediary : nsISupports {
// Open the connection to the server with the given parameters
nsIDOMTCPSocket open(in nsITCPSocketParent parent,
in DOMString host, in unsigned short port,
in boolean useSSL, in DOMString binaryType);
in boolean useSSL, in DOMString binaryType,
in unsigned long appId);
// Listen on a port
nsIDOMTCPServerSocket listen(in nsITCPServerSocketParent parent,

View File

@ -22,6 +22,7 @@ const TOPIC_INTERFACE_REGISTERED = "network-interface-registered";
const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
const NET_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
const NET_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
const NET_TYPE_UNKNOWN = Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN;
// The maximum traffic amount can be saved in the |cachedAppStats|.
const MAX_CACHED_TRAFFIC = 500 * 1000 * 1000; // 500 MB
@ -424,8 +425,8 @@ this.NetworkStatsService = {
aTimeStamp + " " + aRxBytes + " " + aTxBytes);
}
// |aAppId| can not be 0 or null in this case.
if (!aAppId) {
// Check if |aAppId| and |aConnectionType| are valid.
if (!aAppId || aConnectionType == NET_TYPE_UNKNOWN) {
return;
}

View File

@ -37,6 +37,7 @@ const kCLOSED = 'closed';
const kRESUME_ERROR = 'Calling resume() on a connection that was not suspended.';
const BUFFER_SIZE = 65536;
const NETWORK_STATS_THRESHOLD = 65536;
// XXX we have no TCPError implementation right now because it's really hard to
// do on b2g18. On mozilla-central we want a proper TCPError that ideally
@ -161,6 +162,14 @@ TCPSocket.prototype = {
_waitingForStartTLS: false,
_pendingDataAfterStartTLS: [],
#ifdef MOZ_WIDGET_GONK
// Network statistics (Gonk-specific feature)
_txBytes: 0,
_rxBytes: 0,
_appId: Ci.nsIScriptSecurityManager.NO_APP_ID,
_connectionType: Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN,
#endif
// Public accessors.
get readyState() {
return this._readyState;
@ -315,6 +324,38 @@ TCPSocket.prototype = {
BUFFER_SIZE, /* close source*/ false, /* close sink */ false);
},
#ifdef MOZ_WIDGET_GONK
// Helper method for collecting network statistics.
// Note this method is Gonk-specific.
_saveNetworkStats: function ts_saveNetworkStats(enforce) {
if (this._txBytes <= 0 && this._rxBytes <= 0) {
// There is no traffic at all. No need to save statistics.
return;
}
// If "enforce" is false, the traffic amount is saved to NetworkStatsServiceProxy
// only when the total amount exceeds the predefined threshold value.
// The purpose is to avoid too much overhead for collecting statistics.
let totalBytes = this._txBytes + this._rxBytes;
if (!enforce && totalBytes < NETWORK_STATS_THRESHOLD) {
return;
}
let nssProxy = Cc["@mozilla.org/networkstatsServiceProxy;1"]
.getService(Ci.nsINetworkStatsServiceProxy);
if (!nssProxy) {
LOG("Error: Ci.nsINetworkStatsServiceProxy service is not available.");
return;
}
nssProxy.saveAppStats(this._appId, this._connectionType, Date.now(),
this._rxBytes, this._txBytes);
// Reset the counters once the statistics is saved to NetworkStatsServiceProxy.
this._txBytes = this._rxBytes = 0;
},
// End of helper method for network statistics.
#endif
callListener: function ts_callListener(type, data) {
if (!this["on" + type])
return;
@ -371,6 +412,14 @@ TCPSocket.prototype = {
return that;
},
setAppId: function ts_setAppId(appId) {
#ifdef MOZ_WIDGET_GONK
this._appId = appId;
#else
// Do nothing because _appId only exists on Gonk-specific platform.
#endif
},
/* end nsITCPSocketInternal methods */
initWindowless: function ts_initWindowless() {
@ -479,6 +528,17 @@ TCPSocket.prototype = {
let transport = that._transport = this._createTransport(host, port, that._ssl);
transport.setEventSink(that, Services.tm.currentThread);
that._initStream(that._binaryType);
#ifdef MOZ_WIDGET_GONK
// Set _connectionType, which is only required for network statistics.
// Note that nsINetworkManager, as well as nsINetworkStatsServiceProxy, is
// Gonk-specific.
let networkManager = Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
if (networkManager && networkManager.active) {
that._connectionType = networkManager.active.type;
}
#endif
return that;
},
@ -589,6 +649,13 @@ TCPSocket.prototype = {
}
this._ensureCopying();
#ifdef MOZ_WIDGET_GONK
// Collect transmitted amount for network statistics.
this._txBytes += length;
this._saveNetworkStats(false);
#endif
return bufferNotFull;
},
@ -621,6 +688,12 @@ TCPSocket.prototype = {
},
_maybeReportErrorAndCloseIfOpen: function(status) {
#ifdef MOZ_WIDGET_GONK
// Save network statistics once the connection is closed.
// For now this function is Gonk-specific.
this._saveNetworkStats(true);
#endif
// If we're closed, we've already reported the error or just don't need to
// report the error.
if (this._readyState === kCLOSED)
@ -813,6 +886,12 @@ TCPSocket.prototype = {
} else {
this.callListener("data", this._inputStreamScriptable.read(count));
}
#ifdef MOZ_WIDGET_GONK
// Collect received amount for network statistics.
this._rxBytes += count;
this._saveNetworkStats(false);
#endif
},
classID: Components.ID("{cda91b22-6472-11e1-aa11-834fec09cd0a}"),

View File

@ -12,6 +12,8 @@
#include "mozilla/AppProcessChecker.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/PNeckoParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
namespace IPC {
@ -91,6 +93,15 @@ TCPSocketParent::RecvOpen(const nsString& aHost, const uint16_t& aPort, const bo
return true;
}
// Obtain App ID
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
const PContentParent *content = Manager()->Manager();
const InfallibleTArray<PBrowserParent*>& browsers = content->ManagedPBrowserParent();
if (browsers.Length() > 0) {
TabParent *tab = static_cast<TabParent*>(browsers[0]);
appId = tab->OwnAppId();
}
nsresult rv;
mIntermediary = do_CreateInstance("@mozilla.org/tcp-socket-intermediary;1", &rv);
if (NS_FAILED(rv)) {
@ -98,7 +109,8 @@ TCPSocketParent::RecvOpen(const nsString& aHost, const uint16_t& aPort, const bo
return true;
}
rv = mIntermediary->Open(this, aHost, aPort, aUseSSL, aBinaryType, getter_AddRefs(mSocket));
rv = mIntermediary->Open(this, aHost, aPort, aUseSSL, aBinaryType, appId,
getter_AddRefs(mSocket));
if (NS_FAILED(rv) || !mSocket) {
FireInteralError(this, __LINE__);
return true;

View File

@ -30,12 +30,17 @@ TCPSocketParentIntermediary.prototype = {
);
},
open: function(aParentSide, aHost, aPort, aUseSSL, aBinaryType) {
open: function(aParentSide, aHost, aPort, aUseSSL, aBinaryType, aAppId) {
let baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket);
let socket = baseSocket.open(aHost, aPort, {useSecureTransport: aUseSSL, binaryType: aBinaryType});
if (!socket)
return null;
let socketInternal = socket.QueryInterface(Ci.nsITCPSocketInternal);
if (socketInternal) {
socketInternal.setAppId(aAppId);
}
// Handlers are set to the JS-implemented socket object on the parent side.
this._setCallbacks(aParentSide, socket);
return socket;

View File

@ -32,11 +32,14 @@ if CONFIG['MOZ_B2G_RIL']:
EXTRA_COMPONENTS += [
'TCPServerSocket.js',
'TCPSocket.js',
'TCPSocket.manifest',
'TCPSocketParentIntermediary.js',
]
EXTRA_PP_COMPONENTS += [
'TCPSocket.js',
]
if CONFIG['MOZ_B2G_RIL']:
EXTRA_COMPONENTS += [
'NetworkStatsManager.js',

View File

@ -226,6 +226,49 @@ tasks.push(function testEnableData() {
setSetting(DATA_KEY, true);
});
tasks.push(function testUnregisterDataWhileDataEnabled() {
log("Set data registration unregistered while data enabled.");
// When data registration is unregistered, all data calls
// will be automatically deactivated.
sendCmdToEmulator("gsm data unregistered", function() {
connection.addEventListener("datachange", function ondatachange() {
log("mobileConnection.data.state is now '"
+ connection.data.state + "'.");
if (connection.data.state == "notSearching") {
connection.removeEventListener("datachange", ondatachange);
log("mobileConnection.data.connected is now '"
+ connection.data.connected + "'.");
is(connection.data.connected, false, "data.connected");
tasks.next();
}
});
});
});
tasks.push(function testRegisterDataWhileDataEnabled() {
log("Set data registration home while data enabled.");
// When data registration is registered, data call will be
// (re)activated by gecko if ril.data.enabled is set to true.
sendCmdToEmulator("gsm data home", function() {
connection.addEventListener("datachange", function ondatachange() {
connection.removeEventListener("datachange", ondatachange);
log("mobileConnection.data.state is now '"
+ connection.data.state + "'.");
is(connection.data.state, "registered", "data.state");
connection.addEventListener("datachange", function ondatachange() {
connection.removeEventListener("datachange", ondatachange);
log("mobileConnection.data.connected is now '"
+ connection.data.connected + "'.");
is(connection.data.connected, true, "data.connected");
tasks.next();
});
});
});
});
tasks.push(function testDisableDataRoamingWhileRoaming() {
log("Disable data roaming while roaming.");

View File

@ -233,6 +233,7 @@ NetworkManager.prototype = {
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
this.removeHostRoutes(network.name);
this.addHostRoute(network);
}
// Add extra host route. For example, mms proxy or mmsc.
@ -640,6 +641,15 @@ NetworkManager.prototype = {
this.worker.postMessage(options);
},
removeHostRoutes: function removeHostRoutes(ifname) {
debug("Going to remove all host routes on " + ifname);
let options = {
cmd: "removeHostRoutes",
ifname: ifname,
};
this.worker.postMessage(options);
},
resolveHostname: function resolveHostname(hosts) {
let retval = [];

View File

@ -3242,7 +3242,30 @@ RILNetworkInterface.prototype = {
if (this.cid == null) {
return;
}
if (this.state == datacall.state) {
if (datacall.state != GECKO_NETWORK_STATE_CONNECTED) {
return;
}
// State remains connected, check for minor changes.
let changed = false;
if (this.gateway != datacall.gw) {
this.gateway = datacall.gw;
changed = true;
}
if (datacall.dns &&
(this.dns1 != datacall.dns[0] ||
this.dns2 != datacall.dns[1])) {
this.dns1 = datacall.dns[0];
this.dns2 = datacall.dns[1];
changed = true;
}
if (changed) {
if (DEBUG) this.debug("Notify for data call minor changes.");
Services.obs.notifyObservers(this,
kNetworkInterfaceStateChangedTopic,
null);
}
return;
}

View File

@ -275,6 +275,13 @@ function removeHostRoute(options) {
}
}
/**
* Remove the routes associated with the named interface.
*/
function removeHostRoutes(options) {
libnetutils.ifc_remove_host_routes(options.ifname);
}
function removeNetworkRoute(options) {
let ipvalue = netHelpers.stringToIP(options.ip);
let netmaskvalue = netHelpers.stringToIP(options.netmask);

View File

@ -7,7 +7,7 @@
/**
* Information about networks that is exposed to network manager API consumers.
*/
[scriptable, uuid(04fe5049-1ea8-4b4f-8c27-d23cd24611bb)]
[scriptable, uuid(f4cf9d88-f962-4d29-9baa-fb295dad387b)]
interface nsINetworkInterface : nsISupports
{
const long NETWORK_STATE_UNKNOWN = -1;
@ -24,6 +24,7 @@ interface nsINetworkInterface : nsISupports
*/
readonly attribute long state;
const long NETWORK_TYPE_UNKNOWN = -1;
const long NETWORK_TYPE_WIFI = 0;
const long NETWORK_TYPE_MOBILE = 1;
const long NETWORK_TYPE_MOBILE_MMS = 2;

View File

@ -450,6 +450,7 @@ this.NETWORK_CREG_TECH_LTE = 14;
this.NETWORK_CREG_TECH_HSPAP = 15;
this.NETWORK_CREG_TECH_GSM = 16;
this.CALL_STATE_UNKNOWN = -1;
this.CALL_STATE_ACTIVE = 0;
this.CALL_STATE_HOLDING = 1;
this.CALL_STATE_DIALING = 2;

View File

@ -3629,12 +3629,12 @@ let RIL = {
delete this.currentConference.cache;
// Update the conference call's state.
let state = null;
let state = CALL_STATE_UNKNOWN;
for each (let call in this.currentConference.participants) {
if (state && state != call.state) {
if (state != CALL_STATE_UNKNOWN && state != call.state) {
// Each participant should have the same state, otherwise something
// wrong happens.
state = null;
state = CALL_STATE_UNKNOWN;
break;
}
state = call.state;
@ -3677,6 +3677,27 @@ let RIL = {
this.sendChromeMessage(message);
},
_compareDataCallLink: function _compareDataCallLink(source, target) {
if (source.ifname != target.ifname ||
source.ipaddr != target.ipaddr ||
source.gw != target.gw) {
return false;
}
// Compare <datacall>.dns.
let sdns = source.dns, tdns = target.dns;
if (sdns.length != tdns.length) {
return false;
}
for (let i = 0; i < sdns.length; i++) {
if (sdns[i] != tdns[i]) {
return false;
}
}
return true;
},
_processDataCallList: function _processDataCallList(datacalls, newDataCallOptions) {
// Check for possible PDP errors: We check earlier because the datacall
// can be removed if is the same as the current one.
@ -3700,6 +3721,7 @@ let RIL = {
// If datacalls list is coming from REQUEST_SETUP_DATA_CALL response,
// we do not change state for any currentDataCalls not in datacalls list.
if (!newDataCallOptions) {
delete this.currentDataCalls[currentDataCall.cid];
currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
currentDataCall.rilMessageType = "datacallstatechange";
this.sendChromeMessage(currentDataCall);
@ -3717,31 +3739,60 @@ let RIL = {
this._setDataCallGeckoState(updatedDataCall);
if (updatedDataCall.state != currentDataCall.state) {
if (updatedDataCall.state == GECKO_NETWORK_STATE_DISCONNECTED) {
delete this.currentDataCalls[currentDataCall.cid];
}
currentDataCall.status = updatedDataCall.status;
currentDataCall.active = updatedDataCall.active;
currentDataCall.state = updatedDataCall.state;
currentDataCall.rilMessageType = "datacallstatechange";
this.sendChromeMessage(currentDataCall);
continue;
}
// State not changed, now check links.
if (this._compareDataCallLink(updatedDataCall, currentDataCall)) {
if(DEBUG) debug("No changes in data call.");
continue;
}
if ((updatedDataCall.ifname != currentDataCall.ifname) ||
(updatedDataCall.ipaddr != currentDataCall.ipaddr)) {
if(DEBUG) debug("Data link changed, cleanup.");
this.deactivateDataCall(currentDataCall);
continue;
}
// Minor change, just update and notify.
if(DEBUG) debug("Data link minor change, just update and notify.");
currentDataCall.gw = updatedDataCall.gw;
if (updatedDataCall.dns) {
currentDataCall.dns[0] = updatedDataCall.dns[0];
currentDataCall.dns[1] = updatedDataCall.dns[1];
}
currentDataCall.rilMessageType = "datacallstatechange";
this.sendChromeMessage(currentDataCall);
}
for each (let newDataCall in datacalls) {
if (!newDataCall.ifname) {
continue;
}
if (!newDataCallOptions) {
if (DEBUG) debug("Unexpected new data call: " + JSON.stringify(newDataCall));
continue;
}
this.currentDataCalls[newDataCall.cid] = newDataCall;
this._setDataCallGeckoState(newDataCall);
if (newDataCallOptions) {
newDataCall.radioTech = newDataCallOptions.radioTech;
newDataCall.apn = newDataCallOptions.apn;
newDataCall.user = newDataCallOptions.user;
newDataCall.passwd = newDataCallOptions.passwd;
newDataCall.chappap = newDataCallOptions.chappap;
newDataCall.pdptype = newDataCallOptions.pdptype;
newDataCallOptions = null;
} else if (DEBUG) {
debug("Unexpected new data call: " + JSON.stringify(newDataCall));
}
newDataCall.radioTech = newDataCallOptions.radioTech;
newDataCall.apn = newDataCallOptions.apn;
newDataCall.user = newDataCallOptions.user;
newDataCall.passwd = newDataCallOptions.passwd;
newDataCall.chappap = newDataCallOptions.chappap;
newDataCall.pdptype = newDataCallOptions.pdptype;
newDataCallOptions = null;
newDataCall.rilMessageType = "datacallstatechange";
this.sendChromeMessage(newDataCall);
}

View File

@ -216,6 +216,8 @@ TelephonyProvider.prototype = {
_convertRILCallState: function _convertRILCallState(aState) {
switch (aState) {
case RIL.CALL_STATE_UNKNOWN:
return nsITelephonyProvider.CALL_STATE_UNKNOWN;
case RIL.CALL_STATE_ACTIVE:
return nsITelephonyProvider.CALL_STATE_CONNECTED;
case RIL.CALL_STATE_HOLDING:
@ -492,8 +494,7 @@ TelephonyProvider.prototype = {
notifyConferenceCallStateChanged: function notifyConferenceCallStateChanged(aState) {
if (DEBUG) debug("handleConferenceCallStateChanged: " + aState);
aState = aState != null ? this._convertRILCallState(aState) :
nsITelephonyProvider.CALL_STATE_UNKNOWN;
aState = this._convertRILCallState(aState);
this._updateCallAudioState(null, aState);
this._notifyAllListeners("conferenceCallStateChanged", [aState]);

View File

@ -10,7 +10,7 @@
"@mozilla.org/telephony/gonktelephonyprovider;1"
%}
[scriptable, uuid(0d106c7e-ba47-48ee-ba48-c92002d401b6)]
[scriptable, uuid(f072f334-e4ea-4754-9929-533da30444a8)]
interface nsIGonkTelephonyProvider : nsITelephonyProvider
{
void notifyCallDisconnected(in jsval call);
@ -27,5 +27,5 @@ interface nsIGonkTelephonyProvider : nsITelephonyProvider
void notifySupplementaryService(in long callIndex,
in AString notification);
void notifyConferenceCallStateChanged(in unsigned short state);
void notifyConferenceCallStateChanged(in short state);
};

View File

@ -58,12 +58,17 @@ function verifyInitialState() {
ok(telephony);
ok(conference);
checkState(null, [], '', []);
sendCmdToEmulator("gsm clear", function(result) {
log("Clear up calls from a previous test if any.");
is(result[0], "OK");
dial();
// No more calls in the list; give time for emulator to catch up.
waitFor(function next() {
checkState(null, [], '', []);
dial();
}, function isDone() {
return (telephony.calls.length == 0);
});
});
}
@ -200,6 +205,7 @@ function conferenceAddTwoCalls() {
let pending = ["conference.oncallschanged", "conference.onconnected",
"outgoingCall.onstatechange", "outgoingCall.ongroupchange",
"incomingCall.onstatechange", "incomingCall.ongroupchange"];
let nextTest = conferenceHold;
// We are expecting to receive conference.oncallschanged two times since
// two calls are added into conference.
@ -214,7 +220,7 @@ function conferenceAddTwoCalls() {
if (expected.length == 0) {
conference.oncallschanged = null;
receivedPending("conference.oncallschanged", pending, conferenceHold);
receivedPending("conference.oncallschanged", pending, nextTest);
}
};
@ -232,7 +238,7 @@ function conferenceAddTwoCalls() {
is(result[1], "inbound from " + inNumber + " : active");
is(result[2], "OK");
receivedPending("conference.onconnected", pending, conferenceHold);
receivedPending("conference.onconnected", pending, nextTest);
});
};
@ -243,7 +249,7 @@ function conferenceAddTwoCalls() {
ok(outgoingCall.group);
is(outgoingCall.group, conference);
receivedPending("outgoingCall.ongroupchange", pending, conferenceHold);
receivedPending("outgoingCall.ongroupchange", pending, nextTest);
};
outgoingCall.onstatechange = function(event) {
@ -253,7 +259,7 @@ function conferenceAddTwoCalls() {
ok(!outgoingCall.ongroupchange);
is(outgoingCall.state, conference.state);
receivedPending("outgoingCall.onstatechange", pending, conferenceHold);
receivedPending("outgoingCall.onstatechange", pending, nextTest);
};
incomingCall.ongroupchange = function(event) {
@ -263,7 +269,7 @@ function conferenceAddTwoCalls() {
ok(incomingCall.group);
is(incomingCall.group, conference);
receivedPending("incomingCall.ongroupchange", pending, conferenceHold);
receivedPending("incomingCall.ongroupchange", pending, nextTest);
};
incomingCall.onstatechange = function(event) {
@ -273,7 +279,7 @@ function conferenceAddTwoCalls() {
ok(!incomingCall.ongroupchange);
is(incomingCall.state, conference.state);
receivedPending("incomingCall.onstatechange", pending, conferenceHold);
receivedPending("incomingCall.onstatechange", pending, nextTest);
};
conference.add(outgoingCall, incomingCall);
@ -285,6 +291,7 @@ function conferenceHold() {
let pending = ["conference.onholding", "conference.onheld",
"outgoingCall.onholding", "outgoingCall.onheld",
"incomingCall.onholding", "incomingCall.onheld"];
let nextTest = conferenceResume;
conference.onholding = function(event) {
log("Received 'holding' event for the conference call.");
@ -292,7 +299,7 @@ function conferenceHold() {
is(conference.state, 'holding');
receivedPending("conference.onholding", pending, conferenceResume);
receivedPending("conference.onholding", pending, nextTest);
};
conference.onheld = function(event) {
@ -308,7 +315,7 @@ function conferenceHold() {
is(result[1], "inbound from " + inNumber + " : held");
is(result[2], "OK");
receivedPending("conference.onheld", pending, conferenceResume);
receivedPending("conference.onheld", pending, nextTest);
});
};
@ -318,7 +325,7 @@ function conferenceHold() {
is(outgoingCall.state, 'holding');
receivedPending("outgoingCall.onholding", pending, conferenceResume);
receivedPending("outgoingCall.onholding", pending, nextTest);
};
outgoingCall.onheld = function(event) {
@ -328,7 +335,7 @@ function conferenceHold() {
ok(!outgoingCall.onholding);
is(outgoingCall.state, 'held');
receivedPending("outgoingCall.onheld", pending, conferenceResume);
receivedPending("outgoingCall.onheld", pending, nextTest);
};
incomingCall.onholding = function(event) {
@ -337,7 +344,7 @@ function conferenceHold() {
is(incomingCall.state, 'holding');
receivedPending("incomingCall.onholding", pending, conferenceResume);
receivedPending("incomingCall.onholding", pending, nextTest);
};
incomingCall.onheld = function(event) {
@ -347,7 +354,7 @@ function conferenceHold() {
ok(!incomingCall.onholding);
is(incomingCall.state, 'held');
receivedPending("incomingCall.onheld", pending, conferenceResume);
receivedPending("incomingCall.onheld", pending, nextTest);
};
conference.hold();
@ -359,6 +366,7 @@ function conferenceResume() {
let pending = ["conference.onresuming", "conference.onconnected",
"outgoingCall.onresuming", "outgoingCall.onconnected",
"incomingCall.onresuming", "incomingCall.onconnected"];
let nextTest = simulate2ndIncoming;
conference.onresuming = function(event) {
log("Received 'resuming' event for the conference call.");
@ -366,7 +374,7 @@ function conferenceResume() {
is(conference.state, 'resuming');
receivedPending("conference.onresuming", pending, simulate2ndIncoming);
receivedPending("conference.onresuming", pending, nextTest);
};
conference.onconnected = function(event) {
@ -382,7 +390,7 @@ function conferenceResume() {
is(result[1], "inbound from " + inNumber + " : active");
is(result[2], "OK");
receivedPending("conference.onconnected", pending, simulate2ndIncoming);
receivedPending("conference.onconnected", pending, nextTest);
});
};
@ -392,7 +400,7 @@ function conferenceResume() {
is(outgoingCall.state, 'resuming');
receivedPending("outgoingCall.onresuming", pending, simulate2ndIncoming);
receivedPending("outgoingCall.onresuming", pending, nextTest);
};
outgoingCall.onconnected = function(event) {
@ -402,7 +410,7 @@ function conferenceResume() {
ok(!outgoingCall.onresuming);
is(outgoingCall.state, 'connected');
receivedPending("outgoingCall.onconnected", pending, simulate2ndIncoming);
receivedPending("outgoingCall.onconnected", pending, nextTest);
};
incomingCall.onresuming = function(event) {
@ -411,7 +419,7 @@ function conferenceResume() {
is(incomingCall.state, 'resuming');
receivedPending("incomingCall.onresuming", pending, simulate2ndIncoming);
receivedPending("incomingCall.onresuming", pending, nextTest);
};
incomingCall.onconnected = function(event) {
@ -421,7 +429,7 @@ function conferenceResume() {
ok(!incomingCall.onresuming);
is(incomingCall.state, 'connected');
receivedPending("incomingCall.onconnected", pending, simulate2ndIncoming);
receivedPending("incomingCall.onconnected", pending, nextTest);
};
conference.resume();
@ -496,6 +504,7 @@ function conferenceAddOneCall() {
let callToAdd = incomingCall2;
let pending = ["conference.oncallschanged", "conference.onconnected",
"callToAdd.ongroupchange", "callToAdd.onconnected"];
let nextTest = conferenceRemove;
ok(!callToAdd.group);
@ -507,7 +516,7 @@ function conferenceAddOneCall() {
is(conference.calls.length, 3);
is(conference.calls[2].number, event.call.number);
receivedPending("conference.oncallschanged", pending, conferenceRemove);
receivedPending("conference.oncallschanged", pending, nextTest);
};
conference.onconnected = function(event) {
@ -526,7 +535,7 @@ function conferenceAddOneCall() {
is(result[2], "inbound from " + inNumber2 + " : active");
is(result[3], "OK");
receivedPending("conference.onconnected", pending, conferenceRemove);
receivedPending("conference.onconnected", pending, nextTest);
});
};
@ -535,7 +544,7 @@ function conferenceAddOneCall() {
callToAdd.ongroupchange = null;
is(callToAdd.group, conference);
receivedPending("callToAdd.ongroupchange", pending, conferenceRemove);
receivedPending("callToAdd.ongroupchange", pending, nextTest);
};
callToAdd.onconnected = function(event) {
@ -545,7 +554,7 @@ function conferenceAddOneCall() {
ok(!callToAdd.ongroupchange);
is(callToAdd.state, 'connected');
receivedPending("callToAdd.onconnected", pending, conferenceRemove);
receivedPending("callToAdd.onconnected", pending, nextTest);
};
conference.add(callToAdd);
}
@ -560,6 +569,7 @@ function conferenceRemove() {
let callToRemove = conference.calls[0];
let pending = ["callToRemove.ongroupchange", "telephony.oncallschanged",
"conference.oncallschanged", "conference.onstatechange"];
let nextTest = emptyConference;
callToRemove.ongroupchange = function(event) {
log("Received 'groupchange' event for the call to remove.");
@ -568,7 +578,7 @@ function conferenceRemove() {
ok(!callToRemove.group);
is(callToRemove.state, 'connected');
receivedPending("callToRemove.ongroupchange", pending, cleanUp);
receivedPending("callToRemove.ongroupchange", pending, nextTest);
};
telephony.oncallschanged = function(event) {
@ -582,7 +592,7 @@ function conferenceRemove() {
is(telephony.calls.length, 1);
is(telephony.calls[0].number, event.call.number);
receivedPending("telephony.oncallschanged", pending, cleanUp);
receivedPending("telephony.oncallschanged", pending, nextTest);
}
};
@ -593,7 +603,7 @@ function conferenceRemove() {
is(event.call.number, callToRemove.number);
is(conference.calls.length, 2);
receivedPending("conference.oncallschanged", pending, cleanUp);
receivedPending("conference.oncallschanged", pending, nextTest);
};
conference.onstatechange = function(event) {
@ -612,13 +622,94 @@ function conferenceRemove() {
is(result[2], "inbound from " + inNumber2 + " : held");
is(result[3], "OK");
receivedPending("conference.onstatechange", pending, cleanUp);
receivedPending("conference.onstatechange", pending, nextTest);
});
};
conference.remove(callToRemove);
}
// We first release a call in telephony, then release a call in conference.
// The only call left in conference will be automatically moved from conference
// to the calls list of telephony.
function emptyConference() {
log("Release one call in conference.");
outgoingCall.ondisconnected = function(event) {
log("Received 'disconnected' event for the outgoing call.");
outgoingCall.ondisconnected = null;
checkState(null, [], 'held',
[incomingCall, incomingCall2]);
// We are going to release incomingCall. Once released, incomingCall2
// is going to be moved out of the conference call automatically.
sendCmdToEmulator("gsm cancel " + inNumber);
};
let pending = ["conference.oncallschanged", "conference.onstatechange",
"incomingCall2.ongroupchange"];
let nextTest = hangUpLastCall;
incomingCall2.ongroupchange = function(event) {
log("Received 'groupchange' event for the outgoing call.");
incomingCall2.ongroupchange = null;
ok(!incomingCall2.group);
is(incomingCall2.state, 'held');
receivedPending("incomingCall2.ongroupchange", pending, nextTest);
};
// We are expecting to receive conference.oncallschanged two times since
// two calls are removed from conference.
let expected = [incomingCall, incomingCall2];
conference.oncallschanged = function(event) {
log("Received 'callschanged' event for the conference call.");
let index = expected.indexOf(event.call);
ok(index != -1);
expected.splice(index, 1);
if (expected.length == 0) {
conference.oncallschanged = null;
is(conference.calls.length, 0);
receivedPending("conference.oncallschanged", pending, nextTest);
}
};
conference.onstatechange = function(event) {
log("Received 'statechange' event for the conference call.");
conference.onstatechange = null;
ok(!conference.oncallschanged);
checkState(null, [incomingCall2], '', []);
receivedPending("conference.onstatechange", pending, nextTest);
};
sendCmdToEmulator("gsm cancel " + outNumber);
}
function hangUpLastCall() {
log("Going to leave the test. Hanging up the last call.");
incomingCall2.ondisconnected = function(event) {
incomingCall2.ondisconnected = null;
checkState(null, [], '', []);
sendCmdToEmulator("gsm list", function(result) {
log("Call list is now: " + result);
is(result[0], "OK");
cleanUp();
});
};
sendCmdToEmulator("gsm cancel " + inNumber2);
}
function cleanUp() {
if (pendingEmulatorCmdCount) {
window.setTimeout(cleanUp, 100);

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {
@ -48,7 +48,7 @@ function dial() {
outgoingCall.onalerting = function onalerting(event) {
log("Received 'alerting' call event.");
answer();
};
};
}
function answer() {
@ -73,4 +73,4 @@ function cleanUp(){
finish();
}
getExistingCalls();
getExistingCalls();

View File

@ -32,7 +32,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -27,7 +27,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -26,7 +26,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -25,7 +25,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -25,7 +25,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -36,7 +36,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -24,7 +24,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -121,6 +121,11 @@ function cleanUp() {
setRadioEnabled(false, function() {
sendToEmulator("gsm clear", function(result) {
is(result[0], "OK");
dial("0912345678");
waitFor(function() {
dial("0912345678");
}, function() {
return telephony.calls.length === 0;
});
});
});

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -23,7 +23,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -28,7 +28,7 @@ function getExistingCalls() {
function cancelExistingCalls(callList) {
if (callList.length && callList[0] != "OK") {
// Existing calls remain; get rid of the next one in the list
nextCall = callList.shift().split(' ')[2].trim();
nextCall = callList.shift().split(/\s+/)[2].trim();
log("Cancelling existing call '" + nextCall +"'");
runEmulatorCmd("gsm cancel " + nextCall, function(result) {
if (result[0] == "OK") {

View File

@ -133,7 +133,10 @@ public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
delete gHalDiskSpaceWatcher;
if (gHalDiskSpaceWatcher) {
delete gHalDiskSpaceWatcher;
gHalDiskSpaceWatcher = nullptr;
}
return NS_OK;
}
};

View File

@ -885,7 +885,7 @@ DestroyAlarmData(void* aData)
// Runs on alarm-watcher thread.
void ShutDownAlarm(int aSigno)
{
if (aSigno == SIGUSR1) {
if (aSigno == SIGUSR1 && sAlarmData) {
sAlarmData->mShuttingDown = true;
}
return;

View File

@ -2672,17 +2672,6 @@ bool nsPresContext::GetPaintFlashing() const
return mPaintFlashing;
}
bool
nsPresContext::IsDeviceSizePageSize()
{
bool isDeviceSizePageSize = false;
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
if (docShell) {
isDeviceSizePageSize = docShell->GetDeviceSizeIsPageSize();
}
return isDeviceSizePageSize;
}
nsRootPresContext::nsRootPresContext(nsIDocument* aDocument,
nsPresContextType aType)
: nsPresContext(aDocument, aType),

View File

@ -1003,8 +1003,6 @@ public:
mExistThrottledUpdates = aExistThrottledUpdates;
}
bool IsDeviceSizePageSize();
protected:
friend class nsRunnableMethod<nsPresContext>;
NS_HIDDEN_(void) ThemeChangedInternal();

View File

@ -111,19 +111,14 @@ static nsSize
GetDeviceSize(nsPresContext* aPresContext)
{
nsSize size;
if (aPresContext->IsDeviceSizePageSize()) {
size = GetSize(aPresContext);
} else if (aPresContext->IsRootPaginatedDocument()) {
if (aPresContext->IsRootPaginatedDocument())
// We want the page size, including unprintable areas and margins.
// XXX The spec actually says we want the "page sheet size", but
// how is that different?
size = aPresContext->GetPageSize();
} else {
else
GetDeviceContextFor(aPresContext)->
GetDeviceSurfaceDimensions(size.width, size.height);
}
return size;
}

View File

@ -2257,7 +2257,7 @@ public class GeckoAppShell
sEventDispatcher.registerEventListener(event, listener);
}
static EventDispatcher getEventDispatcher() {
public static EventDispatcher getEventDispatcher() {
return sEventDispatcher;
}

View File

@ -220,14 +220,12 @@ FENNEC_JAVA_FILES = \
home/BookmarkThumbnailView.java \
home/BrowserSearch.java \
home/HistoryPage.java \
home/HomeCursorLoaderCallbacks.java \
home/HomeFragment.java \
home/HomeListView.java \
home/HomePager.java \
home/HomePagerTabStrip.java \
home/HomeBanner.java \
home/FadedTextView.java \
home/FaviconsLoader.java \
home/LastTabsPage.java \
home/MostRecentPage.java \
home/MostVisitedPage.java \

View File

@ -25,6 +25,7 @@ SYNC_JAVA_FILES := \
background/bagheera/BagheeraRequestDelegate.java \
background/bagheera/BoundedByteArrayEntity.java \
background/bagheera/DeflateHelper.java \
background/common/DateUtils.java \
background/common/log/Logger.java \
background/common/log/writers/AndroidLevelCachingLogWriter.java \
background/common/log/writers/AndroidLogWriter.java \

View File

@ -160,12 +160,17 @@ public class PropertyAnimator implements Runnable {
}
// Try to start animation after any on-going layout round
// in the current view tree.
if (treeObserver != null && treeObserver.isAlive()) {
// in the current view tree. OnPreDrawListener seems broken
// on pre-Honeycomb devices, start animation immediatelly
// in this case.
if (Build.VERSION.SDK_INT >= 11 && treeObserver != null && treeObserver.isAlive()) {
treeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
treeObserver.removeOnPreDrawListener(this);
if (treeObserver.isAlive()) {
treeObserver.removeOnPreDrawListener(this);
}
mFramePoster.postFirstAnimationFrame();
return true;
}

View File

@ -0,0 +1,43 @@
/* 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.background.common;
import java.util.Calendar;
import java.util.Formatter;
import java.util.TimeZone;
public class DateUtils {
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
public static final class DateFormatter {
private final Calendar calendar;
private final Formatter formatter;
private final StringBuilder builder;
public DateFormatter() {
this.calendar = Calendar.getInstance(UTC);
this.builder = new StringBuilder(); // So we can reset it.
this.formatter = new Formatter(this.builder, null);
}
public String getDateString(long time) {
calendar.setTimeInMillis(time);
builder.setLength(0);
return formatter.format("%04d-%02d-%02d",
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1, // 0-indexed.
calendar.get(Calendar.DAY_OF_MONTH))
.toString();
}
public String getDateStringForDay(long day) {
return getDateString(GlobalConstants.MILLISECONDS_PER_DAY * day);
}
}
public static int getDay(final long time) {
return (int) Math.floor(time / GlobalConstants.MILLISECONDS_PER_DAY);
}
}

View File

@ -47,4 +47,8 @@ public class GlobalConstants {
public static String GECKO_PREFERENCES_CLASS = "org.mozilla.gecko.GeckoPreferences";
public static String GECKO_BROADCAST_ANNOUNCEMENTS_PREF_METHOD = "broadcastAnnouncementsPref";
public static String GECKO_BROADCAST_HEALTHREPORT_UPLOAD_PREF_METHOD = "broadcastHealthReportUploadPref";
// Common time values.
public static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
public static final long MILLISECONDS_PER_SIX_MONTHS = 180 * MILLISECONDS_PER_DAY;
}

View File

@ -9,6 +9,7 @@ import java.util.Iterator;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.SysInfo;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.common.log.Logger;
import android.content.ContentProvider;
@ -77,7 +78,7 @@ public class EnvironmentBuilder {
e.sysName = SysInfo.getName();
e.sysVersion = SysInfo.getReleaseVersion();
e.profileCreation = (int) (info.getProfileCreationTime() / HealthReportConstants.MILLISECONDS_PER_DAY);
e.profileCreation = (int) (info.getProfileCreationTime() / GlobalConstants.MILLISECONDS_PER_DAY);
// Corresponds to Gecko pref "extensions.blocklist.enabled".
e.isBlocklistEnabled = (info.isBlocklistEnabled() ? 1 : 0);

View File

@ -5,6 +5,8 @@
package org.mozilla.gecko.background.healthreport;
import org.mozilla.gecko.background.common.GlobalConstants;
public class HealthReportConstants {
public static final String HEALTH_AUTHORITY = "@ANDROID_PACKAGE_NAME@.health";
public static final String GLOBAL_LOG_TAG = "GeckoHealth";
@ -15,9 +17,6 @@ public class HealthReportConstants {
*/
public static final long EARLIEST_LAST_PING = 1367500000000L;
public static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
public static final long MILLISECONDS_PER_SIX_MONTHS = 180 * MILLISECONDS_PER_DAY;
// Not `final` so we have the option to turn this on at runtime with a magic addon.
public static boolean UPLOAD_FEATURE_DISABLED = false;
@ -29,15 +28,15 @@ public class HealthReportConstants {
// intent is scheduled to be called by the Android Alarm Manager, not how
// frequently we actually submit.
public static final String PREF_SUBMISSION_INTENT_INTERVAL_MSEC = "healthreport_submission_intent_interval_msec";
public static final long DEFAULT_SUBMISSION_INTENT_INTERVAL_MSEC = MILLISECONDS_PER_DAY / 24;
public static final long DEFAULT_SUBMISSION_INTENT_INTERVAL_MSEC = GlobalConstants.MILLISECONDS_PER_DAY / 24;
public static final String ACTION_HEALTHREPORT_UPLOAD_PREF = "@ANDROID_PACKAGE_NAME@.HEALTHREPORT_UPLOAD_PREF";
public static final String PREF_MINIMUM_TIME_BETWEEN_UPLOADS = "healthreport_time_between_uploads";
public static final long DEFAULT_MINIMUM_TIME_BETWEEN_UPLOADS = MILLISECONDS_PER_DAY;
public static final long DEFAULT_MINIMUM_TIME_BETWEEN_UPLOADS = GlobalConstants.MILLISECONDS_PER_DAY;
public static final String PREF_MINIMUM_TIME_BEFORE_FIRST_SUBMISSION = "healthreport_time_before_first_submission";
public static final long DEFAULT_MINIMUM_TIME_BEFORE_FIRST_SUBMISSION = MILLISECONDS_PER_DAY;
public static final long DEFAULT_MINIMUM_TIME_BEFORE_FIRST_SUBMISSION = GlobalConstants.MILLISECONDS_PER_DAY;
public static final String PREF_MINIMUM_TIME_AFTER_FAILURE = "healthreport_time_after_failure";
public static final long DEFAULT_MINIMUM_TIME_AFTER_FAILURE = DEFAULT_SUBMISSION_INTENT_INTERVAL_MSEC;

View File

@ -12,6 +12,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.json.JSONObject;
import org.mozilla.gecko.background.common.DateUtils;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.HealthReportStorage.MeasurementFields.FieldSpec;
@ -1029,7 +1030,7 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
@Override
public int getDay(long time) {
return HealthReportUtils.getDay(time);
return DateUtils.getDay(time);
}
@Override

View File

@ -10,6 +10,7 @@ import java.util.Set;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.background.common.DateUtils.DateFormatter;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.HealthReportStorage.Field;
@ -22,9 +23,11 @@ public class HealthReportGenerator {
private static final String LOG_TAG = "GeckoHealthGen";
private final HealthReportStorage storage;
private final DateFormatter dateFormatter;
public HealthReportGenerator(HealthReportStorage storage) {
this.storage = storage;
this.dateFormatter = new DateFormatter();
}
@SuppressWarnings("static-method")
@ -76,10 +79,10 @@ public class HealthReportGenerator {
JSONObject document = new JSONObject();
if (lastPingTime >= HealthReportConstants.EARLIEST_LAST_PING) {
document.put("lastPingDate", HealthReportUtils.getDateString(lastPingTime));
document.put("lastPingDate", dateFormatter.getDateString(lastPingTime));
}
document.put("thisPingDate", HealthReportUtils.getDateString(now()));
document.put("thisPingDate", dateFormatter.getDateString(now()));
document.put("version", PAYLOAD_VERSION);
document.put("environments", getEnvironmentsJSON(currentEnvironment, envs));
@ -147,7 +150,7 @@ public class HealthReportGenerator {
if (dateChanged) {
if (dateObject != null) {
days.put(HealthReportUtils.getDateStringForDay(lastDate), dateObject);
days.put(dateFormatter.getDateStringForDay(lastDate), dateObject);
}
dateObject = new JSONObject();
lastDate = cDate;
@ -179,7 +182,7 @@ public class HealthReportGenerator {
cursor.moveToNext();
continue;
}
days.put(HealthReportUtils.getDateStringForDay(lastDate), dateObject);
days.put(dateFormatter.getDateStringForDay(lastDate), dateObject);
} finally {
cursor.close();
}

View File

@ -4,13 +4,10 @@
package org.mozilla.gecko.background.healthreport;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.UUID;
@ -25,24 +22,10 @@ import android.net.Uri;
public class HealthReportUtils {
public static final String LOG_TAG = HealthReportUtils.class.getSimpleName();
public static int getDay(final long time) {
return (int) Math.floor(time / HealthReportConstants.MILLISECONDS_PER_DAY);
}
public static String getEnvironmentHash(final String input) {
return DigestUtils.shaHex(input);
}
public static String getDateStringForDay(long day) {
return getDateString(HealthReportConstants.MILLISECONDS_PER_DAY * day);
}
public static String getDateString(long time) {
final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format.format(time);
}
/**
* Take an environment URI (one that identifies an environment) and produce an
* event URI.

View File

@ -10,6 +10,7 @@ import java.util.Collection;
import org.json.JSONObject;
import org.mozilla.gecko.background.bagheera.BagheeraClient;
import org.mozilla.gecko.background.bagheera.BagheeraRequestDelegate;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder;
import org.mozilla.gecko.background.healthreport.HealthReportConstants;
@ -103,7 +104,7 @@ public class AndroidSubmissionClient implements SubmissionClient {
return;
}
long since = localTime - HealthReportConstants.MILLISECONDS_PER_SIX_MONTHS;
long since = localTime - GlobalConstants.MILLISECONDS_PER_SIX_MONTHS;
long last = Math.max(getLastUploadLocalTime(), HealthReportConstants.EARLIEST_LAST_PING);
if (!storage.hasEventSince(last)) {

View File

@ -14,6 +14,7 @@ import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder;
import org.mozilla.gecko.background.common.GlobalConstants;
import org.mozilla.gecko.background.healthreport.HealthReportConstants;
import org.mozilla.gecko.background.healthreport.HealthReportDatabaseStorage;
import org.mozilla.gecko.background.healthreport.HealthReportGenerator;
@ -124,7 +125,7 @@ public class BrowserHealthReporter implements GeckoEventListener {
GeckoProfile profile = GeckoAppShell.getGeckoInterface().getProfile();
String profilePath = profile.getDir().getAbsolutePath();
long since = System.currentTimeMillis() - HealthReportConstants.MILLISECONDS_PER_SIX_MONTHS;
long since = System.currentTimeMillis() - GlobalConstants.MILLISECONDS_PER_SIX_MONTHS;
long lastPingTime = Math.max(getLastUploadLocalTime(), HealthReportConstants.EARLIEST_LAST_PING);
return generateReport(since, lastPingTime, profilePath);

View File

@ -179,7 +179,7 @@ public class BookmarksPage extends HomeFragment {
BrowserDB.invalidateCachedState();
// Create callbacks before the initial loader is started.
mLoaderCallbacks = new CursorLoaderCallbacks(activity, getLoaderManager());
mLoaderCallbacks = new CursorLoaderCallbacks();
mThumbnailsLoaderCallbacks = new ThumbnailsLoaderCallbacks();
loadIfVisible();
}
@ -453,11 +453,7 @@ public class BookmarksPage extends HomeFragment {
/**
* Loader callbacks for the LoaderManager of this fragment.
*/
private class CursorLoaderCallbacks extends HomeCursorLoaderCallbacks {
public CursorLoaderCallbacks(Context context, LoaderManager loaderManager) {
super(context, loaderManager);
}
private class CursorLoaderCallbacks implements LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch(id) {
@ -472,11 +468,9 @@ public class BookmarksPage extends HomeFragment {
case LOADER_ID_TOP_BOOKMARKS: {
return new TopBookmarksLoader(getActivity());
}
default: {
return super.onCreateLoader(id, args);
}
}
return null;
}
@Override
@ -485,7 +479,6 @@ public class BookmarksPage extends HomeFragment {
switch(loaderId) {
case LOADER_ID_BOOKMARKS_LIST: {
mListAdapter.swapCursor(c);
loadFavicons(c);
mList.setHeaderDividersEnabled(c != null && c.getCount() > 0);
break;
}
@ -509,11 +502,6 @@ public class BookmarksPage extends HomeFragment {
}
break;
}
default: {
super.onLoadFinished(loader, c);
break;
}
}
}
@ -534,18 +522,8 @@ public class BookmarksPage extends HomeFragment {
break;
}
}
default: {
super.onLoaderReset(loader);
break;
}
}
}
@Override
public void onFaviconsLoaded() {
mListAdapter.notifyDataSetChanged();
}
}
/**

Some files were not shown because too many files have changed in this diff Show More